@integrity-labs/agt-cli 0.27.150-test.15 → 0.27.151
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 +13 -6
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-24FTY53Z.js → chunk-EI2FRRGG.js} +141 -50
- package/dist/chunk-EI2FRRGG.js.map +1 -0
- package/dist/{chunk-WOOYOAPG.js → chunk-K5XUY6PS.js} +127 -1
- package/dist/chunk-K5XUY6PS.js.map +1 -0
- package/dist/{chunk-7GKJZBTB.js → chunk-UF6HY7TN.js} +209 -52
- package/dist/chunk-UF6HY7TN.js.map +1 -0
- package/dist/{claude-pair-runtime-GIUCD7IG.js → claude-pair-runtime-AYMNAIYY.js} +2 -2
- package/dist/lib/manager-worker.js +395 -164
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-35PWSTLO.js → persistent-session-CZQPV267.js} +3 -4
- package/dist/{responsiveness-probe-MA4M2QM4.js → responsiveness-probe-EW2ZLSZL.js} +3 -4
- package/dist/{responsiveness-probe-MA4M2QM4.js.map → responsiveness-probe-EW2ZLSZL.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-24FTY53Z.js.map +0 -1
- package/dist/chunk-354FAVQR.js +0 -173
- package/dist/chunk-354FAVQR.js.map +0 -1
- package/dist/chunk-7GKJZBTB.js.map +0 -1
- package/dist/chunk-WOOYOAPG.js.map +0 -1
- package/dist/daily-session-PNQX5URX.js +0 -27
- package/dist/persistent-session-35PWSTLO.js.map +0 -1
- /package/dist/{claude-pair-runtime-GIUCD7IG.js.map → claude-pair-runtime-AYMNAIYY.js.map} +0 -0
- /package/dist/{daily-session-PNQX5URX.js.map → persistent-session-CZQPV267.js.map} +0 -0
|
@@ -15,10 +15,11 @@ import {
|
|
|
15
15
|
provisionAutoKanbanProgressHook,
|
|
16
16
|
provisionIsolationHook,
|
|
17
17
|
provisionOrientHook,
|
|
18
|
+
provisionSessionStateHook,
|
|
18
19
|
provisionStopHook,
|
|
19
20
|
requireHost,
|
|
20
21
|
safeWriteJsonAtomic
|
|
21
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-EI2FRRGG.js";
|
|
22
23
|
import {
|
|
23
24
|
getProjectDir as getProjectDir2,
|
|
24
25
|
getReadyTasks,
|
|
@@ -37,10 +38,13 @@ import {
|
|
|
37
38
|
getSessionState,
|
|
38
39
|
injectMessage,
|
|
39
40
|
injectMessageWithStatus,
|
|
41
|
+
isAgentIdle,
|
|
40
42
|
isAgentPromptReady,
|
|
41
43
|
isSessionHealthy,
|
|
44
|
+
isStaleForToday,
|
|
42
45
|
paneLogPath,
|
|
43
46
|
parseEnvIntegrations,
|
|
47
|
+
peekCurrentSession,
|
|
44
48
|
prepareForRespawn,
|
|
45
49
|
probeMcpEnvSubstitution,
|
|
46
50
|
readPaneLogTail,
|
|
@@ -49,16 +53,19 @@ import {
|
|
|
49
53
|
rotateSessionForWedge,
|
|
50
54
|
sanitizeMcpJson,
|
|
51
55
|
sendToAgent,
|
|
56
|
+
sessionTranscriptDir,
|
|
52
57
|
startPersistentSession,
|
|
53
58
|
stopAllSessionsAndWait,
|
|
54
59
|
stopPersistentSession,
|
|
55
60
|
takeWatchdogGiveUpCount,
|
|
56
|
-
takeZombieDetection
|
|
57
|
-
|
|
61
|
+
takeZombieDetection,
|
|
62
|
+
transcriptActivityAgeSeconds
|
|
63
|
+
} from "../chunk-UF6HY7TN.js";
|
|
58
64
|
import {
|
|
59
65
|
KANBAN_CHECK_COMMAND,
|
|
60
66
|
MAX_AVATAR_ENV_URL_BYTES,
|
|
61
67
|
SUPPRESS_SENTINEL,
|
|
68
|
+
StreamEncoder,
|
|
62
69
|
appendDmFooter,
|
|
63
70
|
attributeTranscriptUsageByRun,
|
|
64
71
|
classifyActor,
|
|
@@ -83,13 +90,7 @@ import {
|
|
|
83
90
|
resolveDmTarget,
|
|
84
91
|
worseConnectivityOutcome,
|
|
85
92
|
wrapScheduledTaskPrompt
|
|
86
|
-
} from "../chunk-
|
|
87
|
-
import {
|
|
88
|
-
isAgentIdle,
|
|
89
|
-
isStaleForToday,
|
|
90
|
-
peekCurrentSession,
|
|
91
|
-
sessionTranscriptDir
|
|
92
|
-
} from "../chunk-354FAVQR.js";
|
|
93
|
+
} from "../chunk-K5XUY6PS.js";
|
|
93
94
|
import {
|
|
94
95
|
parsePsRows,
|
|
95
96
|
reapOrphanChannelMcps
|
|
@@ -100,8 +101,8 @@ import { createHash as createHash3 } from "crypto";
|
|
|
100
101
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, appendFileSync, mkdirSync as mkdirSync4, chmodSync, existsSync as existsSync5, rmSync as rmSync2, readdirSync as readdirSync4, statSync as statSync3, unlinkSync, copyFileSync } from "fs";
|
|
101
102
|
import https from "https";
|
|
102
103
|
import { execFileSync as syncExecFile } from "child_process";
|
|
103
|
-
import { join as
|
|
104
|
-
import { homedir as
|
|
104
|
+
import { join as join9, dirname as dirname3 } from "path";
|
|
105
|
+
import { homedir as homedir5 } from "os";
|
|
105
106
|
import { fileURLToPath } from "url";
|
|
106
107
|
|
|
107
108
|
// src/lib/mcp-config-drift.ts
|
|
@@ -1515,6 +1516,7 @@ function isUrgentUpgrade(opts) {
|
|
|
1515
1516
|
}
|
|
1516
1517
|
var RESTART_IDLE_THRESHOLD_SECONDS = 120;
|
|
1517
1518
|
var RESTART_INBOUND_QUIET_SECONDS = 300;
|
|
1519
|
+
var RESTART_TRANSCRIPT_STALE_SECONDS = 60;
|
|
1518
1520
|
var GATEABLE_RESTART_REASONS = /* @__PURE__ */ new Set([
|
|
1519
1521
|
"model-change",
|
|
1520
1522
|
"channel-set-change",
|
|
@@ -1533,9 +1535,11 @@ function decideRestartGate(opts) {
|
|
|
1533
1535
|
}
|
|
1534
1536
|
const paneThreshold = opts.idleThresholdSeconds ?? RESTART_IDLE_THRESHOLD_SECONDS;
|
|
1535
1537
|
const inboundThreshold = opts.inboundQuietSeconds ?? RESTART_INBOUND_QUIET_SECONDS;
|
|
1536
|
-
const
|
|
1538
|
+
const transcriptThreshold = opts.transcriptStaleSeconds ?? RESTART_TRANSCRIPT_STALE_SECONDS;
|
|
1539
|
+
const transcriptAge = opts.transcriptAgeSeconds ?? null;
|
|
1540
|
+
const progressBusy = transcriptAge !== null ? transcriptAge < transcriptThreshold : opts.paneLogAgeSeconds !== null && opts.paneLogAgeSeconds < paneThreshold;
|
|
1537
1541
|
const inboundBusy = opts.inboundAgeSeconds !== null && opts.inboundAgeSeconds < inboundThreshold;
|
|
1538
|
-
if (
|
|
1542
|
+
if (progressBusy || inboundBusy) return "defer-idle";
|
|
1539
1543
|
return "proceed";
|
|
1540
1544
|
}
|
|
1541
1545
|
|
|
@@ -1682,6 +1686,148 @@ var DirectChatSpawnGate = class {
|
|
|
1682
1686
|
}
|
|
1683
1687
|
};
|
|
1684
1688
|
|
|
1689
|
+
// src/lib/artifact-stream.ts
|
|
1690
|
+
import { join as join2 } from "path";
|
|
1691
|
+
import { homedir } from "os";
|
|
1692
|
+
import { readdir, stat, readFile } from "fs/promises";
|
|
1693
|
+
var ARTIFACT_STREAM_ENV = "AUGMENTED_ARTIFACT_STREAM_ENABLED";
|
|
1694
|
+
var ARTEFACT_ENTRY_FILE = "index.html";
|
|
1695
|
+
function isArtifactStreamingEnabled(env = process.env) {
|
|
1696
|
+
const v = env[ARTIFACT_STREAM_ENV];
|
|
1697
|
+
return v === "true" || v === "1";
|
|
1698
|
+
}
|
|
1699
|
+
function errMessage(err) {
|
|
1700
|
+
return err instanceof Error ? err.message : String(err);
|
|
1701
|
+
}
|
|
1702
|
+
var ArtifactStreamSession = class {
|
|
1703
|
+
constructor(agentId, clientToken, deps, meta = {}) {
|
|
1704
|
+
this.agentId = agentId;
|
|
1705
|
+
this.clientToken = clientToken;
|
|
1706
|
+
this.deps = deps;
|
|
1707
|
+
this.meta = meta;
|
|
1708
|
+
this.encoder = new StreamEncoder(deps.now ? { now: deps.now } : {});
|
|
1709
|
+
}
|
|
1710
|
+
encoder;
|
|
1711
|
+
draftId = null;
|
|
1712
|
+
creating = null;
|
|
1713
|
+
/** The draft id once created, else null. */
|
|
1714
|
+
get id() {
|
|
1715
|
+
return this.draftId;
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1718
|
+
* Create the draft on first use (idempotent via client_token — a manager
|
|
1719
|
+
* restart returns the same draft). Concurrent callers share one in-flight
|
|
1720
|
+
* request. Returns null on failure (best-effort; the next snapshot retries).
|
|
1721
|
+
*/
|
|
1722
|
+
async ensureDraft() {
|
|
1723
|
+
if (this.draftId) return this.draftId;
|
|
1724
|
+
if (!this.creating) {
|
|
1725
|
+
this.creating = this.deps.api.post("/host/artifacts/draft", {
|
|
1726
|
+
agent_id: this.agentId,
|
|
1727
|
+
client_token: this.clientToken,
|
|
1728
|
+
kind: this.meta.kind ?? "other",
|
|
1729
|
+
...this.meta.title ? { title: this.meta.title } : {}
|
|
1730
|
+
}).then((res) => {
|
|
1731
|
+
this.draftId = res?.id ?? null;
|
|
1732
|
+
return this.draftId;
|
|
1733
|
+
}).catch((err) => {
|
|
1734
|
+
this.deps.log?.(`[artifact-stream] draft create failed (${this.clientToken}): ${errMessage(err)}`);
|
|
1735
|
+
return null;
|
|
1736
|
+
}).finally(() => {
|
|
1737
|
+
this.creating = null;
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
return this.creating;
|
|
1741
|
+
}
|
|
1742
|
+
/** Encode one snapshot and relay its frame(s). Best-effort, never throws. */
|
|
1743
|
+
async pushSnapshot(content) {
|
|
1744
|
+
const id = await this.ensureDraft();
|
|
1745
|
+
if (!id) return;
|
|
1746
|
+
const frames = this.encoder.encode(content);
|
|
1747
|
+
for (const frame of frames) {
|
|
1748
|
+
try {
|
|
1749
|
+
await this.deps.api.post(`/host/artifacts/${encodeURIComponent(id)}/stream`, {
|
|
1750
|
+
agent_id: this.agentId,
|
|
1751
|
+
frame
|
|
1752
|
+
});
|
|
1753
|
+
} catch (err) {
|
|
1754
|
+
this.deps.log?.(`[artifact-stream] frame ${frame.seq} failed (${id}): ${errMessage(err)}`);
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
};
|
|
1759
|
+
var ArtifactStreamScanner = class {
|
|
1760
|
+
constructor(agentId, artifactsDir, fsDeps, deps) {
|
|
1761
|
+
this.agentId = agentId;
|
|
1762
|
+
this.artifactsDir = artifactsDir;
|
|
1763
|
+
this.fsDeps = fsDeps;
|
|
1764
|
+
this.deps = deps;
|
|
1765
|
+
}
|
|
1766
|
+
sessions = /* @__PURE__ */ new Map();
|
|
1767
|
+
seenMtime = /* @__PURE__ */ new Map();
|
|
1768
|
+
scanning = false;
|
|
1769
|
+
/** One scan pass. Reads + streams every changed artefact. Never throws. */
|
|
1770
|
+
async scanOnce() {
|
|
1771
|
+
if (this.scanning) return;
|
|
1772
|
+
this.scanning = true;
|
|
1773
|
+
try {
|
|
1774
|
+
let names;
|
|
1775
|
+
try {
|
|
1776
|
+
names = await this.fsDeps.listArtefactNames(this.artifactsDir);
|
|
1777
|
+
} catch {
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
for (const name of names) {
|
|
1781
|
+
const file = join2(this.artifactsDir, name, ARTEFACT_ENTRY_FILE);
|
|
1782
|
+
const mtime = await this.fsDeps.mtimeMs(file).catch(() => null);
|
|
1783
|
+
if (mtime === null) continue;
|
|
1784
|
+
if (this.seenMtime.get(name) === mtime) continue;
|
|
1785
|
+
let content;
|
|
1786
|
+
try {
|
|
1787
|
+
content = await this.fsDeps.readFile(file);
|
|
1788
|
+
} catch (err) {
|
|
1789
|
+
this.deps.log?.(`[artifact-stream] read failed (${name}): ${errMessage(err)}`);
|
|
1790
|
+
continue;
|
|
1791
|
+
}
|
|
1792
|
+
this.seenMtime.set(name, mtime);
|
|
1793
|
+
await this.sessionFor(name).pushSnapshot(content);
|
|
1794
|
+
}
|
|
1795
|
+
const live = new Set(names);
|
|
1796
|
+
for (const key of this.seenMtime.keys()) if (!live.has(key)) this.seenMtime.delete(key);
|
|
1797
|
+
for (const key of this.sessions.keys()) if (!live.has(key)) this.sessions.delete(key);
|
|
1798
|
+
} finally {
|
|
1799
|
+
this.scanning = false;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
sessionFor(name) {
|
|
1803
|
+
let session = this.sessions.get(name);
|
|
1804
|
+
if (!session) {
|
|
1805
|
+
session = new ArtifactStreamSession(this.agentId, name, this.deps, { title: name });
|
|
1806
|
+
this.sessions.set(name, session);
|
|
1807
|
+
}
|
|
1808
|
+
return session;
|
|
1809
|
+
}
|
|
1810
|
+
};
|
|
1811
|
+
function artifactsDirFor(codeName) {
|
|
1812
|
+
return join2(homedir(), ".augmented", codeName, "artifacts");
|
|
1813
|
+
}
|
|
1814
|
+
var nodeArtifactFs = {
|
|
1815
|
+
async listArtefactNames(artifactsDir) {
|
|
1816
|
+
const entries = await readdir(artifactsDir, { withFileTypes: true });
|
|
1817
|
+
return entries.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
|
|
1818
|
+
},
|
|
1819
|
+
async mtimeMs(filePath) {
|
|
1820
|
+
try {
|
|
1821
|
+
return (await stat(filePath)).mtimeMs;
|
|
1822
|
+
} catch {
|
|
1823
|
+
return null;
|
|
1824
|
+
}
|
|
1825
|
+
},
|
|
1826
|
+
readFile(filePath) {
|
|
1827
|
+
return readFile(filePath, "utf8");
|
|
1828
|
+
}
|
|
1829
|
+
};
|
|
1830
|
+
|
|
1685
1831
|
// src/lib/usage-banner-monitor.ts
|
|
1686
1832
|
var MIN_CHECK_INTERVAL_MS = 6e4;
|
|
1687
1833
|
var PANE_TAIL_LINES_FOR_BANNER = 200;
|
|
@@ -1739,7 +1885,7 @@ async function maybeReportUsageBanner(args) {
|
|
|
1739
1885
|
|
|
1740
1886
|
// src/lib/token-usage-monitor.ts
|
|
1741
1887
|
import { readdirSync, readFileSync as readFileSync4, statSync } from "fs";
|
|
1742
|
-
import { join as
|
|
1888
|
+
import { join as join3 } from "path";
|
|
1743
1889
|
var MIN_CHECK_INTERVAL_MS2 = 6e4;
|
|
1744
1890
|
var TRANSCRIPT_MTIME_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
1745
1891
|
var MAX_ENTRIES_PER_POST = 200;
|
|
@@ -1768,7 +1914,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
1768
1914
|
if (!name.endsWith(".jsonl")) continue;
|
|
1769
1915
|
const sessionId = name.slice(0, -".jsonl".length);
|
|
1770
1916
|
if (!sessionId) continue;
|
|
1771
|
-
const path =
|
|
1917
|
+
const path = join3(dir, name);
|
|
1772
1918
|
let st;
|
|
1773
1919
|
try {
|
|
1774
1920
|
st = statSync(path);
|
|
@@ -1866,7 +2012,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
1866
2012
|
|
|
1867
2013
|
// src/lib/conversation-evaluator.ts
|
|
1868
2014
|
import { readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
1869
|
-
import { join as
|
|
2015
|
+
import { join as join4 } from "path";
|
|
1870
2016
|
var MIN_CHECK_INTERVAL_MS3 = 5 * 6e4;
|
|
1871
2017
|
var TRANSCRIPT_MTIME_WINDOW_MS2 = 3 * 24 * 60 * 60 * 1e3;
|
|
1872
2018
|
var WINDOW_PAD_MS = 5 * 6e4;
|
|
@@ -2103,7 +2249,7 @@ function readRecentTurns(dir, nowMs) {
|
|
|
2103
2249
|
const turns = [];
|
|
2104
2250
|
for (const name of entries) {
|
|
2105
2251
|
if (!name.endsWith(".jsonl")) continue;
|
|
2106
|
-
const full =
|
|
2252
|
+
const full = join4(dir, name);
|
|
2107
2253
|
let mtimeMs;
|
|
2108
2254
|
try {
|
|
2109
2255
|
mtimeMs = statSync2(full).mtimeMs;
|
|
@@ -2283,10 +2429,10 @@ async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
|
|
|
2283
2429
|
|
|
2284
2430
|
// src/lib/activity-cache-monitor.ts
|
|
2285
2431
|
import { existsSync as existsSync2, readFileSync as readFileSync6 } from "fs";
|
|
2286
|
-
import { homedir } from "os";
|
|
2287
|
-
import { join as
|
|
2432
|
+
import { homedir as homedir2 } from "os";
|
|
2433
|
+
import { join as join5 } from "path";
|
|
2288
2434
|
var MIN_CHECK_INTERVAL_MS5 = 6e4;
|
|
2289
|
-
var STATS_CACHE_PATH =
|
|
2435
|
+
var STATS_CACHE_PATH = join5(homedir2(), ".claude", "stats-cache.json");
|
|
2290
2436
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
2291
2437
|
var state5 = { lastObservedDate: null, lastCheckedAt: 0 };
|
|
2292
2438
|
function selectNewDailyRows(raw, lastObservedDate) {
|
|
@@ -2782,9 +2928,9 @@ var GatewayClientPool = class extends EventEmitter {
|
|
|
2782
2928
|
};
|
|
2783
2929
|
|
|
2784
2930
|
// src/lib/claude-auth-detect.ts
|
|
2785
|
-
import { readFile, readdir } from "fs/promises";
|
|
2786
|
-
import { homedir as
|
|
2787
|
-
import { join as
|
|
2931
|
+
import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
|
|
2932
|
+
import { homedir as homedir3, platform } from "os";
|
|
2933
|
+
import { join as join6 } from "path";
|
|
2788
2934
|
import { execFile as execFile2 } from "child_process";
|
|
2789
2935
|
import { promisify } from "util";
|
|
2790
2936
|
var execFileAsync = promisify(execFile2);
|
|
@@ -2799,17 +2945,17 @@ async function detectClaudeAuth() {
|
|
|
2799
2945
|
}
|
|
2800
2946
|
async function findClaudeCredentialsPaths() {
|
|
2801
2947
|
const candidates = [
|
|
2802
|
-
|
|
2803
|
-
|
|
2948
|
+
join6(homedir3(), ".claude", ".credentials.json"),
|
|
2949
|
+
join6(homedir3(), ".claude", "credentials.json")
|
|
2804
2950
|
];
|
|
2805
2951
|
const isLinuxRoot = platform() === "linux" && typeof process.getuid === "function" && process.getuid() === 0;
|
|
2806
2952
|
if (isLinuxRoot) {
|
|
2807
2953
|
try {
|
|
2808
|
-
const entries = await
|
|
2954
|
+
const entries = await readdir2("/home", { withFileTypes: true });
|
|
2809
2955
|
for (const entry of entries) {
|
|
2810
2956
|
if (!entry.isDirectory()) continue;
|
|
2811
|
-
candidates.push(
|
|
2812
|
-
candidates.push(
|
|
2957
|
+
candidates.push(join6("/home", entry.name, ".claude", ".credentials.json"));
|
|
2958
|
+
candidates.push(join6("/home", entry.name, ".claude", "credentials.json"));
|
|
2813
2959
|
}
|
|
2814
2960
|
} catch {
|
|
2815
2961
|
}
|
|
@@ -2845,7 +2991,7 @@ async function readMacKeychain() {
|
|
|
2845
2991
|
}
|
|
2846
2992
|
async function readJsonSilently(path) {
|
|
2847
2993
|
try {
|
|
2848
|
-
const raw = await
|
|
2994
|
+
const raw = await readFile2(path, "utf-8");
|
|
2849
2995
|
return JSON.parse(raw);
|
|
2850
2996
|
} catch {
|
|
2851
2997
|
return null;
|
|
@@ -2902,10 +3048,10 @@ function normalize(value) {
|
|
|
2902
3048
|
|
|
2903
3049
|
// src/lib/channel-hash-cache.ts
|
|
2904
3050
|
import { existsSync as existsSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync2 } from "fs";
|
|
2905
|
-
import { join as
|
|
3051
|
+
import { join as join7 } from "path";
|
|
2906
3052
|
var CACHE_FILENAME = "channel-hash-cache.json";
|
|
2907
3053
|
function getChannelHashCacheFile(configDir) {
|
|
2908
|
-
return
|
|
3054
|
+
return join7(configDir, CACHE_FILENAME);
|
|
2909
3055
|
}
|
|
2910
3056
|
function loadChannelHashCache(target, configDir) {
|
|
2911
3057
|
const path = getChannelHashCacheFile(configDir);
|
|
@@ -3377,13 +3523,18 @@ function clearAgentState(agentId, codeName) {
|
|
|
3377
3523
|
// src/lib/wedge-detection.ts
|
|
3378
3524
|
var DEFAULTS = {
|
|
3379
3525
|
inboundWaitSeconds: 120,
|
|
3380
|
-
// ENG-
|
|
3381
|
-
//
|
|
3382
|
-
//
|
|
3383
|
-
//
|
|
3384
|
-
//
|
|
3385
|
-
//
|
|
3386
|
-
|
|
3526
|
+
// ENG-6264: DISABLED by default (0). A session that's actively producing
|
|
3527
|
+
// tokens is never force-respawned — a working agent must not be killed just
|
|
3528
|
+
// because a message has been queued behind its turn, no matter how long.
|
|
3529
|
+
// ENG-6238 made this an absolute backstop (1200s) to still catch a
|
|
3530
|
+
// producing-but-never-draining runaway loop, but that re-introduced the exact
|
|
3531
|
+
// failure we set out to kill: cutting off real work on a long turn. Runaway
|
|
3532
|
+
// token burn is owned by the cost guardrail (ENG-5556); a producing-but-silent
|
|
3533
|
+
// loop still trips the synthetic-probe alarm. So the backstop is now opt-in:
|
|
3534
|
+
// set AGT_WEDGE_INBOUND_HARD_WAIT_SECONDS to a positive value to re-enable it
|
|
3535
|
+
// (floored at inboundWaitSeconds). 0 = the frozen/hung wedge (transcript
|
|
3536
|
+
// static) is still caught by the soft path; only the *producing* path is spared.
|
|
3537
|
+
inboundHardWaitSeconds: 0,
|
|
3387
3538
|
paneStaleSeconds: 120,
|
|
3388
3539
|
transcriptStaleSeconds: 60,
|
|
3389
3540
|
minCycles: 3
|
|
@@ -3402,10 +3553,12 @@ function resolveWedgeConfig(env = process.env) {
|
|
|
3402
3553
|
DEFAULTS.inboundWaitSeconds,
|
|
3403
3554
|
30
|
|
3404
3555
|
);
|
|
3405
|
-
const
|
|
3406
|
-
|
|
3407
|
-
|
|
3556
|
+
const inboundHardWaitRaw = parsePositiveInt(
|
|
3557
|
+
env.AGT_WEDGE_INBOUND_HARD_WAIT_SECONDS,
|
|
3558
|
+
DEFAULTS.inboundHardWaitSeconds,
|
|
3559
|
+
0
|
|
3408
3560
|
);
|
|
3561
|
+
const inboundHardWaitSeconds = inboundHardWaitRaw <= 0 ? 0 : Math.max(inboundWaitSeconds, inboundHardWaitRaw);
|
|
3409
3562
|
return {
|
|
3410
3563
|
mode: parseMode(env.AGT_WEDGE_RESTART_MODE),
|
|
3411
3564
|
inboundWaitSeconds,
|
|
@@ -3430,6 +3583,7 @@ function isWedgeCandidateCycle(signals, config2) {
|
|
|
3430
3583
|
if (inboundAge === null) return false;
|
|
3431
3584
|
if (inboundAge < config2.inboundWaitSeconds) return false;
|
|
3432
3585
|
if (isSessionProducing(signals, config2)) {
|
|
3586
|
+
if (config2.inboundHardWaitSeconds <= 0) return false;
|
|
3433
3587
|
return inboundAge >= config2.inboundHardWaitSeconds;
|
|
3434
3588
|
}
|
|
3435
3589
|
return true;
|
|
@@ -3498,14 +3652,14 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
3498
3652
|
|
|
3499
3653
|
// src/lib/restart-flags.ts
|
|
3500
3654
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync8, renameSync as renameSync2, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
3501
|
-
import { homedir as
|
|
3502
|
-
import { join as
|
|
3655
|
+
import { homedir as homedir4 } from "os";
|
|
3656
|
+
import { join as join8 } from "path";
|
|
3503
3657
|
import { randomUUID } from "crypto";
|
|
3504
3658
|
function restartFlagsDir() {
|
|
3505
|
-
return
|
|
3659
|
+
return join8(homedir4(), ".augmented", "restart-flags");
|
|
3506
3660
|
}
|
|
3507
3661
|
function flagPath(codeName) {
|
|
3508
|
-
return
|
|
3662
|
+
return join8(restartFlagsDir(), `${codeName}.flag`);
|
|
3509
3663
|
}
|
|
3510
3664
|
function readRestartFlags() {
|
|
3511
3665
|
const dir = restartFlagsDir();
|
|
@@ -3514,7 +3668,7 @@ function readRestartFlags() {
|
|
|
3514
3668
|
for (const entry of readdirSync3(dir)) {
|
|
3515
3669
|
if (!entry.endsWith(".flag")) continue;
|
|
3516
3670
|
try {
|
|
3517
|
-
const raw = readFileSync8(
|
|
3671
|
+
const raw = readFileSync8(join8(dir, entry), "utf8");
|
|
3518
3672
|
const parsed = JSON.parse(raw);
|
|
3519
3673
|
if (typeof parsed.codeName !== "string" || parsed.codeName.length === 0) {
|
|
3520
3674
|
parsed.codeName = entry.replace(/\.flag$/, "");
|
|
@@ -4062,8 +4216,8 @@ function applyRestartAcks(args) {
|
|
|
4062
4216
|
var GATEWAY_PORT_BASE = 18800;
|
|
4063
4217
|
var GATEWAY_PORT_STEP = 10;
|
|
4064
4218
|
var GATEWAY_PORT_MAX = 18899;
|
|
4065
|
-
var AUGMENTED_DIR =
|
|
4066
|
-
var GATEWAY_PORTS_FILE =
|
|
4219
|
+
var AUGMENTED_DIR = join9(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
4220
|
+
var GATEWAY_PORTS_FILE = join9(AUGMENTED_DIR, "gateway-ports.json");
|
|
4067
4221
|
var CHANNEL_SWEEP_INTERVAL_MS = (() => {
|
|
4068
4222
|
const raw = parseInt(process.env["AGT_CHANNEL_SWEEP_INTERVAL_MS"] ?? "", 10);
|
|
4069
4223
|
if (!Number.isFinite(raw)) return 5 * 60 * 1e3;
|
|
@@ -4417,11 +4571,16 @@ function paneLogAgeSecondsFor(codeName) {
|
|
|
4417
4571
|
return 0;
|
|
4418
4572
|
}
|
|
4419
4573
|
}
|
|
4420
|
-
function
|
|
4421
|
-
|
|
4574
|
+
function transcriptAgeSecondsFor(codeName) {
|
|
4575
|
+
const sessionId = getSessionState(codeName)?.currentSessionId ?? null;
|
|
4576
|
+
return transcriptActivityAgeSeconds(getProjectDir2(codeName), sessionId, /* @__PURE__ */ new Date());
|
|
4577
|
+
}
|
|
4578
|
+
function restartGateFor(codeName, reason) {
|
|
4579
|
+
if (!isGateableRestartReason(reason)) return "bypass";
|
|
4422
4580
|
return decideRestartGate({
|
|
4423
4581
|
window: cachedMaintenanceWindow,
|
|
4424
4582
|
paneLogAgeSeconds: paneLogAgeSecondsFor(codeName),
|
|
4583
|
+
transcriptAgeSeconds: transcriptAgeSecondsFor(codeName),
|
|
4425
4584
|
inboundAgeSeconds: inboundAgeSecondsFor(codeName),
|
|
4426
4585
|
now: /* @__PURE__ */ new Date()
|
|
4427
4586
|
});
|
|
@@ -4431,7 +4590,7 @@ var runningMcpServerKeys = /* @__PURE__ */ new Map();
|
|
|
4431
4590
|
var runningChannelSecretHashes = /* @__PURE__ */ new Map();
|
|
4432
4591
|
function projectMcpHash(_codeName, projectDir) {
|
|
4433
4592
|
try {
|
|
4434
|
-
const raw = readFileSync9(
|
|
4593
|
+
const raw = readFileSync9(join9(projectDir, ".mcp.json"), "utf-8");
|
|
4435
4594
|
return createHash3("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
|
|
4436
4595
|
} catch {
|
|
4437
4596
|
return null;
|
|
@@ -4439,7 +4598,7 @@ function projectMcpHash(_codeName, projectDir) {
|
|
|
4439
4598
|
}
|
|
4440
4599
|
function projectMcpKeys(_codeName, projectDir) {
|
|
4441
4600
|
try {
|
|
4442
|
-
const raw = readFileSync9(
|
|
4601
|
+
const raw = readFileSync9(join9(projectDir, ".mcp.json"), "utf-8");
|
|
4443
4602
|
const parsed = JSON.parse(raw);
|
|
4444
4603
|
const servers = parsed.mcpServers;
|
|
4445
4604
|
if (!servers || typeof servers !== "object") return /* @__PURE__ */ new Set();
|
|
@@ -4450,7 +4609,7 @@ function projectMcpKeys(_codeName, projectDir) {
|
|
|
4450
4609
|
}
|
|
4451
4610
|
function readMcpHttpServerConfig(projectDir, serverKey, env) {
|
|
4452
4611
|
try {
|
|
4453
|
-
const raw = readFileSync9(
|
|
4612
|
+
const raw = readFileSync9(join9(projectDir, ".mcp.json"), "utf-8");
|
|
4454
4613
|
const servers = JSON.parse(raw).mcpServers ?? {};
|
|
4455
4614
|
const entry = servers[serverKey];
|
|
4456
4615
|
if (entry && typeof entry.url === "string" && (entry.type === "http" || entry.type === void 0)) {
|
|
@@ -4478,7 +4637,7 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
|
|
|
4478
4637
|
if (integrations.length === 0) return;
|
|
4479
4638
|
const probeEnv = { ...process.env };
|
|
4480
4639
|
try {
|
|
4481
|
-
const envIntPath =
|
|
4640
|
+
const envIntPath = join9(projectDir, ".env.integrations");
|
|
4482
4641
|
if (existsSync5(envIntPath)) {
|
|
4483
4642
|
Object.assign(probeEnv, parseEnvIntegrations(readFileSync9(envIntPath, "utf-8")));
|
|
4484
4643
|
}
|
|
@@ -4580,10 +4739,10 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
|
|
|
4580
4739
|
);
|
|
4581
4740
|
}
|
|
4582
4741
|
}
|
|
4583
|
-
function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason) {
|
|
4584
|
-
const gate = restartGateFor(codeName,
|
|
4742
|
+
function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gateReason = breakerReason) {
|
|
4743
|
+
const gate = restartGateFor(codeName, gateReason);
|
|
4585
4744
|
if (gate !== "bypass" && gate !== "proceed") {
|
|
4586
|
-
log(`[maintenance-window] Deferring '${
|
|
4745
|
+
log(`[maintenance-window] Deferring '${gateReason}' restart for '${codeName}' (${gate})`);
|
|
4587
4746
|
return;
|
|
4588
4747
|
}
|
|
4589
4748
|
cancelPendingSessionRestart(codeName);
|
|
@@ -4668,7 +4827,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
4668
4827
|
function projectChannelSecretHash(projectDir) {
|
|
4669
4828
|
try {
|
|
4670
4829
|
const entries = parseEnvIntegrations(
|
|
4671
|
-
readFileSync9(
|
|
4830
|
+
readFileSync9(join9(projectDir, ".env.integrations"), "utf-8")
|
|
4672
4831
|
);
|
|
4673
4832
|
return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
|
|
4674
4833
|
} catch {
|
|
@@ -4760,7 +4919,7 @@ var cachedMaintenanceWindow = null;
|
|
|
4760
4919
|
var lastVersionCheckAt = 0;
|
|
4761
4920
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
4762
4921
|
var lastResponsivenessProbeAt = 0;
|
|
4763
|
-
var agtCliVersion = true ? "0.27.
|
|
4922
|
+
var agtCliVersion = true ? "0.27.151" : "dev";
|
|
4764
4923
|
function resolveBrewPath(execFileSync4) {
|
|
4765
4924
|
try {
|
|
4766
4925
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -5011,7 +5170,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
5011
5170
|
var CLAUDE_CODE_UPGRADE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
5012
5171
|
var claudeCodeUpgradeInFlight = false;
|
|
5013
5172
|
function claudeCodeUpgradeMarkerPath() {
|
|
5014
|
-
return
|
|
5173
|
+
return join9(homedir5(), ".augmented", ".last-claude-code-upgrade-check");
|
|
5015
5174
|
}
|
|
5016
5175
|
function stampClaudeCodeUpgradeMarker() {
|
|
5017
5176
|
try {
|
|
@@ -5074,7 +5233,7 @@ ${r.stderr}`;
|
|
|
5074
5233
|
}
|
|
5075
5234
|
var UPDATE_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
5076
5235
|
function selfUpdateAppliedMarkerPath() {
|
|
5077
|
-
return
|
|
5236
|
+
return join9(homedir5(), ".augmented", ".last-self-update-applied");
|
|
5078
5237
|
}
|
|
5079
5238
|
var selfUpdateUpToDateLogged = false;
|
|
5080
5239
|
var restartAfterUpgrade = false;
|
|
@@ -5097,7 +5256,7 @@ async function checkAndUpdateCli() {
|
|
|
5097
5256
|
const isNpmGlobal = !isBrewFormula && resolvedPath.includes("node_modules");
|
|
5098
5257
|
if (!isBrewFormula && !isNpmGlobal) return;
|
|
5099
5258
|
const { readFileSync: readF, writeFileSync: writeF } = await import("fs");
|
|
5100
|
-
const markerPath =
|
|
5259
|
+
const markerPath = join9(homedir5(), ".augmented", ".last-update-check");
|
|
5101
5260
|
try {
|
|
5102
5261
|
const lastCheck = parseInt(readF(markerPath, "utf-8").trim(), 10);
|
|
5103
5262
|
if (Date.now() - lastCheck < UPDATE_CHECK_INTERVAL_MS) return;
|
|
@@ -5354,9 +5513,9 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
5354
5513
|
throw new Error("claude_auth_mode=api_key but /host/exchange returned no decrypted key");
|
|
5355
5514
|
}
|
|
5356
5515
|
childEnv.ANTHROPIC_API_KEY = exchange.anthropicApiKey;
|
|
5357
|
-
const claudeDir =
|
|
5516
|
+
const claudeDir = join9(homedir5(), ".claude");
|
|
5358
5517
|
for (const filename of [".credentials.json", "credentials.json"]) {
|
|
5359
|
-
const p =
|
|
5518
|
+
const p = join9(claudeDir, filename);
|
|
5360
5519
|
if (existsSync5(p)) {
|
|
5361
5520
|
try {
|
|
5362
5521
|
rmSync2(p, { force: true });
|
|
@@ -5372,12 +5531,12 @@ async function applyClaudeAuthToEnv(childEnv, label) {
|
|
|
5372
5531
|
var evalEmptyMcpConfigPath = null;
|
|
5373
5532
|
function ensureEvalEmptyMcpConfig() {
|
|
5374
5533
|
if (evalEmptyMcpConfigPath && existsSync5(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
|
|
5375
|
-
const dir =
|
|
5534
|
+
const dir = join9(homedir5(), ".augmented");
|
|
5376
5535
|
try {
|
|
5377
5536
|
mkdirSync4(dir, { recursive: true });
|
|
5378
5537
|
} catch {
|
|
5379
5538
|
}
|
|
5380
|
-
const p =
|
|
5539
|
+
const p = join9(dir, ".eval-empty-mcp.json");
|
|
5381
5540
|
writeFileSync4(p, JSON.stringify({ mcpServers: {} }));
|
|
5382
5541
|
evalEmptyMcpConfigPath = p;
|
|
5383
5542
|
return p;
|
|
@@ -5403,7 +5562,7 @@ async function runEvalClaude(prompt, model) {
|
|
|
5403
5562
|
""
|
|
5404
5563
|
];
|
|
5405
5564
|
const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
|
|
5406
|
-
cwd:
|
|
5565
|
+
cwd: homedir5(),
|
|
5407
5566
|
timeout: 12e4,
|
|
5408
5567
|
stdin: "ignore",
|
|
5409
5568
|
env: childEnv,
|
|
@@ -5482,10 +5641,10 @@ function freePort(codeName) {
|
|
|
5482
5641
|
}
|
|
5483
5642
|
}
|
|
5484
5643
|
function getStateFile() {
|
|
5485
|
-
return
|
|
5644
|
+
return join9(config?.configDir ?? join9(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
5486
5645
|
}
|
|
5487
5646
|
function channelHashCacheDir() {
|
|
5488
|
-
return config?.configDir ??
|
|
5647
|
+
return config?.configDir ?? join9(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
5489
5648
|
}
|
|
5490
5649
|
function loadChannelHashCache2() {
|
|
5491
5650
|
loadChannelHashCache(agentState.knownChannelConfigHashes, channelHashCacheDir());
|
|
@@ -5496,7 +5655,7 @@ function saveChannelHashCache2() {
|
|
|
5496
5655
|
var _channelQuarantineStore = null;
|
|
5497
5656
|
function channelQuarantineStore() {
|
|
5498
5657
|
if (!_channelQuarantineStore) {
|
|
5499
|
-
const dir = config?.configDir ??
|
|
5658
|
+
const dir = config?.configDir ?? join9(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
5500
5659
|
_channelQuarantineStore = new ChannelQuarantineStore(defaultQuarantinePath(dir));
|
|
5501
5660
|
}
|
|
5502
5661
|
return _channelQuarantineStore;
|
|
@@ -5551,7 +5710,7 @@ function log(msg) {
|
|
|
5551
5710
|
`;
|
|
5552
5711
|
if (!managerLogPath) {
|
|
5553
5712
|
try {
|
|
5554
|
-
managerLogPath =
|
|
5713
|
+
managerLogPath = join9(homedir5(), ".augmented", "manager.log");
|
|
5555
5714
|
mkdirSync4(dirname3(managerLogPath), { recursive: true });
|
|
5556
5715
|
if (existsSync5(managerLogPath)) {
|
|
5557
5716
|
chmodSync(managerLogPath, 384);
|
|
@@ -5606,12 +5765,12 @@ function parseSkillFrontmatter(content) {
|
|
|
5606
5765
|
}
|
|
5607
5766
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
5608
5767
|
const { readdirSync: readdirSync5, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync5 } = await import("fs");
|
|
5609
|
-
const skillsDir =
|
|
5610
|
-
const claudeMdPath =
|
|
5768
|
+
const skillsDir = join9(configDir, codeName, "project", ".claude", "skills");
|
|
5769
|
+
const claudeMdPath = join9(configDir, codeName, "project", "CLAUDE.md");
|
|
5611
5770
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
5612
5771
|
const entries = [];
|
|
5613
5772
|
for (const dir of readdirSync5(skillsDir).sort()) {
|
|
5614
|
-
const skillFile =
|
|
5773
|
+
const skillFile = join9(skillsDir, dir, "SKILL.md");
|
|
5615
5774
|
if (!ex(skillFile)) continue;
|
|
5616
5775
|
try {
|
|
5617
5776
|
const { name, description } = parseSkillFrontmatter(rfs(skillFile, "utf-8"));
|
|
@@ -5659,7 +5818,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
5659
5818
|
}
|
|
5660
5819
|
async function migrateToProfiles() {
|
|
5661
5820
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5662
|
-
const sharedConfigPath =
|
|
5821
|
+
const sharedConfigPath = join9(homeDir, ".openclaw", "openclaw.json");
|
|
5663
5822
|
let sharedConfig;
|
|
5664
5823
|
try {
|
|
5665
5824
|
sharedConfig = JSON.parse(readFileSync9(sharedConfigPath, "utf-8"));
|
|
@@ -5675,19 +5834,19 @@ async function migrateToProfiles() {
|
|
|
5675
5834
|
const codeName = agentEntry["id"];
|
|
5676
5835
|
if (!codeName) continue;
|
|
5677
5836
|
if (codeName === "main") continue;
|
|
5678
|
-
const profileDir =
|
|
5679
|
-
if (existsSync5(
|
|
5837
|
+
const profileDir = join9(homeDir, `.openclaw-${codeName}`);
|
|
5838
|
+
if (existsSync5(join9(profileDir, "openclaw.json"))) continue;
|
|
5680
5839
|
log(`Migrating agent '${codeName}' to per-agent profile`);
|
|
5681
5840
|
if (adapter.seedProfileConfig) {
|
|
5682
5841
|
adapter.seedProfileConfig(codeName);
|
|
5683
5842
|
}
|
|
5684
|
-
const sharedAuthDir =
|
|
5685
|
-
const profileAuthDir =
|
|
5686
|
-
const authFile =
|
|
5843
|
+
const sharedAuthDir = join9(homeDir, ".openclaw", "agents", codeName, "agent");
|
|
5844
|
+
const profileAuthDir = join9(profileDir, "agents", codeName, "agent");
|
|
5845
|
+
const authFile = join9(sharedAuthDir, "auth-profiles.json");
|
|
5687
5846
|
if (existsSync5(authFile)) {
|
|
5688
5847
|
mkdirSync4(profileAuthDir, { recursive: true });
|
|
5689
5848
|
const authContent = readFileSync9(authFile, "utf-8");
|
|
5690
|
-
writeFileSync4(
|
|
5849
|
+
writeFileSync4(join9(profileAuthDir, "auth-profiles.json"), authContent);
|
|
5691
5850
|
}
|
|
5692
5851
|
allocatePort(codeName);
|
|
5693
5852
|
migrated++;
|
|
@@ -5725,7 +5884,7 @@ function readGatewayToken(codeName) {
|
|
|
5725
5884
|
}
|
|
5726
5885
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5727
5886
|
try {
|
|
5728
|
-
const cfg = JSON.parse(readFileSync9(
|
|
5887
|
+
const cfg = JSON.parse(readFileSync9(join9(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
|
|
5729
5888
|
return cfg?.gateway?.auth?.token;
|
|
5730
5889
|
} catch {
|
|
5731
5890
|
return void 0;
|
|
@@ -5734,7 +5893,7 @@ function readGatewayToken(codeName) {
|
|
|
5734
5893
|
var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
|
|
5735
5894
|
function isGatewayHung(codeName) {
|
|
5736
5895
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5737
|
-
const jobsPath =
|
|
5896
|
+
const jobsPath = join9(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
5738
5897
|
if (!existsSync5(jobsPath)) return false;
|
|
5739
5898
|
try {
|
|
5740
5899
|
const data = JSON.parse(readFileSync9(jobsPath, "utf-8"));
|
|
@@ -5770,13 +5929,13 @@ async function ensureGatewayRunning(codeName, adapter) {
|
|
|
5770
5929
|
}
|
|
5771
5930
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
5772
5931
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5773
|
-
const cronJobsPath =
|
|
5932
|
+
const cronJobsPath = join9(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
5774
5933
|
clearStaleCronRunState(cronJobsPath);
|
|
5775
5934
|
} else {
|
|
5776
5935
|
if (status.port) {
|
|
5777
5936
|
try {
|
|
5778
5937
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5779
|
-
const configPath =
|
|
5938
|
+
const configPath = join9(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
5780
5939
|
if (existsSync5(configPath)) {
|
|
5781
5940
|
const cfg = JSON.parse(readFileSync9(configPath, "utf-8"));
|
|
5782
5941
|
if (cfg.gateway?.port !== status.port) {
|
|
@@ -5802,7 +5961,7 @@ async function ensureGatewayRunning(codeName, adapter) {
|
|
|
5802
5961
|
gatewaysStartedThisCycle.add(codeName);
|
|
5803
5962
|
try {
|
|
5804
5963
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
5805
|
-
const configPath =
|
|
5964
|
+
const configPath = join9(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
5806
5965
|
if (existsSync5(configPath)) {
|
|
5807
5966
|
const cfg = JSON.parse(readFileSync9(configPath, "utf-8"));
|
|
5808
5967
|
if (!cfg.gateway) cfg.gateway = {};
|
|
@@ -5958,7 +6117,7 @@ async function pollCycle() {
|
|
|
5958
6117
|
}
|
|
5959
6118
|
try {
|
|
5960
6119
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
5961
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
6120
|
+
const { collectDiagnostics } = await import("../persistent-session-CZQPV267.js");
|
|
5962
6121
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
5963
6122
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
5964
6123
|
let tailscaleHostname;
|
|
@@ -6045,12 +6204,12 @@ async function pollCycle() {
|
|
|
6045
6204
|
const {
|
|
6046
6205
|
collectResponsivenessProbes,
|
|
6047
6206
|
getResponsivenessIntervalMs
|
|
6048
|
-
} = await import("../responsiveness-probe-
|
|
6207
|
+
} = await import("../responsiveness-probe-EW2ZLSZL.js");
|
|
6049
6208
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
6050
6209
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
6051
6210
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
6052
6211
|
if (probeCodeNames.length > 0) {
|
|
6053
|
-
const { takeAcpxExecFailureCount, creditAcpxExecFailureCount } = await import("../persistent-session-
|
|
6212
|
+
const { takeAcpxExecFailureCount, creditAcpxExecFailureCount } = await import("../persistent-session-CZQPV267.js");
|
|
6054
6213
|
const drainedGiveUps = /* @__PURE__ */ new Map();
|
|
6055
6214
|
const drainedAcpxFailures = /* @__PURE__ */ new Map();
|
|
6056
6215
|
const probes = collectResponsivenessProbes(probeCodeNames).map((p) => {
|
|
@@ -6084,8 +6243,7 @@ async function pollCycle() {
|
|
|
6084
6243
|
collectResponsivenessProbes,
|
|
6085
6244
|
livePendingInboundOldestAgeSeconds,
|
|
6086
6245
|
deadLetterPendingInbound
|
|
6087
|
-
} = await import("../responsiveness-probe-
|
|
6088
|
-
const { transcriptActivityAgeSeconds } = await import("../daily-session-PNQX5URX.js");
|
|
6246
|
+
} = await import("../responsiveness-probe-EW2ZLSZL.js");
|
|
6089
6247
|
const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
6090
6248
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
6091
6249
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -6149,6 +6307,21 @@ async function pollCycle() {
|
|
|
6149
6307
|
log(
|
|
6150
6308
|
`[wedge] forced fresh respawn ${detail} \u2192 new session ${newId} (transcript preserved${deadNote})`
|
|
6151
6309
|
);
|
|
6310
|
+
const wedgeAgentId = agentState.codeNameToAgentId.get(codeName);
|
|
6311
|
+
if (wedgeAgentId) {
|
|
6312
|
+
api.post("/host/wedge-respawn", {
|
|
6313
|
+
agent_id: wedgeAgentId,
|
|
6314
|
+
code_name: codeName,
|
|
6315
|
+
dead_lettered_count: deadLettered,
|
|
6316
|
+
pane_age_seconds: signals.paneActivityAgeSeconds,
|
|
6317
|
+
inbound_age_seconds: signals.pendingInboundOldestAgeSeconds,
|
|
6318
|
+
transcript_age_seconds: transcriptAge
|
|
6319
|
+
}).catch((err) => {
|
|
6320
|
+
log(
|
|
6321
|
+
`[wedge] failed to record respawn event for '${codeName}' (ENG-6265): ${err.message} \u2014 respawn proceeded; CloudWatch metric will under-count this event`
|
|
6322
|
+
);
|
|
6323
|
+
});
|
|
6324
|
+
}
|
|
6152
6325
|
const inProgressCardIds = (kanbanBoardCache.get(codeName) ?? []).filter((item) => item.status === "in_progress" && isHybridActionable(item)).map((item) => item.id);
|
|
6153
6326
|
const cardStates = wedgeRestartsByCard.get(codeName) ?? /* @__PURE__ */ new Map();
|
|
6154
6327
|
const { next, newlyPoisoned } = recordWedgeForCards(
|
|
@@ -6299,7 +6472,7 @@ async function pollCycle() {
|
|
|
6299
6472
|
}
|
|
6300
6473
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
6301
6474
|
freePort(prev.codeName);
|
|
6302
|
-
const agentDir =
|
|
6475
|
+
const agentDir = join9(adapter.getAgentDir(prev.codeName), "provision");
|
|
6303
6476
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
6304
6477
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
6305
6478
|
}
|
|
@@ -6385,10 +6558,10 @@ async function pollCycle() {
|
|
|
6385
6558
|
// pending-inbound marker. Best-effort: a write failure is logged by
|
|
6386
6559
|
// the watchdog, never fails the poll cycle.
|
|
6387
6560
|
signalGiveUp: (codeName) => {
|
|
6388
|
-
const dir =
|
|
6561
|
+
const dir = join9(homedir5(), ".augmented", codeName);
|
|
6389
6562
|
if (!existsSync5(dir)) return;
|
|
6390
6563
|
atomicWriteFileSync(
|
|
6391
|
-
|
|
6564
|
+
join9(dir, "watchdog-give-up.json"),
|
|
6392
6565
|
JSON.stringify({ gave_up_at: (/* @__PURE__ */ new Date()).toISOString() })
|
|
6393
6566
|
);
|
|
6394
6567
|
}
|
|
@@ -6509,7 +6682,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6509
6682
|
}
|
|
6510
6683
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6511
6684
|
const adapter = resolveAgentFramework(agent.code_name);
|
|
6512
|
-
let agentDir =
|
|
6685
|
+
let agentDir = join9(adapter.getAgentDir(agent.code_name), "provision");
|
|
6513
6686
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
6514
6687
|
if (previousKnownStatus !== agent.status) {
|
|
6515
6688
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
@@ -6713,7 +6886,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6713
6886
|
const frameworkId = refreshData.agent.framework ?? "openclaw";
|
|
6714
6887
|
agentFrameworkCache.set(agent.code_name, frameworkId);
|
|
6715
6888
|
const frameworkAdapter = getFramework(frameworkId);
|
|
6716
|
-
agentDir =
|
|
6889
|
+
agentDir = join9(frameworkAdapter.getAgentDir(agent.code_name), "provision");
|
|
6717
6890
|
cacheAgentDeliveryMetadata(agent.code_name, refreshData);
|
|
6718
6891
|
if (frameworkAdapter.migrateSecretStorage && !migratedSecretStorage.has(agent.code_name)) {
|
|
6719
6892
|
try {
|
|
@@ -6756,7 +6929,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6756
6929
|
const changedFiles = [];
|
|
6757
6930
|
mkdirSync4(agentDir, { recursive: true });
|
|
6758
6931
|
for (const artifact of artifacts) {
|
|
6759
|
-
const filePath =
|
|
6932
|
+
const filePath = join9(agentDir, artifact.relativePath);
|
|
6760
6933
|
let existingHash;
|
|
6761
6934
|
let newHash;
|
|
6762
6935
|
let writeContent = artifact.content;
|
|
@@ -6775,7 +6948,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6775
6948
|
};
|
|
6776
6949
|
newHash = sha256(stripDynamicSections(artifact.content));
|
|
6777
6950
|
try {
|
|
6778
|
-
const projectClaudeMd =
|
|
6951
|
+
const projectClaudeMd = join9(config.configDir, agent.code_name, "project", "CLAUDE.md");
|
|
6779
6952
|
const existing = readFileSync9(projectClaudeMd, "utf-8");
|
|
6780
6953
|
existingHash = sha256(stripDynamicSections(existing));
|
|
6781
6954
|
} catch {
|
|
@@ -6816,12 +6989,12 @@ async function processAgent(agent, agentStates) {
|
|
|
6816
6989
|
}
|
|
6817
6990
|
}
|
|
6818
6991
|
if (changedFiles.length > 0) {
|
|
6819
|
-
const isFirst = !existsSync5(
|
|
6992
|
+
const isFirst = !existsSync5(join9(agentDir, "CHARTER.md"));
|
|
6820
6993
|
const verb = isFirst ? "Provisioning" : "Updating";
|
|
6821
6994
|
const fileNames = changedFiles.map((f) => f.relativePath).join(", ");
|
|
6822
6995
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
6823
6996
|
for (const file of changedFiles) {
|
|
6824
|
-
const filePath =
|
|
6997
|
+
const filePath = join9(agentDir, file.relativePath);
|
|
6825
6998
|
mkdirSync4(dirname3(filePath), { recursive: true });
|
|
6826
6999
|
if (file.relativePath === ".mcp.json") {
|
|
6827
7000
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
@@ -6830,12 +7003,12 @@ async function processAgent(agent, agentStates) {
|
|
|
6830
7003
|
}
|
|
6831
7004
|
}
|
|
6832
7005
|
try {
|
|
6833
|
-
const provSkillsDir =
|
|
7006
|
+
const provSkillsDir = join9(agentDir, ".claude", "skills");
|
|
6834
7007
|
if (existsSync5(provSkillsDir)) {
|
|
6835
7008
|
for (const folder of readdirSync4(provSkillsDir)) {
|
|
6836
7009
|
if (folder.startsWith("knowledge-")) {
|
|
6837
7010
|
try {
|
|
6838
|
-
rmSync2(
|
|
7011
|
+
rmSync2(join9(provSkillsDir, folder), { recursive: true });
|
|
6839
7012
|
} catch {
|
|
6840
7013
|
}
|
|
6841
7014
|
}
|
|
@@ -6848,7 +7021,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6848
7021
|
const trackedFiles2 = frameworkAdapter.driftTrackedFiles();
|
|
6849
7022
|
const hashes = /* @__PURE__ */ new Map();
|
|
6850
7023
|
for (const file of trackedFiles2) {
|
|
6851
|
-
const h = hashFile(
|
|
7024
|
+
const h = hashFile(join9(agentDir, file));
|
|
6852
7025
|
if (h) hashes.set(file, h);
|
|
6853
7026
|
}
|
|
6854
7027
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -6916,7 +7089,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6916
7089
|
if (written && existsSync5(agentDir)) {
|
|
6917
7090
|
const driftedFiles = [];
|
|
6918
7091
|
for (const [file, expectedHash] of written) {
|
|
6919
|
-
const localHash = hashFile(
|
|
7092
|
+
const localHash = hashFile(join9(agentDir, file));
|
|
6920
7093
|
if (localHash && localHash !== expectedHash) {
|
|
6921
7094
|
driftedFiles.push(file);
|
|
6922
7095
|
}
|
|
@@ -6927,7 +7100,7 @@ async function processAgent(agent, agentStates) {
|
|
|
6927
7100
|
try {
|
|
6928
7101
|
const localHashes = {};
|
|
6929
7102
|
for (const file of driftedFiles) {
|
|
6930
|
-
localHashes[file] = hashFile(
|
|
7103
|
+
localHashes[file] = hashFile(join9(agentDir, file));
|
|
6931
7104
|
}
|
|
6932
7105
|
await api.post("/host/drift", {
|
|
6933
7106
|
agent_id: agent.agent_id,
|
|
@@ -7251,18 +7424,18 @@ async function processAgent(agent, agentStates) {
|
|
|
7251
7424
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? "openclaw") === "claude-code") {
|
|
7252
7425
|
try {
|
|
7253
7426
|
const agentProvisionDir = agentDir;
|
|
7254
|
-
const projectDir =
|
|
7427
|
+
const projectDir = join9(homedir5(), ".augmented", agent.code_name, "project");
|
|
7255
7428
|
mkdirSync4(agentProvisionDir, { recursive: true });
|
|
7256
7429
|
mkdirSync4(projectDir, { recursive: true });
|
|
7257
|
-
const provisionMcpPath =
|
|
7258
|
-
const projectMcpPath =
|
|
7430
|
+
const provisionMcpPath = join9(agentProvisionDir, ".mcp.json");
|
|
7431
|
+
const projectMcpPath = join9(projectDir, ".mcp.json");
|
|
7259
7432
|
let mcpConfig = { mcpServers: {} };
|
|
7260
7433
|
try {
|
|
7261
7434
|
mcpConfig = JSON.parse(readFileSync9(provisionMcpPath, "utf-8"));
|
|
7262
7435
|
if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
|
|
7263
7436
|
} catch {
|
|
7264
7437
|
}
|
|
7265
|
-
const localDirectChatChannel =
|
|
7438
|
+
const localDirectChatChannel = join9(homedir5(), ".augmented", "_mcp", "direct-chat-channel.js");
|
|
7266
7439
|
const directChatTeamSettings = refreshData.team?.settings;
|
|
7267
7440
|
const directChatTz = (() => {
|
|
7268
7441
|
const tz = directChatTeamSettings?.["timezone"];
|
|
@@ -7292,7 +7465,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7292
7465
|
log(`Channel credentials written for '${agent.code_name}/direct-chat'`);
|
|
7293
7466
|
}
|
|
7294
7467
|
}
|
|
7295
|
-
const staleChannelsPath =
|
|
7468
|
+
const staleChannelsPath = join9(projectDir, ".mcp-channels.json");
|
|
7296
7469
|
if (existsSync5(staleChannelsPath)) {
|
|
7297
7470
|
try {
|
|
7298
7471
|
rmSync2(staleChannelsPath, { force: true });
|
|
@@ -7357,7 +7530,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7357
7530
|
}
|
|
7358
7531
|
if (process.env.AGT_CONNECTIVITY_PROBE_ENABLED === "true") {
|
|
7359
7532
|
try {
|
|
7360
|
-
const probeProjectDir =
|
|
7533
|
+
const probeProjectDir = join9(homedir5(), ".augmented", agent.code_name, "project");
|
|
7361
7534
|
await runAgentConnectivityProbes(agent, integrations, probeProjectDir);
|
|
7362
7535
|
} catch (err) {
|
|
7363
7536
|
log(`Connectivity probe failed for '${agent.code_name}': ${err.message}`);
|
|
@@ -7375,8 +7548,8 @@ async function processAgent(agent, agentStates) {
|
|
|
7375
7548
|
recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
|
|
7376
7549
|
}
|
|
7377
7550
|
if (intHash !== prevIntHash) {
|
|
7378
|
-
const projectDir =
|
|
7379
|
-
const envIntPath =
|
|
7551
|
+
const projectDir = join9(homedir5(), ".augmented", agent.code_name, "project");
|
|
7552
|
+
const envIntPath = join9(projectDir, ".env.integrations");
|
|
7380
7553
|
let preWriteEnv;
|
|
7381
7554
|
try {
|
|
7382
7555
|
preWriteEnv = readFileSync9(envIntPath, "utf-8");
|
|
@@ -7391,7 +7564,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7391
7564
|
let rotationHandled = true;
|
|
7392
7565
|
if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
|
|
7393
7566
|
try {
|
|
7394
|
-
const projectMcpPath =
|
|
7567
|
+
const projectMcpPath = join9(projectDir, ".mcp.json");
|
|
7395
7568
|
const postWriteEnv = readFileSync9(envIntPath, "utf-8");
|
|
7396
7569
|
const mcpContent = readFileSync9(projectMcpPath, "utf-8");
|
|
7397
7570
|
const changedVars = diffEnvIntegrations(preWriteEnv, postWriteEnv);
|
|
@@ -7575,7 +7748,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7575
7748
|
if (agent.status === "active") {
|
|
7576
7749
|
if (frameworkAdapter.installPlugin) {
|
|
7577
7750
|
try {
|
|
7578
|
-
const pluginPath =
|
|
7751
|
+
const pluginPath = join9(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
|
|
7579
7752
|
if (existsSync5(pluginPath)) {
|
|
7580
7753
|
frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
|
|
7581
7754
|
agtHost: requireHost(),
|
|
@@ -7642,18 +7815,18 @@ async function processAgent(agent, agentStates) {
|
|
|
7642
7815
|
}
|
|
7643
7816
|
try {
|
|
7644
7817
|
const { readdirSync: readdirSync5, rmSync: rmSync3 } = await import("fs");
|
|
7645
|
-
const { homedir:
|
|
7818
|
+
const { homedir: homedir6 } = await import("os");
|
|
7646
7819
|
const frameworkId2 = frameworkAdapter.id;
|
|
7647
7820
|
const candidateSkillDirs = [
|
|
7648
7821
|
// Claude Code — framework runtime tree
|
|
7649
|
-
|
|
7822
|
+
join9(homedir6(), ".augmented", agent.code_name, "skills"),
|
|
7650
7823
|
// Claude Code — project tree
|
|
7651
|
-
|
|
7824
|
+
join9(homedir6(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
7652
7825
|
// OpenClaw — framework runtime tree
|
|
7653
|
-
|
|
7826
|
+
join9(homedir6(), `.openclaw-${agent.code_name}`, "skills"),
|
|
7654
7827
|
// Defensive: legacy provision-side path, not currently an
|
|
7655
7828
|
// install target but cheap to sweep.
|
|
7656
|
-
|
|
7829
|
+
join9(agentDir, ".claude", "skills")
|
|
7657
7830
|
];
|
|
7658
7831
|
const existingDirs = candidateSkillDirs.filter((d) => existsSync5(d));
|
|
7659
7832
|
const discoveredEntries = /* @__PURE__ */ new Set();
|
|
@@ -7669,7 +7842,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7669
7842
|
}
|
|
7670
7843
|
const removeSkillFolder = (entry, reason) => {
|
|
7671
7844
|
for (const dir of existingDirs) {
|
|
7672
|
-
const p =
|
|
7845
|
+
const p = join9(dir, entry);
|
|
7673
7846
|
if (existsSync5(p)) {
|
|
7674
7847
|
rmSync3(p, { recursive: true, force: true });
|
|
7675
7848
|
}
|
|
@@ -7849,7 +8022,7 @@ async function processAgent(agent, agentStates) {
|
|
|
7849
8022
|
const sess = getSessionState(agent.code_name);
|
|
7850
8023
|
let mcpJsonParsed = null;
|
|
7851
8024
|
try {
|
|
7852
|
-
const mcpPath =
|
|
8025
|
+
const mcpPath = join9(getProjectDir(agent.code_name), ".mcp.json");
|
|
7853
8026
|
mcpJsonParsed = JSON.parse(readFileSync9(mcpPath, "utf-8"));
|
|
7854
8027
|
} catch {
|
|
7855
8028
|
}
|
|
@@ -7868,7 +8041,19 @@ async function processAgent(agent, agentStates) {
|
|
|
7868
8041
|
// isolated and the agent keeps running degraded instead of being
|
|
7869
8042
|
// paused wholesale. reaperRestartBreakerReason() encodes that
|
|
7870
8043
|
// single-vs-multi decision; undefined means "restart, don't count".
|
|
7871
|
-
|
|
8044
|
+
//
|
|
8045
|
+
// ENG-6264: the breaker-count reason (above, undefined for a single dead
|
|
8046
|
+
// MCP) is decoupled from the GATE reason. Pre-6264 an undefined breaker
|
|
8047
|
+
// reason also made the restart non-gateable → 'bypass' → the session was
|
|
8048
|
+
// torn down mid-turn (the common single-MCP case interrupted busy
|
|
8049
|
+
// agents). Always pass 'mcp-presence-reaper' as the gate reason so the
|
|
8050
|
+
// restart defers-until-idle, while breakerReason still governs whether it
|
|
8051
|
+
// counts against the breaker.
|
|
8052
|
+
stopSession: (codeName, ctx) => stopPersistentSessionAndForgetMcpBaseline(
|
|
8053
|
+
codeName,
|
|
8054
|
+
reaperRestartBreakerReason(ctx.activeKeys),
|
|
8055
|
+
"mcp-presence-reaper"
|
|
8056
|
+
),
|
|
7872
8057
|
// ENG-5292: when the reaper gives up on a managed MCP (cap from
|
|
7873
8058
|
// ENG-5279 + state-preservation from ENG-5285 both said "this
|
|
7874
8059
|
// MCP keeps failing after 3 restart cycles"), mark the matching
|
|
@@ -8047,7 +8232,7 @@ async function processAgent(agent, agentStates) {
|
|
|
8047
8232
|
lastWorkTriggerAt.set(agent.code_name, triggerTs);
|
|
8048
8233
|
if (agentFw === "openclaw" && gatewayRunning && gatewayPort) {
|
|
8049
8234
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8050
|
-
const jobsPath =
|
|
8235
|
+
const jobsPath = join9(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
|
|
8051
8236
|
if (existsSync5(jobsPath)) {
|
|
8052
8237
|
try {
|
|
8053
8238
|
const jobsData = JSON.parse(readFileSync9(jobsPath, "utf-8"));
|
|
@@ -8187,7 +8372,7 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
|
|
|
8187
8372
|
if (trackedFiles.length > 0 && existsSync5(agentDir)) {
|
|
8188
8373
|
const hashes = /* @__PURE__ */ new Map();
|
|
8189
8374
|
for (const file of trackedFiles) {
|
|
8190
|
-
const h = hashFile(
|
|
8375
|
+
const h = hashFile(join9(agentDir, file));
|
|
8191
8376
|
if (h) hashes.set(file, h);
|
|
8192
8377
|
}
|
|
8193
8378
|
agentState.writtenHashes.set(agent.agent_id, hashes);
|
|
@@ -8221,16 +8406,16 @@ function cleanupStaleSessions(codeName) {
|
|
|
8221
8406
|
lastCleanupAt.set(codeName, Date.now());
|
|
8222
8407
|
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
8223
8408
|
for (const agentDir of ["main", codeName]) {
|
|
8224
|
-
const sessionsDir =
|
|
8409
|
+
const sessionsDir = join9(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
|
|
8225
8410
|
cleanupCronSessions(sessionsDir, CRON_SESSION_KEEP_COUNT);
|
|
8226
8411
|
}
|
|
8227
|
-
const cronRunsDir =
|
|
8412
|
+
const cronRunsDir = join9(homeDir, `.openclaw-${codeName}`, "cron", "runs");
|
|
8228
8413
|
cleanupOldFiles(cronRunsDir, CRON_RUN_RETENTION_DAYS, ".jsonl");
|
|
8229
|
-
const cronJobsPath =
|
|
8414
|
+
const cronJobsPath = join9(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
8230
8415
|
clearStaleCronRunState(cronJobsPath);
|
|
8231
8416
|
}
|
|
8232
8417
|
function cleanupCronSessions(sessionsDir, keepCount) {
|
|
8233
|
-
const indexPath =
|
|
8418
|
+
const indexPath = join9(sessionsDir, "sessions.json");
|
|
8234
8419
|
if (!existsSync5(indexPath)) return;
|
|
8235
8420
|
try {
|
|
8236
8421
|
const raw = readFileSync9(indexPath, "utf-8");
|
|
@@ -8246,7 +8431,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
8246
8431
|
for (const entry of toDelete) {
|
|
8247
8432
|
delete index[entry.key];
|
|
8248
8433
|
if (entry.sessionId) {
|
|
8249
|
-
const sessionFile =
|
|
8434
|
+
const sessionFile = join9(sessionsDir, `${entry.sessionId}.jsonl`);
|
|
8250
8435
|
try {
|
|
8251
8436
|
if (existsSync5(sessionFile)) {
|
|
8252
8437
|
unlinkSync(sessionFile);
|
|
@@ -8268,7 +8453,7 @@ function cleanupCronSessions(sessionsDir, keepCount) {
|
|
|
8268
8453
|
delete index[parentKey];
|
|
8269
8454
|
if (parentSessionId) {
|
|
8270
8455
|
try {
|
|
8271
|
-
const f =
|
|
8456
|
+
const f = join9(sessionsDir, `${parentSessionId}.jsonl`);
|
|
8272
8457
|
if (existsSync5(f)) {
|
|
8273
8458
|
unlinkSync(f);
|
|
8274
8459
|
deletedFiles++;
|
|
@@ -8326,7 +8511,7 @@ function cleanupOldFiles(dir, maxAgeDays, ext) {
|
|
|
8326
8511
|
try {
|
|
8327
8512
|
for (const f of readdirSync4(dir)) {
|
|
8328
8513
|
if (!f.endsWith(ext)) continue;
|
|
8329
|
-
const fullPath =
|
|
8514
|
+
const fullPath = join9(dir, f);
|
|
8330
8515
|
try {
|
|
8331
8516
|
const st = statSync3(fullPath);
|
|
8332
8517
|
if (st.mtimeMs < cutoff) {
|
|
@@ -8366,7 +8551,7 @@ var inFlightClaudeTasks = /* @__PURE__ */ new Set();
|
|
|
8366
8551
|
var claudeTaskConcurrency = /* @__PURE__ */ new Map();
|
|
8367
8552
|
var MAX_CLAUDE_CONCURRENCY = 2;
|
|
8368
8553
|
function claudePidFilePath() {
|
|
8369
|
-
return
|
|
8554
|
+
return join9(homedir5(), ".augmented", "manager-claude-pids.json");
|
|
8370
8555
|
}
|
|
8371
8556
|
var inFlightClaudePids = /* @__PURE__ */ new Map();
|
|
8372
8557
|
function registerClaudeSpawn(record) {
|
|
@@ -8706,7 +8891,7 @@ async function fireScheduledTaskViaKanban(codeName, agentId, task, prompt) {
|
|
|
8706
8891
|
}
|
|
8707
8892
|
async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
8708
8893
|
const projectDir = getProjectDir2(codeName);
|
|
8709
|
-
const mcpConfigPath =
|
|
8894
|
+
const mcpConfigPath = join9(projectDir, ".mcp.json");
|
|
8710
8895
|
let runId = null;
|
|
8711
8896
|
let kanbanItemId = null;
|
|
8712
8897
|
let taskResult;
|
|
@@ -8714,7 +8899,7 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
|
8714
8899
|
const priorRuns = await fetchPriorScheduledRuns(agentId, task.taskId);
|
|
8715
8900
|
prompt = wrapScheduledTaskPrompt(prompt, { priorRuns });
|
|
8716
8901
|
try {
|
|
8717
|
-
const claudeMdPath =
|
|
8902
|
+
const claudeMdPath = join9(projectDir, "CLAUDE.md");
|
|
8718
8903
|
const serverNames = [];
|
|
8719
8904
|
if (existsSync5(mcpConfigPath)) {
|
|
8720
8905
|
try {
|
|
@@ -8741,7 +8926,7 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
|
|
|
8741
8926
|
claudeArgs.push("--system-prompt-file", claudeMdPath);
|
|
8742
8927
|
}
|
|
8743
8928
|
const childEnv = { ...process.env };
|
|
8744
|
-
const envIntPath =
|
|
8929
|
+
const envIntPath = join9(projectDir, ".env.integrations");
|
|
8745
8930
|
if (existsSync5(envIntPath)) {
|
|
8746
8931
|
try {
|
|
8747
8932
|
Object.assign(childEnv, parseEnvIntegrations(readFileSync9(envIntPath, "utf-8")));
|
|
@@ -8916,8 +9101,8 @@ var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
|
8916
9101
|
async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
8917
9102
|
const codeName = agent.code_name;
|
|
8918
9103
|
const projectDir = getProjectDir(codeName);
|
|
8919
|
-
const mcpConfigPath =
|
|
8920
|
-
const claudeMdPath =
|
|
9104
|
+
const mcpConfigPath = join9(projectDir, ".mcp.json");
|
|
9105
|
+
const claudeMdPath = join9(projectDir, "CLAUDE.md");
|
|
8921
9106
|
if (restartBreaker.isTripped(codeName)) {
|
|
8922
9107
|
const trip = restartBreaker.getTrip(codeName);
|
|
8923
9108
|
return {
|
|
@@ -9087,6 +9272,11 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash3("sha256").
|
|
|
9087
9272
|
} catch (err) {
|
|
9088
9273
|
log(`[persistent-session] Failed to provision auto-progress hook for '${codeName}': ${err.message}`);
|
|
9089
9274
|
}
|
|
9275
|
+
try {
|
|
9276
|
+
provisionSessionStateHook(codeName);
|
|
9277
|
+
} catch (err) {
|
|
9278
|
+
log(`[persistent-session] Failed to provision session-state hook for '${codeName}': ${err.message}`);
|
|
9279
|
+
}
|
|
9090
9280
|
const sessionRunResult = await startRun({
|
|
9091
9281
|
agent_id: agent.agent_id,
|
|
9092
9282
|
source_type: "system",
|
|
@@ -9546,7 +9736,7 @@ ${escapeXml(msg.content)}
|
|
|
9546
9736
|
log(`[direct-chat] One-shot spawn for '${agent.codeName}' (msg=${msg.id}; host in-flight=${directChatSpawnGate.hostInFlight}, queued=${directChatSpawnGate.queuedCount})`);
|
|
9547
9737
|
const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
9548
9738
|
const projDir = ccProjectDir(agent.codeName);
|
|
9549
|
-
const mcpConfigPath =
|
|
9739
|
+
const mcpConfigPath = join9(projDir, ".mcp.json");
|
|
9550
9740
|
const serverNames = [];
|
|
9551
9741
|
if (existsSync5(mcpConfigPath)) {
|
|
9552
9742
|
try {
|
|
@@ -9569,11 +9759,11 @@ ${escapeXml(msg.content)}
|
|
|
9569
9759
|
"--allowedTools",
|
|
9570
9760
|
allowedTools
|
|
9571
9761
|
];
|
|
9572
|
-
const chatClaudeMd =
|
|
9762
|
+
const chatClaudeMd = join9(projDir, "CLAUDE.md");
|
|
9573
9763
|
if (existsSync5(chatClaudeMd)) {
|
|
9574
9764
|
chatArgs.push("--system-prompt-file", chatClaudeMd);
|
|
9575
9765
|
}
|
|
9576
|
-
const envIntPath =
|
|
9766
|
+
const envIntPath = join9(projDir, ".env.integrations");
|
|
9577
9767
|
const childEnv = { ...process.env };
|
|
9578
9768
|
if (existsSync5(envIntPath)) {
|
|
9579
9769
|
try {
|
|
@@ -9955,8 +10145,8 @@ function getBuiltInSkillContent(skillId) {
|
|
|
9955
10145
|
if (builtInSkillCache.has(skillId)) return builtInSkillCache.get(skillId);
|
|
9956
10146
|
try {
|
|
9957
10147
|
const candidates = [
|
|
9958
|
-
|
|
9959
|
-
|
|
10148
|
+
join9(process.cwd(), "skills", skillId, "SKILL.md"),
|
|
10149
|
+
join9(new URL(".", import.meta.url).pathname, "..", "..", "..", "..", "skills", skillId, "SKILL.md")
|
|
9960
10150
|
];
|
|
9961
10151
|
for (const candidate of candidates) {
|
|
9962
10152
|
if (existsSync5(candidate)) {
|
|
@@ -10615,7 +10805,7 @@ async function processClaudePairSessions(agents) {
|
|
|
10615
10805
|
killPairSession,
|
|
10616
10806
|
pairTmuxSession,
|
|
10617
10807
|
finalizeClaudePairOnboarding
|
|
10618
|
-
} = await import("../claude-pair-runtime-
|
|
10808
|
+
} = await import("../claude-pair-runtime-AYMNAIYY.js");
|
|
10619
10809
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
10620
10810
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
10621
10811
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -10676,11 +10866,11 @@ async function processClaudePairSessions(agents) {
|
|
|
10676
10866
|
});
|
|
10677
10867
|
} else {
|
|
10678
10868
|
const errKind = result.error.kind;
|
|
10679
|
-
const
|
|
10869
|
+
const errMessage2 = "message" in result.error ? result.error.message : void 0;
|
|
10680
10870
|
await reportAndCleanup(session.pair_id, {
|
|
10681
10871
|
status: errKind === "no-session" ? "session_missing" : "failure",
|
|
10682
10872
|
error_code: errKind,
|
|
10683
|
-
error_message:
|
|
10873
|
+
error_message: errMessage2
|
|
10684
10874
|
});
|
|
10685
10875
|
}
|
|
10686
10876
|
} else if (session.status === "code_submitted" && session.code) {
|
|
@@ -10709,11 +10899,11 @@ async function processClaudePairSessions(agents) {
|
|
|
10709
10899
|
});
|
|
10710
10900
|
} else {
|
|
10711
10901
|
const errKind = result.error.kind;
|
|
10712
|
-
const
|
|
10902
|
+
const errMessage2 = "message" in result.error ? result.error.message : void 0;
|
|
10713
10903
|
await reportAndCleanup(session.pair_id, {
|
|
10714
10904
|
status: errKind === "no-session" ? "session_missing" : "failure",
|
|
10715
10905
|
error_code: errKind,
|
|
10716
|
-
error_message:
|
|
10906
|
+
error_message: errMessage2
|
|
10717
10907
|
});
|
|
10718
10908
|
}
|
|
10719
10909
|
}
|
|
@@ -10925,8 +11115,8 @@ function parseMemoryFile(raw, fallbackName) {
|
|
|
10925
11115
|
};
|
|
10926
11116
|
}
|
|
10927
11117
|
async function syncMemories(agent, configDir, log2) {
|
|
10928
|
-
const projectDir =
|
|
10929
|
-
const memoryDir =
|
|
11118
|
+
const projectDir = join9(configDir, agent.code_name, "project");
|
|
11119
|
+
const memoryDir = join9(projectDir, "memory");
|
|
10930
11120
|
const isFreshSync = pendingFreshMemorySync.has(agent.agent_id);
|
|
10931
11121
|
if (isFreshSync) {
|
|
10932
11122
|
log2(`[memory-sync] Fresh-sync requested for '${agent.code_name}' \u2014 pulling DB first`);
|
|
@@ -10944,7 +11134,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
10944
11134
|
for (const file of readdirSync4(memoryDir)) {
|
|
10945
11135
|
if (!file.endsWith(".md")) continue;
|
|
10946
11136
|
try {
|
|
10947
|
-
const raw = readFileSync9(
|
|
11137
|
+
const raw = readFileSync9(join9(memoryDir, file), "utf-8");
|
|
10948
11138
|
const fileHash = createHash3("sha256").update(raw).digest("hex").slice(0, 16);
|
|
10949
11139
|
currentHashes.set(file, fileHash);
|
|
10950
11140
|
if (prevHashes.get(file) === fileHash) continue;
|
|
@@ -10969,7 +11159,7 @@ async function syncMemories(agent, configDir, log2) {
|
|
|
10969
11159
|
} catch (err) {
|
|
10970
11160
|
for (const mem of changedMemories) {
|
|
10971
11161
|
for (const [file] of currentHashes) {
|
|
10972
|
-
const parsed = parseMemoryFile(readFileSync9(
|
|
11162
|
+
const parsed = parseMemoryFile(readFileSync9(join9(memoryDir, file), "utf-8"), file.replace(/\.md$/, ""));
|
|
10973
11163
|
if (parsed?.name === mem.name) currentHashes.delete(file);
|
|
10974
11164
|
}
|
|
10975
11165
|
}
|
|
@@ -11004,7 +11194,7 @@ async function downloadMemories(agent, memoryDir, log2, { force }) {
|
|
|
11004
11194
|
const mem = dbMemories.memories[i];
|
|
11005
11195
|
const rawSlug = mem.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
|
|
11006
11196
|
const slug = rawSlug || `memory-${i}`;
|
|
11007
|
-
const filePath =
|
|
11197
|
+
const filePath = join9(memoryDir, `${slug}.md`);
|
|
11008
11198
|
const desired = `---
|
|
11009
11199
|
name: ${JSON.stringify(mem.name)}
|
|
11010
11200
|
type: ${mem.type}
|
|
@@ -11125,6 +11315,43 @@ function stopCaffeinate() {
|
|
|
11125
11315
|
log("caffeinate stopped");
|
|
11126
11316
|
}
|
|
11127
11317
|
}
|
|
11318
|
+
var artifactScanners = /* @__PURE__ */ new Map();
|
|
11319
|
+
var artifactStreamingInFlight = false;
|
|
11320
|
+
async function driveArtifactStreaming() {
|
|
11321
|
+
if (!isArtifactStreamingEnabled()) return;
|
|
11322
|
+
if (artifactStreamingInFlight) return;
|
|
11323
|
+
artifactStreamingInFlight = true;
|
|
11324
|
+
try {
|
|
11325
|
+
await driveArtifactStreamingInner();
|
|
11326
|
+
} finally {
|
|
11327
|
+
artifactStreamingInFlight = false;
|
|
11328
|
+
}
|
|
11329
|
+
}
|
|
11330
|
+
async function driveArtifactStreamingInner() {
|
|
11331
|
+
const liveIds = /* @__PURE__ */ new Set();
|
|
11332
|
+
for (const agent of state6.agents) {
|
|
11333
|
+
if (!agent.agentId || !agent.codeName || agent.status !== "active") continue;
|
|
11334
|
+
liveIds.add(agent.agentId);
|
|
11335
|
+
let scanner = artifactScanners.get(agent.agentId);
|
|
11336
|
+
if (!scanner) {
|
|
11337
|
+
scanner = new ArtifactStreamScanner(
|
|
11338
|
+
agent.agentId,
|
|
11339
|
+
artifactsDirFor(agent.codeName),
|
|
11340
|
+
nodeArtifactFs,
|
|
11341
|
+
{ api, log }
|
|
11342
|
+
);
|
|
11343
|
+
artifactScanners.set(agent.agentId, scanner);
|
|
11344
|
+
}
|
|
11345
|
+
try {
|
|
11346
|
+
await scanner.scanOnce();
|
|
11347
|
+
} catch (err) {
|
|
11348
|
+
log(`[artifact-stream] scan failed for ${agent.codeName}: ${err.message}`);
|
|
11349
|
+
}
|
|
11350
|
+
}
|
|
11351
|
+
for (const id of artifactScanners.keys()) {
|
|
11352
|
+
if (!liveIds.has(id)) artifactScanners.delete(id);
|
|
11353
|
+
}
|
|
11354
|
+
}
|
|
11128
11355
|
function startPolling() {
|
|
11129
11356
|
if (!config || running) return;
|
|
11130
11357
|
running = true;
|
|
@@ -11136,6 +11363,7 @@ function startPolling() {
|
|
|
11136
11363
|
startGatewayPool();
|
|
11137
11364
|
return pollCycle();
|
|
11138
11365
|
}).then(() => {
|
|
11366
|
+
void driveArtifactStreaming();
|
|
11139
11367
|
scheduleNext();
|
|
11140
11368
|
});
|
|
11141
11369
|
}
|
|
@@ -11158,7 +11386,10 @@ function scheduleNext() {
|
|
|
11158
11386
|
restartNow();
|
|
11159
11387
|
return;
|
|
11160
11388
|
}
|
|
11161
|
-
void pollCycle().then(
|
|
11389
|
+
void pollCycle().then(() => {
|
|
11390
|
+
void driveArtifactStreaming();
|
|
11391
|
+
scheduleNext();
|
|
11392
|
+
});
|
|
11162
11393
|
}, delayMs);
|
|
11163
11394
|
}
|
|
11164
11395
|
async function killAllAgtTmuxSessions() {
|
|
@@ -11251,7 +11482,7 @@ function startManager(opts) {
|
|
|
11251
11482
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|
|
11252
11483
|
}
|
|
11253
11484
|
log(
|
|
11254
|
-
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${
|
|
11485
|
+
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join9(homedir5(), ".augmented", "manager.log")}`
|
|
11255
11486
|
);
|
|
11256
11487
|
deployMcpAssets();
|
|
11257
11488
|
reapOrphanChannelMcps({ log });
|
|
@@ -11382,14 +11613,14 @@ function restartRunningChannelMcps(basenames) {
|
|
|
11382
11613
|
}
|
|
11383
11614
|
}
|
|
11384
11615
|
function deployMcpAssets() {
|
|
11385
|
-
const targetDir =
|
|
11616
|
+
const targetDir = join9(homedir5(), ".augmented", "_mcp");
|
|
11386
11617
|
mkdirSync4(targetDir, { recursive: true });
|
|
11387
11618
|
const moduleDir = dirname3(fileURLToPath(import.meta.url));
|
|
11388
11619
|
let mcpSourceDir = "";
|
|
11389
11620
|
let dir = moduleDir;
|
|
11390
11621
|
for (let i = 0; i < 6; i++) {
|
|
11391
|
-
const candidate =
|
|
11392
|
-
if (existsSync5(
|
|
11622
|
+
const candidate = join9(dir, "dist", "mcp");
|
|
11623
|
+
if (existsSync5(join9(candidate, "index.js"))) {
|
|
11393
11624
|
mcpSourceDir = candidate;
|
|
11394
11625
|
break;
|
|
11395
11626
|
}
|
|
@@ -11432,8 +11663,8 @@ function deployMcpAssets() {
|
|
|
11432
11663
|
// natural session restart.
|
|
11433
11664
|
"augmented-admin.js"
|
|
11434
11665
|
]) {
|
|
11435
|
-
const src =
|
|
11436
|
-
const dst =
|
|
11666
|
+
const src = join9(mcpSourceDir, file);
|
|
11667
|
+
const dst = join9(targetDir, file);
|
|
11437
11668
|
if (!existsSync5(src)) continue;
|
|
11438
11669
|
const before = fileHash(dst);
|
|
11439
11670
|
try {
|
|
@@ -11451,14 +11682,14 @@ function deployMcpAssets() {
|
|
|
11451
11682
|
log(`[manager] Bundle(s) updated: ${changedBasenames.join(", ")} \u2014 signalling running instances to restart`);
|
|
11452
11683
|
restartRunningChannelMcps(changedBasenames);
|
|
11453
11684
|
}
|
|
11454
|
-
const localMcpPath =
|
|
11685
|
+
const localMcpPath = join9(targetDir, "index.js");
|
|
11455
11686
|
try {
|
|
11456
|
-
const agentsDir =
|
|
11687
|
+
const agentsDir = join9(homedir5(), ".augmented", "agents");
|
|
11457
11688
|
if (existsSync5(agentsDir)) {
|
|
11458
11689
|
for (const entry of readdirSync4(agentsDir, { withFileTypes: true })) {
|
|
11459
11690
|
if (!entry.isDirectory()) continue;
|
|
11460
11691
|
for (const subdir of ["provision", "project"]) {
|
|
11461
|
-
const mcpJsonPath =
|
|
11692
|
+
const mcpJsonPath = join9(agentsDir, entry.name, subdir, ".mcp.json");
|
|
11462
11693
|
try {
|
|
11463
11694
|
const raw = readFileSync9(mcpJsonPath, "utf-8");
|
|
11464
11695
|
if (!raw.includes("@integrity-labs/augmented-mcp")) continue;
|