@integrity-labs/agt-cli 0.28.169 → 0.28.171
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 +14 -43
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-UOL4Z6CG.js → chunk-76XB2I4P.js} +70 -64
- package/dist/chunk-76XB2I4P.js.map +1 -0
- package/dist/{chunk-3DFA7PRA.js → chunk-CPB4L4TB.js} +2499 -4502
- package/dist/chunk-CPB4L4TB.js.map +1 -0
- package/dist/{chunk-VTRZ643P.js → chunk-XJIHUCCF.js} +2 -2
- package/dist/{claude-pair-runtime-2FELNLHJ.js → claude-pair-runtime-37H4BVQC.js} +2 -2
- package/dist/lib/manager-worker.js +25 -1119
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-KRYOZ7JM.js → persistent-session-DUKYMEOQ.js} +3 -3
- package/dist/{responsiveness-probe-GVDKYPLT.js → responsiveness-probe-G5VMYV73.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-3DFA7PRA.js.map +0 -1
- package/dist/chunk-UOL4Z6CG.js.map +0 -1
- /package/dist/{chunk-VTRZ643P.js.map → chunk-XJIHUCCF.js.map} +0 -0
- /package/dist/{claude-pair-runtime-2FELNLHJ.js.map → claude-pair-runtime-37H4BVQC.js.map} +0 -0
- /package/dist/{persistent-session-KRYOZ7JM.js.map → persistent-session-DUKYMEOQ.js.map} +0 -0
- /package/dist/{responsiveness-probe-GVDKYPLT.js.map → responsiveness-probe-G5VMYV73.js.map} +0 -0
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
requireHost,
|
|
29
29
|
safeWriteJsonAtomic,
|
|
30
30
|
setConfigHash
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-CPB4L4TB.js";
|
|
32
32
|
import {
|
|
33
33
|
getProjectDir as getProjectDir2,
|
|
34
34
|
getReadyTasks,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
takeZombieDetection,
|
|
71
71
|
transcriptActivityAgeSeconds,
|
|
72
72
|
writeEgressAllowlist
|
|
73
|
-
} from "../chunk-
|
|
73
|
+
} from "../chunk-XJIHUCCF.js";
|
|
74
74
|
import {
|
|
75
75
|
CONVERSATION_FAILURE_CATEGORIES,
|
|
76
76
|
DEFAULT_FRAMEWORK,
|
|
@@ -111,7 +111,7 @@ import {
|
|
|
111
111
|
resolveChannels,
|
|
112
112
|
resolveDmTarget,
|
|
113
113
|
sumTranscriptUsageInWindow
|
|
114
|
-
} from "../chunk-
|
|
114
|
+
} from "../chunk-76XB2I4P.js";
|
|
115
115
|
import {
|
|
116
116
|
parsePsRows,
|
|
117
117
|
reapOrphanChannelMcps
|
|
@@ -119,7 +119,7 @@ import {
|
|
|
119
119
|
|
|
120
120
|
// src/lib/manager-worker.ts
|
|
121
121
|
import { createHash as createHash10 } from "crypto";
|
|
122
|
-
import { readFileSync as readFileSync14, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync8, rmSync as rmSync4, readdirSync as readdirSync5, statSync as statSync4,
|
|
122
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync8, rmSync as rmSync4, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
|
|
123
123
|
import { execFileSync as syncExecFile } from "child_process";
|
|
124
124
|
import { join as join16, dirname as dirname5 } from "path";
|
|
125
125
|
import { homedir as homedir9 } from "os";
|
|
@@ -3056,275 +3056,6 @@ function bundleFingerprint(files) {
|
|
|
3056
3056
|
return sorted.map((f) => `${f.relativePath}\0${f.content}`).join("");
|
|
3057
3057
|
}
|
|
3058
3058
|
|
|
3059
|
-
// src/lib/gateway-client.ts
|
|
3060
|
-
import { EventEmitter } from "events";
|
|
3061
|
-
import WebSocket from "ws";
|
|
3062
|
-
var DEFAULT_PORT = 18789;
|
|
3063
|
-
var RECONNECT_INITIAL_MS = 1e3;
|
|
3064
|
-
var RECONNECT_BASE_MS = 5e3;
|
|
3065
|
-
var RECONNECT_MAX_MS = 3e4;
|
|
3066
|
-
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
3067
|
-
var GatewayClient = class extends EventEmitter {
|
|
3068
|
-
port;
|
|
3069
|
-
token;
|
|
3070
|
-
ws = null;
|
|
3071
|
-
_connected = false;
|
|
3072
|
-
_everConnected = false;
|
|
3073
|
-
reconnectAttempts = 0;
|
|
3074
|
-
reconnectTimer = null;
|
|
3075
|
-
heartbeatTimer = null;
|
|
3076
|
-
pongReceived = true;
|
|
3077
|
-
intentionalClose = false;
|
|
3078
|
-
pendingRpc = /* @__PURE__ */ new Map();
|
|
3079
|
-
rpcSeq = 0;
|
|
3080
|
-
constructor(options = {}) {
|
|
3081
|
-
super();
|
|
3082
|
-
this.port = options.port ?? Number(process.env["OPENCLAW_GATEWAY_PORT"]) ?? DEFAULT_PORT;
|
|
3083
|
-
this.token = options.token ?? process.env["OPENCLAW_GATEWAY_TOKEN"];
|
|
3084
|
-
}
|
|
3085
|
-
get connected() {
|
|
3086
|
-
return this._connected;
|
|
3087
|
-
}
|
|
3088
|
-
connect() {
|
|
3089
|
-
this.intentionalClose = false;
|
|
3090
|
-
this.doConnect();
|
|
3091
|
-
}
|
|
3092
|
-
disconnect() {
|
|
3093
|
-
this.intentionalClose = true;
|
|
3094
|
-
this.clearTimers();
|
|
3095
|
-
if (this.ws) {
|
|
3096
|
-
this.ws.removeAllListeners();
|
|
3097
|
-
this.ws.close(1e3);
|
|
3098
|
-
this.ws = null;
|
|
3099
|
-
}
|
|
3100
|
-
if (this._connected) {
|
|
3101
|
-
this._connected = false;
|
|
3102
|
-
this.emit("disconnected");
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
// ── Private ──────────────────────────────────────────────────────────────
|
|
3106
|
-
doConnect() {
|
|
3107
|
-
const url = `ws://127.0.0.1:${this.port}`;
|
|
3108
|
-
try {
|
|
3109
|
-
const headers = {};
|
|
3110
|
-
if (this.token) {
|
|
3111
|
-
headers["Authorization"] = `Bearer ${this.token}`;
|
|
3112
|
-
}
|
|
3113
|
-
this.ws = new WebSocket(url, { headers });
|
|
3114
|
-
} catch (err) {
|
|
3115
|
-
this.emit("error", err);
|
|
3116
|
-
this.scheduleReconnect();
|
|
3117
|
-
return;
|
|
3118
|
-
}
|
|
3119
|
-
this.ws.on("open", () => {
|
|
3120
|
-
});
|
|
3121
|
-
this.ws.on("message", (data) => {
|
|
3122
|
-
try {
|
|
3123
|
-
const msg = JSON.parse(data.toString());
|
|
3124
|
-
this.handleMessage(msg);
|
|
3125
|
-
} catch {
|
|
3126
|
-
}
|
|
3127
|
-
});
|
|
3128
|
-
this.ws.on("close", (code, reason) => {
|
|
3129
|
-
this.clearHeartbeat();
|
|
3130
|
-
if (this._connected) {
|
|
3131
|
-
this._connected = false;
|
|
3132
|
-
this.emit("disconnected");
|
|
3133
|
-
} else if (!this._everConnected) {
|
|
3134
|
-
this.emit("error", new Error(`WebSocket closed before auth (code=${code}, reason=${reason?.toString() || "none"})`));
|
|
3135
|
-
}
|
|
3136
|
-
if (!this.intentionalClose) {
|
|
3137
|
-
this.scheduleReconnect();
|
|
3138
|
-
}
|
|
3139
|
-
});
|
|
3140
|
-
this.ws.on("error", (err) => {
|
|
3141
|
-
if (!this._everConnected && err.code === "ECONNREFUSED") {
|
|
3142
|
-
return;
|
|
3143
|
-
}
|
|
3144
|
-
this.emit("error", err);
|
|
3145
|
-
});
|
|
3146
|
-
this.ws.on("pong", () => {
|
|
3147
|
-
this.pongReceived = true;
|
|
3148
|
-
});
|
|
3149
|
-
}
|
|
3150
|
-
handleMessage(msg) {
|
|
3151
|
-
switch (msg.type) {
|
|
3152
|
-
case "challenge":
|
|
3153
|
-
this.sendJson({
|
|
3154
|
-
type: "connect",
|
|
3155
|
-
nonce: msg.nonce,
|
|
3156
|
-
role: "operator",
|
|
3157
|
-
scopes: ["events:read"]
|
|
3158
|
-
});
|
|
3159
|
-
break;
|
|
3160
|
-
case "hello-ok":
|
|
3161
|
-
this._connected = true;
|
|
3162
|
-
this._everConnected = true;
|
|
3163
|
-
this.reconnectAttempts = 0;
|
|
3164
|
-
this.startHeartbeat();
|
|
3165
|
-
this.emit("connected");
|
|
3166
|
-
break;
|
|
3167
|
-
case "event":
|
|
3168
|
-
this.emit("event", {
|
|
3169
|
-
type: "event",
|
|
3170
|
-
event: msg.event,
|
|
3171
|
-
payload: msg.payload,
|
|
3172
|
-
seq: msg.seq,
|
|
3173
|
-
stateVersion: msg.stateVersion
|
|
3174
|
-
});
|
|
3175
|
-
break;
|
|
3176
|
-
case "heartbeat":
|
|
3177
|
-
case "tick":
|
|
3178
|
-
break;
|
|
3179
|
-
case "rpc-result":
|
|
3180
|
-
case "rpc-error": {
|
|
3181
|
-
const rpcId = msg.id;
|
|
3182
|
-
const pending = this.pendingRpc.get(rpcId);
|
|
3183
|
-
if (pending) {
|
|
3184
|
-
this.pendingRpc.delete(rpcId);
|
|
3185
|
-
clearTimeout(pending.timer);
|
|
3186
|
-
if (msg.type === "rpc-error") {
|
|
3187
|
-
pending.reject(new Error(msg.error ?? "RPC error"));
|
|
3188
|
-
} else {
|
|
3189
|
-
pending.resolve(msg.result);
|
|
3190
|
-
}
|
|
3191
|
-
}
|
|
3192
|
-
break;
|
|
3193
|
-
}
|
|
3194
|
-
default:
|
|
3195
|
-
if (msg.id && typeof msg.id === "string") {
|
|
3196
|
-
const pending = this.pendingRpc.get(msg.id);
|
|
3197
|
-
if (pending) {
|
|
3198
|
-
this.pendingRpc.delete(msg.id);
|
|
3199
|
-
clearTimeout(pending.timer);
|
|
3200
|
-
if (msg.error) {
|
|
3201
|
-
pending.reject(new Error(String(msg.error)));
|
|
3202
|
-
} else {
|
|
3203
|
-
pending.resolve(msg);
|
|
3204
|
-
}
|
|
3205
|
-
}
|
|
3206
|
-
}
|
|
3207
|
-
break;
|
|
3208
|
-
}
|
|
3209
|
-
}
|
|
3210
|
-
/**
|
|
3211
|
-
* Send an RPC call to the gateway and wait for a response.
|
|
3212
|
-
* Returns the response payload or throws on timeout/error.
|
|
3213
|
-
*/
|
|
3214
|
-
sendRpc(method, params = {}, timeoutMs = 1e4) {
|
|
3215
|
-
return new Promise((resolve, reject) => {
|
|
3216
|
-
if (!this._connected || this.ws?.readyState !== WebSocket.OPEN) {
|
|
3217
|
-
reject(new Error("Gateway not connected"));
|
|
3218
|
-
return;
|
|
3219
|
-
}
|
|
3220
|
-
const id = `rpc-${++this.rpcSeq}-${Date.now()}`;
|
|
3221
|
-
const timer = setTimeout(() => {
|
|
3222
|
-
this.pendingRpc.delete(id);
|
|
3223
|
-
reject(new Error(`RPC ${method} timed out after ${timeoutMs}ms`));
|
|
3224
|
-
}, timeoutMs);
|
|
3225
|
-
this.pendingRpc.set(id, { resolve, reject, timer });
|
|
3226
|
-
this.sendJson({ type: "rpc", id, method, params });
|
|
3227
|
-
});
|
|
3228
|
-
}
|
|
3229
|
-
sendJson(obj) {
|
|
3230
|
-
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
3231
|
-
this.ws.send(JSON.stringify(obj));
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
startHeartbeat() {
|
|
3235
|
-
this.clearHeartbeat();
|
|
3236
|
-
this.pongReceived = true;
|
|
3237
|
-
this.heartbeatTimer = setInterval(() => {
|
|
3238
|
-
if (!this.pongReceived) {
|
|
3239
|
-
this.ws?.terminate();
|
|
3240
|
-
return;
|
|
3241
|
-
}
|
|
3242
|
-
this.pongReceived = false;
|
|
3243
|
-
this.ws?.ping();
|
|
3244
|
-
}, HEARTBEAT_INTERVAL_MS);
|
|
3245
|
-
}
|
|
3246
|
-
clearHeartbeat() {
|
|
3247
|
-
if (this.heartbeatTimer) {
|
|
3248
|
-
clearInterval(this.heartbeatTimer);
|
|
3249
|
-
this.heartbeatTimer = null;
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
scheduleReconnect() {
|
|
3253
|
-
if (this.intentionalClose) return;
|
|
3254
|
-
const delay = this.reconnectAttempts === 0 ? RECONNECT_INITIAL_MS : Math.min(RECONNECT_BASE_MS * Math.pow(2, this.reconnectAttempts - 1), RECONNECT_MAX_MS);
|
|
3255
|
-
this.reconnectAttempts++;
|
|
3256
|
-
this.reconnectTimer = setTimeout(() => {
|
|
3257
|
-
this.reconnectTimer = null;
|
|
3258
|
-
this.doConnect();
|
|
3259
|
-
}, delay);
|
|
3260
|
-
}
|
|
3261
|
-
clearTimers() {
|
|
3262
|
-
this.clearHeartbeat();
|
|
3263
|
-
if (this.reconnectTimer) {
|
|
3264
|
-
clearTimeout(this.reconnectTimer);
|
|
3265
|
-
this.reconnectTimer = null;
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
};
|
|
3269
|
-
var GatewayClientPool = class extends EventEmitter {
|
|
3270
|
-
clients = /* @__PURE__ */ new Map();
|
|
3271
|
-
addAgent(codeName, port, token) {
|
|
3272
|
-
if (this.clients.has(codeName)) {
|
|
3273
|
-
this.removeAgent(codeName);
|
|
3274
|
-
}
|
|
3275
|
-
const client2 = new GatewayClient({ port, token });
|
|
3276
|
-
client2.on("connected", () => {
|
|
3277
|
-
this.emit("connected", codeName);
|
|
3278
|
-
});
|
|
3279
|
-
client2.on("disconnected", () => {
|
|
3280
|
-
this.emit("disconnected", codeName);
|
|
3281
|
-
});
|
|
3282
|
-
client2.on("error", (err) => {
|
|
3283
|
-
this.emit("error", err, codeName);
|
|
3284
|
-
});
|
|
3285
|
-
client2.on("event", (evt) => {
|
|
3286
|
-
const pooledEvent = {
|
|
3287
|
-
...evt,
|
|
3288
|
-
agentCodeName: codeName
|
|
3289
|
-
};
|
|
3290
|
-
this.emit("event", pooledEvent);
|
|
3291
|
-
});
|
|
3292
|
-
this.clients.set(codeName, client2);
|
|
3293
|
-
client2.connect();
|
|
3294
|
-
}
|
|
3295
|
-
removeAgent(codeName) {
|
|
3296
|
-
const client2 = this.clients.get(codeName);
|
|
3297
|
-
if (client2) {
|
|
3298
|
-
client2.disconnect();
|
|
3299
|
-
this.clients.delete(codeName);
|
|
3300
|
-
}
|
|
3301
|
-
}
|
|
3302
|
-
hasAgent(codeName) {
|
|
3303
|
-
return this.clients.has(codeName);
|
|
3304
|
-
}
|
|
3305
|
-
isConnected(codeName) {
|
|
3306
|
-
return this.clients.get(codeName)?.connected ?? false;
|
|
3307
|
-
}
|
|
3308
|
-
/**
|
|
3309
|
-
* Send an RPC call to a specific agent's gateway.
|
|
3310
|
-
* Returns the response or throws on timeout/error/not connected.
|
|
3311
|
-
*/
|
|
3312
|
-
async sendRpc(codeName, method, params = {}, timeoutMs = 1e4) {
|
|
3313
|
-
const client2 = this.clients.get(codeName);
|
|
3314
|
-
if (!client2) throw new Error(`No gateway client for agent '${codeName}'`);
|
|
3315
|
-
return client2.sendRpc(method, params, timeoutMs);
|
|
3316
|
-
}
|
|
3317
|
-
disconnectAll() {
|
|
3318
|
-
for (const [, client2] of this.clients) {
|
|
3319
|
-
client2.disconnect();
|
|
3320
|
-
}
|
|
3321
|
-
this.clients.clear();
|
|
3322
|
-
}
|
|
3323
|
-
get size() {
|
|
3324
|
-
return this.clients.size;
|
|
3325
|
-
}
|
|
3326
|
-
};
|
|
3327
|
-
|
|
3328
3059
|
// src/lib/claude-auth-detect.ts
|
|
3329
3060
|
import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
|
|
3330
3061
|
import { homedir as homedir4, platform } from "os";
|
|
@@ -3932,15 +3663,6 @@ function hashFile(filePath) {
|
|
|
3932
3663
|
return null;
|
|
3933
3664
|
}
|
|
3934
3665
|
}
|
|
3935
|
-
async function execFilePromise(cmd, args) {
|
|
3936
|
-
const { execFile: ef } = await import("child_process");
|
|
3937
|
-
return new Promise((resolve, reject) => {
|
|
3938
|
-
ef(cmd, args, { timeout: 15e3 }, (err, stdout, stderr) => {
|
|
3939
|
-
if (err) reject(err);
|
|
3940
|
-
else resolve({ stdout, stderr });
|
|
3941
|
-
});
|
|
3942
|
-
});
|
|
3943
|
-
}
|
|
3944
3666
|
var ChildProcessError = class extends Error {
|
|
3945
3667
|
code;
|
|
3946
3668
|
stdout;
|
|
@@ -6080,11 +5802,6 @@ function applyRestartAcks(args) {
|
|
|
6080
5802
|
}
|
|
6081
5803
|
return changed;
|
|
6082
5804
|
}
|
|
6083
|
-
var GATEWAY_PORT_BASE = 18800;
|
|
6084
|
-
var GATEWAY_PORT_STEP = 10;
|
|
6085
|
-
var GATEWAY_PORT_MAX = 18899;
|
|
6086
|
-
var AUGMENTED_DIR = join16(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
6087
|
-
var GATEWAY_PORTS_FILE = join16(AUGMENTED_DIR, "gateway-ports.json");
|
|
6088
5805
|
var CHANNEL_SWEEP_INTERVAL_MS = (() => {
|
|
6089
5806
|
const raw = parseInt(process.env["AGT_CHANNEL_SWEEP_INTERVAL_MS"] ?? "", 10);
|
|
6090
5807
|
if (!Number.isFinite(raw)) return 5 * 60 * 1e3;
|
|
@@ -6819,21 +6536,17 @@ var managedToolkitIdByAgentAndServerId = /* @__PURE__ */ new Map();
|
|
|
6819
6536
|
function managedToolkitMapKey(agentId, serverId) {
|
|
6820
6537
|
return `${agentId}\0${serverId}`;
|
|
6821
6538
|
}
|
|
6822
|
-
var lastCronRunTs = /* @__PURE__ */ new Map();
|
|
6823
6539
|
var lastWorkTriggerAt = /* @__PURE__ */ new Map();
|
|
6824
6540
|
var alertedStaleItems = /* @__PURE__ */ new Set();
|
|
6825
6541
|
var stuckKanbanLogged = /* @__PURE__ */ new Set();
|
|
6826
|
-
var apiKeyStatusCache = /* @__PURE__ */ new Map();
|
|
6827
6542
|
var STALE_TASK_THRESHOLD_MS = (() => {
|
|
6828
6543
|
const env = process.env["AUGMENTED_STUCK_TASK_THRESHOLD_MINUTES"];
|
|
6829
6544
|
const minutes = env ? Number.parseInt(env, 10) : NaN;
|
|
6830
6545
|
if (Number.isFinite(minutes) && minutes > 0) return minutes * 60 * 1e3;
|
|
6831
6546
|
return 30 * 60 * 1e3;
|
|
6832
6547
|
})();
|
|
6833
|
-
var alertedJobs = /* @__PURE__ */ new Set();
|
|
6834
6548
|
var taskDisplayInfo = /* @__PURE__ */ new Map();
|
|
6835
6549
|
var activeChannels = /* @__PURE__ */ new Map();
|
|
6836
|
-
var gatewaysStartedThisCycle = /* @__PURE__ */ new Set();
|
|
6837
6550
|
var state6 = {
|
|
6838
6551
|
pid: process.pid,
|
|
6839
6552
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6852,7 +6565,6 @@ function resolveAgentFramework(codeName) {
|
|
|
6852
6565
|
const frameworkId = agentFrameworkCache.get(codeName) ?? DEFAULT_FRAMEWORK;
|
|
6853
6566
|
return getFramework(frameworkId);
|
|
6854
6567
|
}
|
|
6855
|
-
var gatewayPool = null;
|
|
6856
6568
|
function clearAgentCaches(agentId, codeName) {
|
|
6857
6569
|
const channelCacheMutated = clearAgentState(agentId, codeName);
|
|
6858
6570
|
agentChannelTokens.delete(codeName);
|
|
@@ -6878,7 +6590,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
6878
6590
|
var lastVersionCheckAt = 0;
|
|
6879
6591
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6880
6592
|
var lastResponsivenessProbeAt = 0;
|
|
6881
|
-
var agtCliVersion = true ? "0.28.
|
|
6593
|
+
var agtCliVersion = true ? "0.28.171" : "dev";
|
|
6882
6594
|
function resolveBrewPath(execFileSync4) {
|
|
6883
6595
|
try {
|
|
6884
6596
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -7556,37 +7268,6 @@ function resolveConversationEvalBackend() {
|
|
|
7556
7268
|
conversationEvalBackendSig = sig;
|
|
7557
7269
|
return conversationEvalBackend;
|
|
7558
7270
|
}
|
|
7559
|
-
function loadGatewayPorts() {
|
|
7560
|
-
try {
|
|
7561
|
-
return JSON.parse(readFileSync14(GATEWAY_PORTS_FILE, "utf-8"));
|
|
7562
|
-
} catch {
|
|
7563
|
-
return {};
|
|
7564
|
-
}
|
|
7565
|
-
}
|
|
7566
|
-
function saveGatewayPorts(ports) {
|
|
7567
|
-
mkdirSync6(AUGMENTED_DIR, { recursive: true });
|
|
7568
|
-
writeFileSync6(GATEWAY_PORTS_FILE, JSON.stringify(ports, null, 2));
|
|
7569
|
-
}
|
|
7570
|
-
function allocatePort(codeName) {
|
|
7571
|
-
const ports = loadGatewayPorts();
|
|
7572
|
-
if (ports[codeName]) return ports[codeName];
|
|
7573
|
-
const usedPorts = new Set(Object.values(ports));
|
|
7574
|
-
for (let port = GATEWAY_PORT_BASE; port <= GATEWAY_PORT_MAX; port += GATEWAY_PORT_STEP) {
|
|
7575
|
-
if (!usedPorts.has(port)) {
|
|
7576
|
-
ports[codeName] = port;
|
|
7577
|
-
saveGatewayPorts(ports);
|
|
7578
|
-
return port;
|
|
7579
|
-
}
|
|
7580
|
-
}
|
|
7581
|
-
throw new Error(`No free gateway ports in range ${GATEWAY_PORT_BASE}-${GATEWAY_PORT_MAX}`);
|
|
7582
|
-
}
|
|
7583
|
-
function freePort(codeName) {
|
|
7584
|
-
const ports = loadGatewayPorts();
|
|
7585
|
-
if (ports[codeName]) {
|
|
7586
|
-
delete ports[codeName];
|
|
7587
|
-
saveGatewayPorts(ports);
|
|
7588
|
-
}
|
|
7589
|
-
}
|
|
7590
7271
|
function getStateFile() {
|
|
7591
7272
|
return join16(config?.configDir ?? join16(process.env["HOME"] ?? "/tmp", ".augmented"), "manager-state.json");
|
|
7592
7273
|
}
|
|
@@ -7713,214 +7394,6 @@ ${SKILLS_INDEX_END}`;
|
|
|
7713
7394
|
log2(`Refreshed skills index in CLAUDE.md for '${codeName}' (${entries.length} skills)`);
|
|
7714
7395
|
}
|
|
7715
7396
|
}
|
|
7716
|
-
async function migrateToProfiles() {
|
|
7717
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
7718
|
-
const sharedConfigPath = join16(homeDir, ".openclaw", "openclaw.json");
|
|
7719
|
-
let sharedConfig;
|
|
7720
|
-
try {
|
|
7721
|
-
sharedConfig = JSON.parse(readFileSync14(sharedConfigPath, "utf-8"));
|
|
7722
|
-
} catch {
|
|
7723
|
-
return;
|
|
7724
|
-
}
|
|
7725
|
-
const agents = sharedConfig["agents"];
|
|
7726
|
-
const agentList = agents?.["list"] ?? [];
|
|
7727
|
-
if (agentList.length === 0) return;
|
|
7728
|
-
const adapter = getFramework(DEFAULT_FRAMEWORK);
|
|
7729
|
-
let migrated = 0;
|
|
7730
|
-
for (const agentEntry of agentList) {
|
|
7731
|
-
const codeName = agentEntry["id"];
|
|
7732
|
-
if (!codeName) continue;
|
|
7733
|
-
if (codeName === "main") continue;
|
|
7734
|
-
const profileDir = join16(homeDir, `.openclaw-${codeName}`);
|
|
7735
|
-
if (existsSync8(join16(profileDir, "openclaw.json"))) continue;
|
|
7736
|
-
log(`Migrating agent '${codeName}' to per-agent profile`);
|
|
7737
|
-
if (adapter.seedProfileConfig) {
|
|
7738
|
-
adapter.seedProfileConfig(codeName);
|
|
7739
|
-
}
|
|
7740
|
-
const sharedAuthDir = join16(homeDir, ".openclaw", "agents", codeName, "agent");
|
|
7741
|
-
const profileAuthDir = join16(profileDir, "agents", codeName, "agent");
|
|
7742
|
-
const authFile = join16(sharedAuthDir, "auth-profiles.json");
|
|
7743
|
-
if (existsSync8(authFile)) {
|
|
7744
|
-
mkdirSync6(profileAuthDir, { recursive: true });
|
|
7745
|
-
const authContent = readFileSync14(authFile, "utf-8");
|
|
7746
|
-
writeFileSync6(join16(profileAuthDir, "auth-profiles.json"), authContent);
|
|
7747
|
-
}
|
|
7748
|
-
allocatePort(codeName);
|
|
7749
|
-
migrated++;
|
|
7750
|
-
}
|
|
7751
|
-
if (migrated > 0) {
|
|
7752
|
-
log(`Migration complete: ${migrated} agent(s) migrated to per-agent profiles`);
|
|
7753
|
-
}
|
|
7754
|
-
}
|
|
7755
|
-
function readGatewayToken(codeName) {
|
|
7756
|
-
const adapter = resolveAgentFramework(codeName);
|
|
7757
|
-
if (adapter.readGatewayToken) {
|
|
7758
|
-
return adapter.readGatewayToken(codeName);
|
|
7759
|
-
}
|
|
7760
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
7761
|
-
try {
|
|
7762
|
-
const cfg = JSON.parse(readFileSync14(join16(homeDir, `.openclaw-${codeName}`, "openclaw.json"), "utf-8"));
|
|
7763
|
-
return cfg?.gateway?.auth?.token;
|
|
7764
|
-
} catch {
|
|
7765
|
-
return void 0;
|
|
7766
|
-
}
|
|
7767
|
-
}
|
|
7768
|
-
var GATEWAY_HUNG_TIMEOUT_MS = 5 * 6e4;
|
|
7769
|
-
function isGatewayHung(codeName) {
|
|
7770
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
7771
|
-
const jobsPath = join16(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
7772
|
-
if (!existsSync8(jobsPath)) return false;
|
|
7773
|
-
try {
|
|
7774
|
-
const data = JSON.parse(readFileSync14(jobsPath, "utf-8"));
|
|
7775
|
-
const jobs = data.jobs ?? data;
|
|
7776
|
-
if (!Array.isArray(jobs)) return false;
|
|
7777
|
-
const now = Date.now();
|
|
7778
|
-
for (const job of jobs) {
|
|
7779
|
-
const state7 = job.state;
|
|
7780
|
-
if (!state7) continue;
|
|
7781
|
-
const runStartedAt = state7.runStartedAtMs;
|
|
7782
|
-
const isRunning = state7.status === "running" || state7.running === true;
|
|
7783
|
-
if (isRunning && runStartedAt && now - runStartedAt > GATEWAY_HUNG_TIMEOUT_MS) {
|
|
7784
|
-
return true;
|
|
7785
|
-
}
|
|
7786
|
-
}
|
|
7787
|
-
} catch {
|
|
7788
|
-
}
|
|
7789
|
-
return false;
|
|
7790
|
-
}
|
|
7791
|
-
async function ensureGatewayRunning(codeName, adapter) {
|
|
7792
|
-
if (!adapter.isGatewayRunning || !adapter.startGateway) {
|
|
7793
|
-
return { pid: null, port: null, running: false };
|
|
7794
|
-
}
|
|
7795
|
-
const status = await adapter.isGatewayRunning(codeName);
|
|
7796
|
-
if (status.running) {
|
|
7797
|
-
if (await isGatewayHung(codeName)) {
|
|
7798
|
-
log(`Gateway for '${codeName}' appears hung (cron stuck >5min) \u2014 restarting`);
|
|
7799
|
-
if (adapter.stopGateway) {
|
|
7800
|
-
try {
|
|
7801
|
-
await adapter.stopGateway(codeName);
|
|
7802
|
-
} catch {
|
|
7803
|
-
}
|
|
7804
|
-
}
|
|
7805
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
7806
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
7807
|
-
const cronJobsPath = join16(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
7808
|
-
clearStaleCronRunState(cronJobsPath);
|
|
7809
|
-
} else {
|
|
7810
|
-
if (status.port) {
|
|
7811
|
-
try {
|
|
7812
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
7813
|
-
const configPath = join16(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
7814
|
-
if (existsSync8(configPath)) {
|
|
7815
|
-
const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
7816
|
-
if (cfg.gateway?.port !== status.port) {
|
|
7817
|
-
if (!cfg.gateway) cfg.gateway = {};
|
|
7818
|
-
cfg.gateway.port = status.port;
|
|
7819
|
-
writeFileSync6(configPath, JSON.stringify(cfg, null, 2));
|
|
7820
|
-
}
|
|
7821
|
-
}
|
|
7822
|
-
} catch {
|
|
7823
|
-
}
|
|
7824
|
-
}
|
|
7825
|
-
if (gatewayPool && status.port && !gatewayPool.hasAgent(codeName)) {
|
|
7826
|
-
const token = readGatewayToken(codeName);
|
|
7827
|
-
gatewayPool.addAgent(codeName, status.port, token);
|
|
7828
|
-
}
|
|
7829
|
-
return { pid: status.pid ?? null, port: status.port ?? null, running: true };
|
|
7830
|
-
}
|
|
7831
|
-
}
|
|
7832
|
-
const port = allocatePort(codeName);
|
|
7833
|
-
try {
|
|
7834
|
-
const result = await adapter.startGateway(codeName, port);
|
|
7835
|
-
log(`Gateway started for '${codeName}' on port ${port} (PID ${result.pid})`);
|
|
7836
|
-
gatewaysStartedThisCycle.add(codeName);
|
|
7837
|
-
try {
|
|
7838
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
7839
|
-
const configPath = join16(homeDir, `.openclaw-${codeName}`, "openclaw.json");
|
|
7840
|
-
if (existsSync8(configPath)) {
|
|
7841
|
-
const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
7842
|
-
if (!cfg.gateway) cfg.gateway = {};
|
|
7843
|
-
cfg.gateway.port = port;
|
|
7844
|
-
writeFileSync6(configPath, JSON.stringify(cfg, null, 2));
|
|
7845
|
-
}
|
|
7846
|
-
} catch {
|
|
7847
|
-
}
|
|
7848
|
-
if (gatewayPool) {
|
|
7849
|
-
const token = readGatewayToken(codeName);
|
|
7850
|
-
gatewayPool.addAgent(codeName, port, token);
|
|
7851
|
-
}
|
|
7852
|
-
return { pid: result.pid, port, running: true };
|
|
7853
|
-
} catch (err) {
|
|
7854
|
-
log(`Failed to start gateway for '${codeName}': ${err.message}`);
|
|
7855
|
-
return { pid: null, port, running: false };
|
|
7856
|
-
}
|
|
7857
|
-
}
|
|
7858
|
-
async function stopGatewayIfRunning(codeName, adapter) {
|
|
7859
|
-
if (!adapter.stopGateway) return;
|
|
7860
|
-
try {
|
|
7861
|
-
const stopped = await adapter.stopGateway(codeName);
|
|
7862
|
-
if (stopped) {
|
|
7863
|
-
log(`Gateway stopped for '${codeName}'`);
|
|
7864
|
-
}
|
|
7865
|
-
} catch (err) {
|
|
7866
|
-
log(`Failed to stop gateway for '${codeName}': ${err.message}`);
|
|
7867
|
-
}
|
|
7868
|
-
if (gatewayPool) {
|
|
7869
|
-
gatewayPool.removeAgent(codeName);
|
|
7870
|
-
}
|
|
7871
|
-
}
|
|
7872
|
-
async function stopAllGateways() {
|
|
7873
|
-
const ports = loadGatewayPorts();
|
|
7874
|
-
for (const codeName of Object.keys(ports)) {
|
|
7875
|
-
const adapter = resolveAgentFramework(codeName);
|
|
7876
|
-
await stopGatewayIfRunning(codeName, adapter);
|
|
7877
|
-
}
|
|
7878
|
-
if (gatewayPool) {
|
|
7879
|
-
gatewayPool.disconnectAll();
|
|
7880
|
-
}
|
|
7881
|
-
}
|
|
7882
|
-
async function healthCheckGateways(agentStates) {
|
|
7883
|
-
for (const agent of agentStates) {
|
|
7884
|
-
if (agent.status !== "active" || !agent.gatewayPort) continue;
|
|
7885
|
-
const adapter = resolveAgentFramework(agent.codeName);
|
|
7886
|
-
if (!adapter.isGatewayRunning || !adapter.startGateway) continue;
|
|
7887
|
-
if (gatewaysStartedThisCycle.has(agent.codeName)) continue;
|
|
7888
|
-
const status = await adapter.isGatewayRunning(agent.codeName);
|
|
7889
|
-
if (!status.running && agent.gatewayRunning) {
|
|
7890
|
-
const displayName = agentState.agentDisplayNames.get(agent.codeName) ?? agent.codeName;
|
|
7891
|
-
log(`Gateway for '${agent.codeName}' crashed, restarting...`);
|
|
7892
|
-
sendSlackWebhookMessage(
|
|
7893
|
-
`:red_circle: *Host Down* \u2014 *${displayName}* (\`${agent.codeName}\`)
|
|
7894
|
-
OpenClaw gateway crashed. Attempting automatic restart...`
|
|
7895
|
-
).catch(() => {
|
|
7896
|
-
});
|
|
7897
|
-
try {
|
|
7898
|
-
const result = await adapter.startGateway(agent.codeName, agent.gatewayPort);
|
|
7899
|
-
agent.gatewayPid = result.pid;
|
|
7900
|
-
agent.gatewayRunning = true;
|
|
7901
|
-
log(`Gateway restarted for '${agent.codeName}' (PID ${result.pid})`);
|
|
7902
|
-
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
7903
|
-
if (gatewayPool) {
|
|
7904
|
-
const token = readGatewayToken(agent.codeName);
|
|
7905
|
-
gatewayPool.addAgent(agent.codeName, agent.gatewayPort, token);
|
|
7906
|
-
}
|
|
7907
|
-
sendSlackWebhookMessage(
|
|
7908
|
-
`:large_green_circle: *Host Recovered* \u2014 *${displayName}* (\`${agent.codeName}\`)
|
|
7909
|
-
Gateway restarted successfully (PID ${result.pid}).`
|
|
7910
|
-
).catch(() => {
|
|
7911
|
-
});
|
|
7912
|
-
} catch (err) {
|
|
7913
|
-
agent.gatewayRunning = false;
|
|
7914
|
-
log(`Failed to restart gateway for '${agent.codeName}': ${err.message}`);
|
|
7915
|
-
sendSlackWebhookMessage(
|
|
7916
|
-
`:x: *Host Restart Failed* \u2014 *${displayName}* (\`${agent.codeName}\`)
|
|
7917
|
-
Automatic restart failed: ${err.message}`
|
|
7918
|
-
).catch(() => {
|
|
7919
|
-
});
|
|
7920
|
-
}
|
|
7921
|
-
}
|
|
7922
|
-
}
|
|
7923
|
-
}
|
|
7924
7397
|
var consecutivePollFailures = 0;
|
|
7925
7398
|
async function pollCycle() {
|
|
7926
7399
|
if (!config) return;
|
|
@@ -7991,7 +7464,6 @@ async function pollCycle() {
|
|
|
7991
7464
|
maybeUpgradeClaudeCode().catch((err) => log(`[claude-code-upgrade] Check failed: ${err.message}`));
|
|
7992
7465
|
try {
|
|
7993
7466
|
registeredAgentsCache.clear();
|
|
7994
|
-
gatewaysStartedThisCycle.clear();
|
|
7995
7467
|
const hostId = await getHostId();
|
|
7996
7468
|
if (!hostId) {
|
|
7997
7469
|
send({ type: "error", message: "Could not resolve host ID from API key" });
|
|
@@ -8011,7 +7483,7 @@ async function pollCycle() {
|
|
|
8011
7483
|
}
|
|
8012
7484
|
try {
|
|
8013
7485
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
8014
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
7486
|
+
const { collectDiagnostics } = await import("../persistent-session-DUKYMEOQ.js");
|
|
8015
7487
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
8016
7488
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
8017
7489
|
let tailscaleHostname;
|
|
@@ -8159,7 +7631,7 @@ async function pollCycle() {
|
|
|
8159
7631
|
const {
|
|
8160
7632
|
collectResponsivenessProbes,
|
|
8161
7633
|
getResponsivenessIntervalMs
|
|
8162
|
-
} = await import("../responsiveness-probe-
|
|
7634
|
+
} = await import("../responsiveness-probe-G5VMYV73.js");
|
|
8163
7635
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
8164
7636
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
8165
7637
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -8191,7 +7663,7 @@ async function pollCycle() {
|
|
|
8191
7663
|
collectResponsivenessProbes,
|
|
8192
7664
|
livePendingInboundOldestAgeSeconds,
|
|
8193
7665
|
parkPendingInbound
|
|
8194
|
-
} = await import("../responsiveness-probe-
|
|
7666
|
+
} = await import("../responsiveness-probe-G5VMYV73.js");
|
|
8195
7667
|
const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
8196
7668
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
8197
7669
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -8401,9 +7873,6 @@ async function pollCycle() {
|
|
|
8401
7873
|
lastProvisionAt: null,
|
|
8402
7874
|
lastDriftCheckAt: null,
|
|
8403
7875
|
lastSecretsProvisionAt: null,
|
|
8404
|
-
gatewayPort: null,
|
|
8405
|
-
gatewayPid: null,
|
|
8406
|
-
gatewayRunning: false,
|
|
8407
7876
|
acpSessions: []
|
|
8408
7877
|
});
|
|
8409
7878
|
}
|
|
@@ -8439,7 +7908,6 @@ async function pollCycle() {
|
|
|
8439
7908
|
if (!currentIds.has(prev.agentId)) {
|
|
8440
7909
|
log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
|
|
8441
7910
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
8442
|
-
await stopGatewayIfRunning(prev.codeName, adapter);
|
|
8443
7911
|
stopPersistentSessionAndForgetMcpBaseline(prev.codeName);
|
|
8444
7912
|
try {
|
|
8445
7913
|
const { execSync: es } = await import("child_process");
|
|
@@ -8447,7 +7915,6 @@ async function pollCycle() {
|
|
|
8447
7915
|
} catch {
|
|
8448
7916
|
}
|
|
8449
7917
|
killAgentChannelProcesses(prev.codeName, { log });
|
|
8450
|
-
freePort(prev.codeName);
|
|
8451
7918
|
const agentDir = join16(adapter.getAgentDir(prev.codeName), "provision");
|
|
8452
7919
|
await cleanupAgentFiles(prev.codeName, agentDir);
|
|
8453
7920
|
clearAgentCaches(prev.agentId, prev.codeName);
|
|
@@ -8461,7 +7928,6 @@ async function pollCycle() {
|
|
|
8461
7928
|
} catch (err) {
|
|
8462
7929
|
log(`[claude-pair] poll failed: ${err.message}`);
|
|
8463
7930
|
}
|
|
8464
|
-
await healthCheckGateways(agentStates);
|
|
8465
7931
|
if (Date.now() - lastChannelSweepAt >= CHANNEL_SWEEP_INTERVAL_MS) {
|
|
8466
7932
|
lastChannelSweepAt = Date.now();
|
|
8467
7933
|
const agentCodeNames = new Set(
|
|
@@ -8552,13 +8018,6 @@ async function pollCycle() {
|
|
|
8552
8018
|
healMode: process.env.AGT_INPUT_HEAL_MODE === "bare" ? "bare" : "disturb"
|
|
8553
8019
|
});
|
|
8554
8020
|
}
|
|
8555
|
-
const lastHealthCheck = lastHarvestAt.get("__cron_health__") ?? 0;
|
|
8556
|
-
if (Date.now() - lastHealthCheck >= HARVEST_INTERVAL_MS) {
|
|
8557
|
-
lastHarvestAt.set("__cron_health__", Date.now());
|
|
8558
|
-
monitorCronHealth(agentStates).catch((err) => {
|
|
8559
|
-
log(`Cron health monitor error: ${err.message}`);
|
|
8560
|
-
});
|
|
8561
|
-
}
|
|
8562
8021
|
healRealtimeSocketDivergence();
|
|
8563
8022
|
if (!isRealtimeConnected()) {
|
|
8564
8023
|
pollDirectChatMessages(agentStates).catch((err) => {
|
|
@@ -8681,7 +8140,6 @@ async function processAgent(agent, agentStates) {
|
|
|
8681
8140
|
} else if (killPausedCodeNames.delete(agent.code_name)) {
|
|
8682
8141
|
log(`[kill-switch] '${agent.code_name}' kill switch cleared while still ${agent.status} (no resume \u2014 paused for another reason)`);
|
|
8683
8142
|
}
|
|
8684
|
-
await stopGatewayIfRunning(agent.code_name, adapter);
|
|
8685
8143
|
stopPersistentSessionAndForgetMcpBaseline(agent.code_name);
|
|
8686
8144
|
try {
|
|
8687
8145
|
const { execSync: es } = await import("child_process");
|
|
@@ -8703,9 +8161,6 @@ async function processAgent(agent, agentStates) {
|
|
|
8703
8161
|
lastProvisionAt: null,
|
|
8704
8162
|
lastDriftCheckAt: null,
|
|
8705
8163
|
lastSecretsProvisionAt: null,
|
|
8706
|
-
gatewayPort: null,
|
|
8707
|
-
gatewayPid: null,
|
|
8708
|
-
gatewayRunning: false,
|
|
8709
8164
|
acpSessions: []
|
|
8710
8165
|
});
|
|
8711
8166
|
agentState.knownStatuses.set(agent.agent_id, agent.status);
|
|
@@ -8713,11 +8168,9 @@ async function processAgent(agent, agentStates) {
|
|
|
8713
8168
|
}
|
|
8714
8169
|
if (agent.status === "revoked") {
|
|
8715
8170
|
if (shouldSkipRevokedCleanup(previousKnownStatus)) {
|
|
8716
|
-
const ports = loadGatewayPorts();
|
|
8717
|
-
const gatewayLiveness = adapter.isGatewayRunning ? await adapter.isGatewayRunning(agent.code_name).catch(() => ({ running: false })) : { running: false };
|
|
8718
8171
|
const residuals = {
|
|
8719
|
-
gatewayRunning:
|
|
8720
|
-
portAllocated:
|
|
8172
|
+
gatewayRunning: false,
|
|
8173
|
+
portAllocated: false,
|
|
8721
8174
|
provisionDirExists: existsSync8(agentDir)
|
|
8722
8175
|
};
|
|
8723
8176
|
if (!hasRevokedResiduals(residuals)) {
|
|
@@ -8732,19 +8185,15 @@ async function processAgent(agent, agentStates) {
|
|
|
8732
8185
|
lastProvisionAt: null,
|
|
8733
8186
|
lastDriftCheckAt: null,
|
|
8734
8187
|
lastSecretsProvisionAt: null,
|
|
8735
|
-
gatewayPort: null,
|
|
8736
|
-
gatewayPid: null,
|
|
8737
|
-
gatewayRunning: false,
|
|
8738
8188
|
acpSessions: []
|
|
8739
8189
|
});
|
|
8740
8190
|
return;
|
|
8741
8191
|
}
|
|
8742
8192
|
log(
|
|
8743
|
-
`[revoked] residuals for '${agent.code_name}':
|
|
8193
|
+
`[revoked] residuals for '${agent.code_name}': dir=${residuals.provisionDirExists} \u2014 retrying cleanup`
|
|
8744
8194
|
);
|
|
8745
8195
|
}
|
|
8746
8196
|
log(`Agent '${agent.code_name}' is revoked, cleaning up`);
|
|
8747
|
-
await stopGatewayIfRunning(agent.code_name, adapter);
|
|
8748
8197
|
stopPersistentSessionAndForgetMcpBaseline(agent.code_name);
|
|
8749
8198
|
try {
|
|
8750
8199
|
const { execSync: es } = await import("child_process");
|
|
@@ -8752,7 +8201,6 @@ async function processAgent(agent, agentStates) {
|
|
|
8752
8201
|
} catch {
|
|
8753
8202
|
}
|
|
8754
8203
|
killAgentChannelProcesses(agent.code_name, { log });
|
|
8755
|
-
freePort(agent.code_name);
|
|
8756
8204
|
await cleanupAgentFiles(agent.code_name, agentDir);
|
|
8757
8205
|
clearAgentCaches(agent.agent_id, agent.code_name);
|
|
8758
8206
|
agentState.knownStatuses.set(agent.agent_id, agent.status);
|
|
@@ -8767,9 +8215,6 @@ async function processAgent(agent, agentStates) {
|
|
|
8767
8215
|
lastProvisionAt: null,
|
|
8768
8216
|
lastDriftCheckAt: null,
|
|
8769
8217
|
lastSecretsProvisionAt: null,
|
|
8770
|
-
gatewayPort: null,
|
|
8771
|
-
gatewayPid: null,
|
|
8772
|
-
gatewayRunning: false,
|
|
8773
8218
|
acpSessions: []
|
|
8774
8219
|
});
|
|
8775
8220
|
return;
|
|
@@ -8834,9 +8279,6 @@ async function processAgent(agent, agentStates) {
|
|
|
8834
8279
|
lastProvisionAt: null,
|
|
8835
8280
|
lastDriftCheckAt: null,
|
|
8836
8281
|
lastSecretsProvisionAt: null,
|
|
8837
|
-
gatewayPort: null,
|
|
8838
|
-
gatewayPid: null,
|
|
8839
|
-
gatewayRunning: false,
|
|
8840
8282
|
acpSessions: []
|
|
8841
8283
|
});
|
|
8842
8284
|
return;
|
|
@@ -8860,9 +8302,6 @@ async function processAgent(agent, agentStates) {
|
|
|
8860
8302
|
lastProvisionAt: null,
|
|
8861
8303
|
lastDriftCheckAt: null,
|
|
8862
8304
|
lastSecretsProvisionAt: null,
|
|
8863
|
-
gatewayPort: null,
|
|
8864
|
-
gatewayPid: null,
|
|
8865
|
-
gatewayRunning: false,
|
|
8866
8305
|
acpSessions: []
|
|
8867
8306
|
});
|
|
8868
8307
|
return;
|
|
@@ -9138,8 +8577,6 @@ async function processAgent(agent, agentStates) {
|
|
|
9138
8577
|
agentChannelTokens.delete(agent.code_name);
|
|
9139
8578
|
}
|
|
9140
8579
|
}
|
|
9141
|
-
let needsGatewayRestart = false;
|
|
9142
|
-
const hasChannelConfigs = refreshData.channel_configs && Object.keys(refreshData.channel_configs).length > 0;
|
|
9143
8580
|
if (refreshData.channel_configs && frameworkAdapter.writeChannelCredentials) {
|
|
9144
8581
|
if (agent.status === "active") {
|
|
9145
8582
|
for (const [channelId, entry] of Object.entries(refreshData.channel_configs)) {
|
|
@@ -9547,15 +8984,18 @@ async function processAgent(agent, agentStates) {
|
|
|
9547
8984
|
const integrationId = integration.id;
|
|
9548
8985
|
if (!integrationId) continue;
|
|
9549
8986
|
const refreshResult = await api.post(
|
|
9550
|
-
`/integrations
|
|
9551
|
-
{}
|
|
8987
|
+
`/host/agent-integrations/${integrationId}/credential`,
|
|
8988
|
+
{ agent_id: agent.agent_id }
|
|
9552
8989
|
);
|
|
9553
|
-
if (refreshResult.
|
|
9554
|
-
integration.credentials.
|
|
9555
|
-
if (refreshResult.
|
|
9556
|
-
integration.credentials.
|
|
8990
|
+
if (refreshResult.access_token) {
|
|
8991
|
+
const rotated = refreshResult.access_token !== integration.credentials.access_token || refreshResult.expires_at != null && refreshResult.expires_at !== integration.credentials.token_expires_at;
|
|
8992
|
+
if (refreshResult.expires_at) {
|
|
8993
|
+
integration.credentials.token_expires_at = refreshResult.expires_at;
|
|
8994
|
+
}
|
|
8995
|
+
integration.credentials.access_token = refreshResult.access_token;
|
|
8996
|
+
if (rotated) {
|
|
8997
|
+
log(`OAuth token refreshed for '${agent.code_name}/${integration.definition_id}'`);
|
|
9557
8998
|
}
|
|
9558
|
-
log(`OAuth token refreshed for '${agent.code_name}/${integration.definition_id}'`);
|
|
9559
8999
|
if (frameworkAdapter.writeTokenFile) {
|
|
9560
9000
|
frameworkAdapter.writeTokenFile(agent.code_name, integrations);
|
|
9561
9001
|
}
|
|
@@ -9637,7 +9077,6 @@ async function processAgent(agent, agentStates) {
|
|
|
9637
9077
|
if (rotationHandled) {
|
|
9638
9078
|
agentState.knownIntegrationHashes.set(agent.agent_id, intHash);
|
|
9639
9079
|
}
|
|
9640
|
-
needsGatewayRestart = true;
|
|
9641
9080
|
}
|
|
9642
9081
|
}
|
|
9643
9082
|
const fwForMcp = agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK;
|
|
@@ -9744,17 +9183,6 @@ async function processAgent(agent, agentStates) {
|
|
|
9744
9183
|
} catch (err) {
|
|
9745
9184
|
log(`Integration provisioning failed for '${agent.code_name}': ${err.message}`);
|
|
9746
9185
|
}
|
|
9747
|
-
let gatewayPort = null;
|
|
9748
|
-
let gatewayPid = null;
|
|
9749
|
-
let gatewayRunning = false;
|
|
9750
|
-
if (agent.status === "active" && hasChannelConfigs) {
|
|
9751
|
-
const gwStatus = await ensureGatewayRunning(agent.code_name, frameworkAdapter);
|
|
9752
|
-
gatewayPort = gwStatus.port;
|
|
9753
|
-
gatewayPid = gwStatus.pid;
|
|
9754
|
-
gatewayRunning = gwStatus.running;
|
|
9755
|
-
} else if (agent.status === "paused") {
|
|
9756
|
-
await stopGatewayIfRunning(agent.code_name, frameworkAdapter);
|
|
9757
|
-
}
|
|
9758
9186
|
let tasks = refreshData.scheduled_tasks ?? [];
|
|
9759
9187
|
const existingTemplateIds = new Set(tasks.map((t) => t.template_id));
|
|
9760
9188
|
const kanbanWorkRetired = (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code" && agentSessionMode === "persistent";
|
|
@@ -9786,20 +9214,6 @@ async function processAgent(agent, agentStates) {
|
|
|
9786
9214
|
tasks = tasks.filter((t) => t.template_id !== "kanban-work");
|
|
9787
9215
|
}
|
|
9788
9216
|
if (agent.status === "active") {
|
|
9789
|
-
if (frameworkAdapter.installPlugin) {
|
|
9790
|
-
try {
|
|
9791
|
-
const pluginPath = join16(process.cwd(), "packages", "openclaw-plugin-augmented", "src", "index.ts");
|
|
9792
|
-
if (existsSync8(pluginPath)) {
|
|
9793
|
-
frameworkAdapter.installPlugin(agent.code_name, "augmented", pluginPath, {
|
|
9794
|
-
agtHost: requireHost(),
|
|
9795
|
-
agtApiKey: getApiKey() ?? void 0,
|
|
9796
|
-
agentId: agent.agent_id
|
|
9797
|
-
});
|
|
9798
|
-
}
|
|
9799
|
-
} catch (err) {
|
|
9800
|
-
log(`Augmented plugin install failed for '${agent.code_name}': ${err.message}`);
|
|
9801
|
-
}
|
|
9802
|
-
}
|
|
9803
9217
|
if (frameworkAdapter.installSkillFiles) {
|
|
9804
9218
|
try {
|
|
9805
9219
|
const skillContent = getBuiltInSkillContent("kanban");
|
|
@@ -9862,8 +9276,6 @@ async function processAgent(agent, agentStates) {
|
|
|
9862
9276
|
join16(homedir10(), ".augmented", agent.code_name, "skills"),
|
|
9863
9277
|
// Claude Code — project tree
|
|
9864
9278
|
join16(homedir10(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
9865
|
-
// OpenClaw — framework runtime tree
|
|
9866
|
-
join16(homedir10(), `.openclaw-${agent.code_name}`, "skills"),
|
|
9867
9279
|
// Defensive: legacy provision-side path, not currently an
|
|
9868
9280
|
// install target but cheap to sweep.
|
|
9869
9281
|
join16(agentDir, ".claude", "skills")
|
|
@@ -9915,7 +9327,6 @@ async function processAgent(agent, agentStates) {
|
|
|
9915
9327
|
const globalSkillDirs = [
|
|
9916
9328
|
join16(homedir10(), ".augmented", agent.code_name, "skills"),
|
|
9917
9329
|
join16(homedir10(), ".augmented", agent.code_name, "project", ".claude", "skills"),
|
|
9918
|
-
join16(homedir10(), `.openclaw-${agent.code_name}`, "skills"),
|
|
9919
9330
|
join16(agentDir, ".claude", "skills")
|
|
9920
9331
|
];
|
|
9921
9332
|
for (const id of plan.removes) {
|
|
@@ -10239,72 +9650,6 @@ async function processAgent(agent, agentStates) {
|
|
|
10239
9650
|
}
|
|
10240
9651
|
} else if (agentFw === "claude-code" && tasks.length > 0) {
|
|
10241
9652
|
await syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData);
|
|
10242
|
-
} else if (frameworkAdapter.syncScheduledTasks && gatewayRunning && gatewayPort) {
|
|
10243
|
-
const stableTasksHash = createHash10("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
10244
|
-
const boardHash = boardItems.length > 0 ? createHash10("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
|
|
10245
|
-
const resolvedModels = resolveModelChain(refreshData);
|
|
10246
|
-
const modelsHash = createHash10("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
|
|
10247
|
-
const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
|
|
10248
|
-
const prevTasksHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
10249
|
-
if (combinedHash !== prevTasksHash) {
|
|
10250
|
-
const enrichedTasks = tasks.map((t) => {
|
|
10251
|
-
if (BOARD_INJECT_TEMPLATES.has(t.template_id) && boardItems.length > 0) {
|
|
10252
|
-
const template = PLAN_TEMPLATES.has(t.template_id) ? "morning-plan" : "follow-up";
|
|
10253
|
-
const boardPrefix = formatBoardForPrompt(boardItems, template);
|
|
10254
|
-
return { ...t, prompt: boardPrefix + t.prompt };
|
|
10255
|
-
}
|
|
10256
|
-
return t;
|
|
10257
|
-
});
|
|
10258
|
-
try {
|
|
10259
|
-
const token = readGatewayToken(agent.code_name);
|
|
10260
|
-
await frameworkAdapter.syncScheduledTasks(
|
|
10261
|
-
agent.code_name,
|
|
10262
|
-
enrichedTasks.map((t) => ({
|
|
10263
|
-
id: t.id,
|
|
10264
|
-
template_id: t.template_id,
|
|
10265
|
-
name: t.name,
|
|
10266
|
-
schedule_kind: t.schedule_kind,
|
|
10267
|
-
schedule_expr: t.schedule_expr,
|
|
10268
|
-
schedule_every: t.schedule_every,
|
|
10269
|
-
schedule_at: t.schedule_at,
|
|
10270
|
-
timezone: t.timezone,
|
|
10271
|
-
prompt: t.prompt,
|
|
10272
|
-
session_target: t.session_target,
|
|
10273
|
-
delivery_mode: t.delivery_mode,
|
|
10274
|
-
delivery_channel: t.delivery_channel,
|
|
10275
|
-
delivery_to: t.delivery_to,
|
|
10276
|
-
enabled: t.enabled,
|
|
10277
|
-
model_tier: t.model_tier ?? "primary"
|
|
10278
|
-
})),
|
|
10279
|
-
gatewayPort,
|
|
10280
|
-
token,
|
|
10281
|
-
{
|
|
10282
|
-
models: resolvedModels
|
|
10283
|
-
}
|
|
10284
|
-
);
|
|
10285
|
-
agentState.knownTasksHashes.set(agent.agent_id, combinedHash);
|
|
10286
|
-
log(`Scheduled tasks synced for '${agent.code_name}' (${enrichedTasks.length} task(s))`);
|
|
10287
|
-
} catch (err) {
|
|
10288
|
-
log(`Failed to sync scheduled tasks for '${agent.code_name}': ${err.message}`);
|
|
10289
|
-
}
|
|
10290
|
-
}
|
|
10291
|
-
}
|
|
10292
|
-
for (const t of tasks) {
|
|
10293
|
-
const jobName = `aug:${t.template_id}:${t.id ?? t.name.toLowerCase().replace(/\s+/g, "-")}`;
|
|
10294
|
-
taskDisplayInfo.set(`${agent.code_name}:${jobName}`, {
|
|
10295
|
-
taskName: t.name,
|
|
10296
|
-
schedule: t.schedule_expr ?? t.schedule_every ?? "",
|
|
10297
|
-
agentDisplayName: agent.display_name
|
|
10298
|
-
});
|
|
10299
|
-
}
|
|
10300
|
-
if (agentFw === "openclaw" && gatewayRunning && gatewayPort && tasks.length > 0) {
|
|
10301
|
-
const lastHarvest = lastHarvestAt.get(agent.code_name) ?? 0;
|
|
10302
|
-
if (Date.now() - lastHarvest >= HARVEST_INTERVAL_MS) {
|
|
10303
|
-
lastHarvestAt.set(agent.code_name, Date.now());
|
|
10304
|
-
harvestCronResults(agent.code_name, tasks, gatewayPort).catch((err) => {
|
|
10305
|
-
log(`Cron result harvest failed for '${agent.code_name}': ${err.message}`);
|
|
10306
|
-
});
|
|
10307
|
-
}
|
|
10308
9653
|
}
|
|
10309
9654
|
{
|
|
10310
9655
|
const triggerAt = refreshData.agent.work_trigger_at;
|
|
@@ -10313,24 +9658,7 @@ async function processAgent(agent, agentStates) {
|
|
|
10313
9658
|
const lastTrigger = lastWorkTriggerAt.get(agent.code_name) ?? 0;
|
|
10314
9659
|
if (triggerTs > lastTrigger) {
|
|
10315
9660
|
lastWorkTriggerAt.set(agent.code_name, triggerTs);
|
|
10316
|
-
if (agentFw === "
|
|
10317
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
10318
|
-
const jobsPath = join16(homeDir, `.openclaw-${agent.code_name}`, "cron", "jobs.json");
|
|
10319
|
-
if (existsSync8(jobsPath)) {
|
|
10320
|
-
try {
|
|
10321
|
-
const jobsData = JSON.parse(readFileSync14(jobsPath, "utf-8"));
|
|
10322
|
-
const kanbanJob = (jobsData.jobs ?? []).find(
|
|
10323
|
-
(j) => typeof j.name === "string" && j.name.includes("kanban-work")
|
|
10324
|
-
);
|
|
10325
|
-
if (kanbanJob?.id) {
|
|
10326
|
-
const cliBin = resolveAgentFramework(agent.code_name).cliBinary ?? "claude";
|
|
10327
|
-
log(`Work trigger: firing kanban-work for '${agent.code_name}'`);
|
|
10328
|
-
execFilePromise(cliBin, ["--profile", agent.code_name, "cron", "run", kanbanJob.id]).then(() => log(`Work trigger succeeded for '${agent.code_name}'`)).catch((err) => log(`Work trigger failed for '${agent.code_name}': ${err.message}`));
|
|
10329
|
-
}
|
|
10330
|
-
} catch {
|
|
10331
|
-
}
|
|
10332
|
-
}
|
|
10333
|
-
} else if (agentFw === "claude-code") {
|
|
9661
|
+
if (agentFw === "claude-code") {
|
|
10334
9662
|
if (sessionMode === "persistent") {
|
|
10335
9663
|
if (isSessionHealthy(agent.code_name)) {
|
|
10336
9664
|
const todayItem = boardItems.find((b) => b.status === "todo");
|
|
@@ -10347,9 +9675,6 @@ async function processAgent(agent, agentStates) {
|
|
|
10347
9675
|
}
|
|
10348
9676
|
}
|
|
10349
9677
|
}
|
|
10350
|
-
if (agentFw === "openclaw") {
|
|
10351
|
-
cleanupStaleSessions(agent.code_name);
|
|
10352
|
-
}
|
|
10353
9678
|
{
|
|
10354
9679
|
const agentId = agentState.codeNameToAgentId.get(agent.code_name);
|
|
10355
9680
|
if (agentId) {
|
|
@@ -10516,143 +9841,9 @@ In progress for ${age} minutes \u2014 auto-failed`).catch(() => {
|
|
|
10516
9841
|
lastProvisionAt,
|
|
10517
9842
|
lastDriftCheckAt,
|
|
10518
9843
|
lastSecretsProvisionAt,
|
|
10519
|
-
gatewayPort,
|
|
10520
|
-
gatewayPid,
|
|
10521
|
-
gatewayRunning,
|
|
10522
9844
|
acpSessions: []
|
|
10523
9845
|
});
|
|
10524
9846
|
}
|
|
10525
|
-
var CRON_SESSION_KEEP_COUNT = 10;
|
|
10526
|
-
var CRON_RUN_RETENTION_DAYS = 7;
|
|
10527
|
-
var lastCleanupAt = /* @__PURE__ */ new Map();
|
|
10528
|
-
var CLEANUP_INTERVAL_MS = 6e4;
|
|
10529
|
-
function cleanupStaleSessions(codeName) {
|
|
10530
|
-
const lastRun = lastCleanupAt.get(codeName) ?? 0;
|
|
10531
|
-
if (lastRun > 0 && Date.now() - lastRun < CLEANUP_INTERVAL_MS) return;
|
|
10532
|
-
lastCleanupAt.set(codeName, Date.now());
|
|
10533
|
-
const homeDir = process.env["HOME"] ?? "/tmp";
|
|
10534
|
-
for (const agentDir of ["main", codeName]) {
|
|
10535
|
-
const sessionsDir = join16(homeDir, `.openclaw-${codeName}`, "agents", agentDir, "sessions");
|
|
10536
|
-
cleanupCronSessions(sessionsDir, CRON_SESSION_KEEP_COUNT);
|
|
10537
|
-
}
|
|
10538
|
-
const cronRunsDir = join16(homeDir, `.openclaw-${codeName}`, "cron", "runs");
|
|
10539
|
-
cleanupOldFiles(cronRunsDir, CRON_RUN_RETENTION_DAYS, ".jsonl");
|
|
10540
|
-
const cronJobsPath = join16(homeDir, `.openclaw-${codeName}`, "cron", "jobs.json");
|
|
10541
|
-
clearStaleCronRunState(cronJobsPath);
|
|
10542
|
-
}
|
|
10543
|
-
function cleanupCronSessions(sessionsDir, keepCount) {
|
|
10544
|
-
const indexPath = join16(sessionsDir, "sessions.json");
|
|
10545
|
-
if (!existsSync8(indexPath)) return;
|
|
10546
|
-
try {
|
|
10547
|
-
const raw = readFileSync14(indexPath, "utf-8");
|
|
10548
|
-
const index = JSON.parse(raw);
|
|
10549
|
-
const cronRunKeys = Object.keys(index).filter((k) => k.includes(":cron:") && k.includes(":run:")).map((k) => ({
|
|
10550
|
-
key: k,
|
|
10551
|
-
sessionId: index[k]?.sessionId,
|
|
10552
|
-
updatedAt: index[k]?.updatedAt ?? 0
|
|
10553
|
-
})).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
10554
|
-
if (cronRunKeys.length <= keepCount) return;
|
|
10555
|
-
const toDelete = cronRunKeys.slice(keepCount);
|
|
10556
|
-
let deletedFiles = 0;
|
|
10557
|
-
for (const entry of toDelete) {
|
|
10558
|
-
delete index[entry.key];
|
|
10559
|
-
if (entry.sessionId) {
|
|
10560
|
-
const sessionFile = join16(sessionsDir, `${entry.sessionId}.jsonl`);
|
|
10561
|
-
try {
|
|
10562
|
-
if (existsSync8(sessionFile)) {
|
|
10563
|
-
unlinkSync(sessionFile);
|
|
10564
|
-
deletedFiles++;
|
|
10565
|
-
}
|
|
10566
|
-
} catch {
|
|
10567
|
-
}
|
|
10568
|
-
}
|
|
10569
|
-
}
|
|
10570
|
-
const cronParentKeys = Object.keys(index).filter(
|
|
10571
|
-
(k) => k.includes(":cron:") && !k.includes(":run:") && k !== "agent:main:main"
|
|
10572
|
-
);
|
|
10573
|
-
for (const parentKey of cronParentKeys) {
|
|
10574
|
-
const hasRuns = Object.keys(index).some(
|
|
10575
|
-
(k) => k.startsWith(parentKey + ":run:")
|
|
10576
|
-
);
|
|
10577
|
-
if (!hasRuns) {
|
|
10578
|
-
const parentSessionId = index[parentKey]?.sessionId;
|
|
10579
|
-
delete index[parentKey];
|
|
10580
|
-
if (parentSessionId) {
|
|
10581
|
-
try {
|
|
10582
|
-
const f = join16(sessionsDir, `${parentSessionId}.jsonl`);
|
|
10583
|
-
if (existsSync8(f)) {
|
|
10584
|
-
unlinkSync(f);
|
|
10585
|
-
deletedFiles++;
|
|
10586
|
-
}
|
|
10587
|
-
} catch {
|
|
10588
|
-
}
|
|
10589
|
-
}
|
|
10590
|
-
}
|
|
10591
|
-
}
|
|
10592
|
-
writeFileSync6(indexPath, JSON.stringify(index));
|
|
10593
|
-
if (toDelete.length > 0) {
|
|
10594
|
-
log(`Cleaned ${toDelete.length} cron session(s) and ${deletedFiles} file(s) from ${sessionsDir}`);
|
|
10595
|
-
}
|
|
10596
|
-
} catch {
|
|
10597
|
-
}
|
|
10598
|
-
}
|
|
10599
|
-
var STALE_RUN_TIMEOUT_MS = 5 * 6e4;
|
|
10600
|
-
function clearStaleCronRunState(jobsPath) {
|
|
10601
|
-
if (!existsSync8(jobsPath)) return;
|
|
10602
|
-
try {
|
|
10603
|
-
const raw = readFileSync14(jobsPath, "utf-8");
|
|
10604
|
-
const data = JSON.parse(raw);
|
|
10605
|
-
const jobs = data.jobs ?? data;
|
|
10606
|
-
if (!Array.isArray(jobs)) return;
|
|
10607
|
-
let changed = false;
|
|
10608
|
-
const now = Date.now();
|
|
10609
|
-
for (const job of jobs) {
|
|
10610
|
-
const state7 = job.state;
|
|
10611
|
-
if (!state7) continue;
|
|
10612
|
-
const runStartedAt = state7.runningAtMs ?? state7.runStartedAtMs;
|
|
10613
|
-
const isRunning = state7.running === true || state7.status === "running";
|
|
10614
|
-
if (isRunning && runStartedAt && now - runStartedAt > STALE_RUN_TIMEOUT_MS) {
|
|
10615
|
-
state7.running = false;
|
|
10616
|
-
delete state7.status;
|
|
10617
|
-
delete state7.runStartedAtMs;
|
|
10618
|
-
delete state7.currentRunId;
|
|
10619
|
-
changed = true;
|
|
10620
|
-
log(`Cleared stale running state for cron job '${job.name}' (stuck for ${Math.round((now - runStartedAt) / 6e4)}min)`);
|
|
10621
|
-
} else if (isRunning && !runStartedAt) {
|
|
10622
|
-
state7.running = false;
|
|
10623
|
-
changed = true;
|
|
10624
|
-
log(`Cleared stale running state for cron job '${job.name}' (no start timestamp)`);
|
|
10625
|
-
}
|
|
10626
|
-
}
|
|
10627
|
-
if (changed) {
|
|
10628
|
-
writeFileSync6(jobsPath, JSON.stringify(data, null, 2));
|
|
10629
|
-
}
|
|
10630
|
-
} catch {
|
|
10631
|
-
}
|
|
10632
|
-
}
|
|
10633
|
-
function cleanupOldFiles(dir, maxAgeDays, ext) {
|
|
10634
|
-
if (!existsSync8(dir)) return;
|
|
10635
|
-
const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1e3;
|
|
10636
|
-
let removed = 0;
|
|
10637
|
-
try {
|
|
10638
|
-
for (const f of readdirSync5(dir)) {
|
|
10639
|
-
if (!f.endsWith(ext)) continue;
|
|
10640
|
-
const fullPath = join16(dir, f);
|
|
10641
|
-
try {
|
|
10642
|
-
const st = statSync4(fullPath);
|
|
10643
|
-
if (st.mtimeMs < cutoff) {
|
|
10644
|
-
unlinkSync(fullPath);
|
|
10645
|
-
removed++;
|
|
10646
|
-
}
|
|
10647
|
-
} catch {
|
|
10648
|
-
}
|
|
10649
|
-
}
|
|
10650
|
-
if (removed > 0) {
|
|
10651
|
-
log(`Cleaned ${removed} old cron run log(s) from ${dir}`);
|
|
10652
|
-
}
|
|
10653
|
-
} catch {
|
|
10654
|
-
}
|
|
10655
|
-
}
|
|
10656
9847
|
var lastMcpFailedBannerCount = /* @__PURE__ */ new Map();
|
|
10657
9848
|
var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
|
|
10658
9849
|
var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
|
|
@@ -11263,8 +10454,6 @@ var directChatInFlight = /* @__PURE__ */ new Set();
|
|
|
11263
10454
|
async function pollDirectChatMessages(agentStates) {
|
|
11264
10455
|
for (const agent of agentStates) {
|
|
11265
10456
|
if (agent.status !== "active") continue;
|
|
11266
|
-
const fw = agentFrameworkCache.get(agent.codeName) ?? DEFAULT_FRAMEWORK;
|
|
11267
|
-
if (fw === "openclaw" && (!agent.gatewayRunning || !agent.gatewayPort)) continue;
|
|
11268
10457
|
try {
|
|
11269
10458
|
const data = await api.post("/host/direct-chat/poll", { agent_id: agent.agentId });
|
|
11270
10459
|
for (const msg of data.messages) {
|
|
@@ -11329,51 +10518,7 @@ ${escapeXml(msg.content)}
|
|
|
11329
10518
|
}
|
|
11330
10519
|
log(`[direct-chat] Inject reported unverified for '${agent.codeName}' (msg=${msg.id}) \u2014 leaving pending for durable replay`);
|
|
11331
10520
|
}
|
|
11332
|
-
|
|
11333
|
-
log(`[direct-chat] No in-session delivery for '${agent.codeName}' (msg=${msg.id}) \u2014 leaving pending for ENG-5927 durable replay`);
|
|
11334
|
-
return;
|
|
11335
|
-
}
|
|
11336
|
-
try {
|
|
11337
|
-
const { stdout } = await execFilePromiseLong("openclaw", [
|
|
11338
|
-
"--profile",
|
|
11339
|
-
agent.codeName,
|
|
11340
|
-
"agent",
|
|
11341
|
-
"--local",
|
|
11342
|
-
"--agent",
|
|
11343
|
-
agent.codeName,
|
|
11344
|
-
"--message",
|
|
11345
|
-
msg.content,
|
|
11346
|
-
"--session-id",
|
|
11347
|
-
msg.session_id,
|
|
11348
|
-
"--json"
|
|
11349
|
-
]);
|
|
11350
|
-
let reply;
|
|
11351
|
-
try {
|
|
11352
|
-
const parsed = JSON.parse(stdout);
|
|
11353
|
-
const payloads = parsed?.payloads ?? parsed?.result?.payloads;
|
|
11354
|
-
reply = payloads?.[0]?.text ?? parsed?.reply ?? parsed?.text ?? parsed?.message ?? stdout;
|
|
11355
|
-
} catch {
|
|
11356
|
-
reply = stdout.trim() || "[No response from agent]";
|
|
11357
|
-
}
|
|
11358
|
-
await api.post("/host/direct-chat/reply", {
|
|
11359
|
-
agent_id: agent.agentId,
|
|
11360
|
-
session_id: msg.session_id,
|
|
11361
|
-
content: reply
|
|
11362
|
-
});
|
|
11363
|
-
log(`[direct-chat] Reply sent for '${agent.codeName}'`);
|
|
11364
|
-
} catch (err) {
|
|
11365
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
11366
|
-
const errorId = createHash10("sha256").update(errMsg).digest("hex").slice(0, 12);
|
|
11367
|
-
log(`[direct-chat] Failed to process message for '${agent.codeName}': error_id=${errorId} error=${errMsg.slice(0, 500)}`);
|
|
11368
|
-
try {
|
|
11369
|
-
await api.post("/host/direct-chat/reply", {
|
|
11370
|
-
agent_id: agent.agentId,
|
|
11371
|
-
session_id: msg.session_id,
|
|
11372
|
-
content: `[Error] Failed to process message (ref: ${errorId}). Please retry.`
|
|
11373
|
-
});
|
|
11374
|
-
} catch {
|
|
11375
|
-
}
|
|
11376
|
-
}
|
|
10521
|
+
log(`[direct-chat] No in-session delivery for '${agent.codeName}' (msg=${msg.id}) \u2014 leaving pending for ENG-5927 durable replay`);
|
|
11377
10522
|
}
|
|
11378
10523
|
var lastKanbanInjectAt = /* @__PURE__ */ new Map();
|
|
11379
10524
|
var openInjectedRunByCode = /* @__PURE__ */ new Map();
|
|
@@ -11477,205 +10622,6 @@ var lastHarvestAt = /* @__PURE__ */ new Map();
|
|
|
11477
10622
|
var HARVEST_INTERVAL_MS = 3 * 60 * 1e3;
|
|
11478
10623
|
var kanbanBoardCache = /* @__PURE__ */ new Map();
|
|
11479
10624
|
var notifyBoardCache = /* @__PURE__ */ new Map();
|
|
11480
|
-
async function harvestCronResults(codeName, tasks, gatewayPort) {
|
|
11481
|
-
const token = readGatewayToken(codeName);
|
|
11482
|
-
const gwArgs = ["--url", `ws://127.0.0.1:${gatewayPort}`, ...token ? ["--token", token] : []];
|
|
11483
|
-
let gatewayJobs = [];
|
|
11484
|
-
try {
|
|
11485
|
-
const cliBin = resolveAgentFramework(codeName).cliBinary ?? "claude";
|
|
11486
|
-
const { stdout } = await execFilePromise(cliBin, ["--profile", codeName, "cron", "list", "--json", ...gwArgs]);
|
|
11487
|
-
const parsed = JSON.parse(stdout);
|
|
11488
|
-
gatewayJobs = parsed.jobs ?? [];
|
|
11489
|
-
} catch {
|
|
11490
|
-
return;
|
|
11491
|
-
}
|
|
11492
|
-
const jobTemplateMap = /* @__PURE__ */ new Map();
|
|
11493
|
-
for (const job of gatewayJobs) {
|
|
11494
|
-
if (!job.name.startsWith("aug:")) continue;
|
|
11495
|
-
const parts = job.name.split(":");
|
|
11496
|
-
if (parts.length >= 3) {
|
|
11497
|
-
jobTemplateMap.set(job.id, parts[1]);
|
|
11498
|
-
}
|
|
11499
|
-
}
|
|
11500
|
-
for (const [jobId, templateId] of jobTemplateMap) {
|
|
11501
|
-
if (!STANDUP_TEMPLATES.has(templateId) && !TASK_UPDATE_TEMPLATES.has(templateId) && !PLAN_TEMPLATES.has(templateId) && !KANBAN_WORK_TEMPLATES.has(templateId)) continue;
|
|
11502
|
-
let runs = [];
|
|
11503
|
-
try {
|
|
11504
|
-
const cliBin2 = resolveAgentFramework(codeName).cliBinary ?? "claude";
|
|
11505
|
-
const { stdout } = await execFilePromise(cliBin2, ["--profile", codeName, "cron", "runs", "--id", jobId, ...gwArgs]);
|
|
11506
|
-
const parsed = JSON.parse(stdout);
|
|
11507
|
-
runs = parsed.entries ?? [];
|
|
11508
|
-
} catch {
|
|
11509
|
-
continue;
|
|
11510
|
-
}
|
|
11511
|
-
const latestRun = runs.filter((r) => r.action === "finished").sort((a, b) => b.ts - a.ts)[0];
|
|
11512
|
-
if (latestRun) {
|
|
11513
|
-
const agentId = agentState.codeNameToAgentId.get(codeName);
|
|
11514
|
-
const summary = latestRun.summary ?? "";
|
|
11515
|
-
const isKeyError = summary.includes("Key limit exceeded") || summary.includes("key limit") || summary.includes("rate limit") || summary.includes("insufficient_quota") || summary.includes("billing") || summary.includes("402");
|
|
11516
|
-
if (agentId) {
|
|
11517
|
-
if (latestRun.status === "error" && isKeyError) {
|
|
11518
|
-
const errorMsg = summary.slice(0, 200);
|
|
11519
|
-
if (!apiKeyStatusCache.get(codeName)) {
|
|
11520
|
-
apiKeyStatusCache.set(codeName, true);
|
|
11521
|
-
api.post("/host/agent-api-key-status", { agent_id: agentId, status: "rate_limited", error: errorMsg }).catch(() => {
|
|
11522
|
-
});
|
|
11523
|
-
log(`API key error detected for '${codeName}': ${errorMsg}`);
|
|
11524
|
-
}
|
|
11525
|
-
} else if (latestRun.status === "ok" && apiKeyStatusCache.get(codeName)) {
|
|
11526
|
-
apiKeyStatusCache.delete(codeName);
|
|
11527
|
-
api.post("/host/agent-api-key-status", { agent_id: agentId, status: null, error: null }).catch(() => {
|
|
11528
|
-
});
|
|
11529
|
-
log(`API key status cleared for '${codeName}' \u2014 run succeeded`);
|
|
11530
|
-
}
|
|
11531
|
-
}
|
|
11532
|
-
}
|
|
11533
|
-
const completed = runs.filter((r) => r.action === "finished" && r.status === "ok" && r.summary).sort((a, b) => b.ts - a.ts);
|
|
11534
|
-
if (completed.length === 0) continue;
|
|
11535
|
-
const latest = completed[0];
|
|
11536
|
-
const lastSeen = lastCronRunTs.get(jobId) ?? 0;
|
|
11537
|
-
if (latest.ts <= lastSeen) continue;
|
|
11538
|
-
lastCronRunTs.set(jobId, latest.ts);
|
|
11539
|
-
const statusUpdate = { agent_code_name: codeName };
|
|
11540
|
-
if (STANDUP_TEMPLATES.has(templateId)) {
|
|
11541
|
-
const summary = latest.summary ?? "";
|
|
11542
|
-
statusUpdate.standup = parseStandupSummary(summary);
|
|
11543
|
-
}
|
|
11544
|
-
if (TASK_UPDATE_TEMPLATES.has(templateId)) {
|
|
11545
|
-
statusUpdate.current_tasks = latest.summary ?? "";
|
|
11546
|
-
}
|
|
11547
|
-
if (statusUpdate.standup || statusUpdate.current_tasks !== void 0) {
|
|
11548
|
-
try {
|
|
11549
|
-
await api.post("/host/agent-status", statusUpdate);
|
|
11550
|
-
log(`Updated ${templateId} for '${codeName}' from cron result`);
|
|
11551
|
-
} catch (err) {
|
|
11552
|
-
log(`Failed to update ${templateId} for '${codeName}': ${err.message}`);
|
|
11553
|
-
}
|
|
11554
|
-
}
|
|
11555
|
-
if (PLAN_TEMPLATES.has(templateId)) {
|
|
11556
|
-
const summary = latest.summary ?? "";
|
|
11557
|
-
const planItems = parsePlanItems(summary);
|
|
11558
|
-
if (planItems.length > 0) {
|
|
11559
|
-
try {
|
|
11560
|
-
const agentId = agentState.codeNameToAgentId.get(codeName);
|
|
11561
|
-
if (agentId) {
|
|
11562
|
-
await api.post("/host/kanban", {
|
|
11563
|
-
agent_id: agentId,
|
|
11564
|
-
add: planItems,
|
|
11565
|
-
archive_days: 7
|
|
11566
|
-
});
|
|
11567
|
-
log(`Added ${planItems.length} kanban items for '${codeName}' from morning-plan`);
|
|
11568
|
-
}
|
|
11569
|
-
} catch (err) {
|
|
11570
|
-
log(`Failed to update kanban for '${codeName}': ${err.message}`);
|
|
11571
|
-
}
|
|
11572
|
-
}
|
|
11573
|
-
}
|
|
11574
|
-
if (TASK_UPDATE_TEMPLATES.has(templateId) || KANBAN_WORK_TEMPLATES.has(templateId)) {
|
|
11575
|
-
const summary = latest.summary ?? "";
|
|
11576
|
-
const kanbanUpdates = parseKanbanUpdates(summary);
|
|
11577
|
-
if (kanbanUpdates.length > 0) {
|
|
11578
|
-
try {
|
|
11579
|
-
const agentId = agentState.codeNameToAgentId.get(codeName);
|
|
11580
|
-
if (agentId) {
|
|
11581
|
-
await api.post("/host/kanban", {
|
|
11582
|
-
agent_id: agentId,
|
|
11583
|
-
update: kanbanUpdates
|
|
11584
|
-
});
|
|
11585
|
-
log(`Updated ${kanbanUpdates.length} kanban items for '${codeName}'`);
|
|
11586
|
-
}
|
|
11587
|
-
} catch (err) {
|
|
11588
|
-
log(`Failed to update kanban for '${codeName}': ${err.message}`);
|
|
11589
|
-
}
|
|
11590
|
-
}
|
|
11591
|
-
}
|
|
11592
|
-
}
|
|
11593
|
-
}
|
|
11594
|
-
var LATE_THRESHOLD_MS = 5 * 60 * 1e3;
|
|
11595
|
-
async function monitorCronHealth(agentStates) {
|
|
11596
|
-
const alerts = [];
|
|
11597
|
-
const now = Date.now();
|
|
11598
|
-
for (const agent of agentStates) {
|
|
11599
|
-
if (!agent.gatewayRunning || !agent.gatewayPort) continue;
|
|
11600
|
-
const token = readGatewayToken(agent.codeName);
|
|
11601
|
-
const gwArgs = ["--url", `ws://127.0.0.1:${agent.gatewayPort}`, ...token ? ["--token", token] : []];
|
|
11602
|
-
let jobs = [];
|
|
11603
|
-
try {
|
|
11604
|
-
const cliBin = resolveAgentFramework(agent.codeName).cliBinary ?? "claude";
|
|
11605
|
-
const { stdout } = await execFilePromise(cliBin, ["--profile", agent.codeName, "cron", "list", "--json", ...gwArgs]);
|
|
11606
|
-
const parsed = JSON.parse(stdout);
|
|
11607
|
-
jobs = parsed.jobs ?? [];
|
|
11608
|
-
} catch {
|
|
11609
|
-
continue;
|
|
11610
|
-
}
|
|
11611
|
-
for (const job of jobs) {
|
|
11612
|
-
if (!job.enabled || !job.name.startsWith("aug:")) continue;
|
|
11613
|
-
const alertKey = `${agent.codeName}:${job.id}`;
|
|
11614
|
-
const displayInfo = taskDisplayInfo.get(`${agent.codeName}:${job.name}`);
|
|
11615
|
-
const taskName = displayInfo?.taskName ?? job.name;
|
|
11616
|
-
const schedule = displayInfo?.schedule ?? "";
|
|
11617
|
-
const agentDisplayName = displayInfo?.agentDisplayName ?? agent.codeName;
|
|
11618
|
-
if (job.state?.nextRunAtMs && job.state.nextRunAtMs + LATE_THRESHOLD_MS < now) {
|
|
11619
|
-
if (!alertedJobs.has(`late:${alertKey}`)) {
|
|
11620
|
-
const minsLate = Math.round((now - job.state.nextRunAtMs) / 6e4);
|
|
11621
|
-
alerts.push({
|
|
11622
|
-
type: "late_standup",
|
|
11623
|
-
agentCodeName: agent.codeName,
|
|
11624
|
-
agentDisplayName,
|
|
11625
|
-
jobName: job.name,
|
|
11626
|
-
taskName,
|
|
11627
|
-
schedule,
|
|
11628
|
-
jobId: job.id,
|
|
11629
|
-
detail: `Job is ${minsLate}m late (expected at ${new Date(job.state.nextRunAtMs).toISOString()})`
|
|
11630
|
-
});
|
|
11631
|
-
alertedJobs.add(`late:${alertKey}`);
|
|
11632
|
-
}
|
|
11633
|
-
} else {
|
|
11634
|
-
alertedJobs.delete(`late:${alertKey}`);
|
|
11635
|
-
}
|
|
11636
|
-
if (job.state?.lastRunStatus === "error" || job.state?.consecutiveErrors && job.state.consecutiveErrors > 0) {
|
|
11637
|
-
if (!alertedJobs.has(`fail:${alertKey}`)) {
|
|
11638
|
-
alerts.push({
|
|
11639
|
-
type: "cron_failure",
|
|
11640
|
-
agentCodeName: agent.codeName,
|
|
11641
|
-
agentDisplayName,
|
|
11642
|
-
jobName: job.name,
|
|
11643
|
-
taskName,
|
|
11644
|
-
schedule,
|
|
11645
|
-
jobId: job.id,
|
|
11646
|
-
detail: `Last run failed (${job.state.consecutiveErrors ?? 1} consecutive error(s))`
|
|
11647
|
-
});
|
|
11648
|
-
alertedJobs.add(`fail:${alertKey}`);
|
|
11649
|
-
}
|
|
11650
|
-
} else {
|
|
11651
|
-
alertedJobs.delete(`fail:${alertKey}`);
|
|
11652
|
-
}
|
|
11653
|
-
}
|
|
11654
|
-
}
|
|
11655
|
-
if (alerts.length === 0) return;
|
|
11656
|
-
for (const alert of alerts) {
|
|
11657
|
-
log(`ALERT [${alert.type}] ${alert.agentCodeName}/${alert.jobName}: ${alert.detail}`);
|
|
11658
|
-
}
|
|
11659
|
-
if (getAlertSlackWebhook()) {
|
|
11660
|
-
await sendSlackAlert(alerts);
|
|
11661
|
-
}
|
|
11662
|
-
try {
|
|
11663
|
-
await api.post("/host/cron-alerts", { alerts });
|
|
11664
|
-
} catch {
|
|
11665
|
-
}
|
|
11666
|
-
}
|
|
11667
|
-
async function sendSlackAlert(alerts) {
|
|
11668
|
-
const blocks = alerts.map((a) => {
|
|
11669
|
-
const emoji = a.type === "late_standup" ? ":warning:" : ":x:";
|
|
11670
|
-
const label = a.type === "late_standup" ? "Late" : "Failed";
|
|
11671
|
-
const scheduleInfo = a.schedule ? ` (${a.schedule})` : "";
|
|
11672
|
-
return `${emoji} *${label}* \u2014 *${a.agentDisplayName}* / ${a.taskName}${scheduleInfo}
|
|
11673
|
-
${a.detail}`;
|
|
11674
|
-
});
|
|
11675
|
-
await sendSlackWebhookMessage(`:rotating_light: *Cron Health Alert*
|
|
11676
|
-
|
|
11677
|
-
${blocks.join("\n\n")}`);
|
|
11678
|
-
}
|
|
11679
10625
|
var spawnedPairIds = /* @__PURE__ */ new Set();
|
|
11680
10626
|
async function processClaudePairSessions(agents) {
|
|
11681
10627
|
if (agents.length === 0 && spawnedPairIds.size === 0) return;
|
|
@@ -11692,7 +10638,7 @@ async function processClaudePairSessions(agents) {
|
|
|
11692
10638
|
killPairSession,
|
|
11693
10639
|
pairTmuxSession,
|
|
11694
10640
|
finalizeClaudePairOnboarding
|
|
11695
|
-
} = await import("../claude-pair-runtime-
|
|
10641
|
+
} = await import("../claude-pair-runtime-37H4BVQC.js");
|
|
11696
10642
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
11697
10643
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
11698
10644
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -11874,7 +10820,6 @@ function generateArtifacts(agent, refreshData, adapter) {
|
|
|
11874
10820
|
toolsContent,
|
|
11875
10821
|
resolvedChannels: effectiveChannels,
|
|
11876
10822
|
deploymentTarget: "local_docker",
|
|
11877
|
-
gatewayPort: 9e3,
|
|
11878
10823
|
team: refreshData.team ?? void 0,
|
|
11879
10824
|
activeTasks: activeTasksFromRefresh,
|
|
11880
10825
|
// ENG-5009: org name for the identity-preamble. Only present when
|
|
@@ -12071,41 +11016,6 @@ async function cleanupAgentFiles(codeName, agentDir) {
|
|
|
12071
11016
|
log(`Failed to deregister '${codeName}': ${err.message}`);
|
|
12072
11017
|
}
|
|
12073
11018
|
}
|
|
12074
|
-
function startGatewayPool() {
|
|
12075
|
-
if (gatewayPool) return;
|
|
12076
|
-
gatewayPool = new GatewayClientPool();
|
|
12077
|
-
gatewayPool.on("connected", (codeName) => {
|
|
12078
|
-
log(`Gateway WebSocket connected for '${codeName}'`);
|
|
12079
|
-
});
|
|
12080
|
-
gatewayPool.on("disconnected", (codeName) => {
|
|
12081
|
-
log(`Gateway WebSocket disconnected for '${codeName}'`);
|
|
12082
|
-
});
|
|
12083
|
-
gatewayPool.on("error", (err, codeName) => {
|
|
12084
|
-
log(`Gateway WebSocket error for '${codeName}': ${err.message}`);
|
|
12085
|
-
});
|
|
12086
|
-
gatewayPool.on("event", (evt) => {
|
|
12087
|
-
send({ type: "gateway-event", event: evt.event, payload: evt.payload, agentCodeName: evt.agentCodeName });
|
|
12088
|
-
getHostId().then((hostId) => {
|
|
12089
|
-
if (!hostId) return;
|
|
12090
|
-
api.post("/host/events", {
|
|
12091
|
-
host_id: hostId,
|
|
12092
|
-
agent_code_name: evt.agentCodeName,
|
|
12093
|
-
event_type: evt.event,
|
|
12094
|
-
payload: evt.payload,
|
|
12095
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
12096
|
-
}).catch((err) => {
|
|
12097
|
-
log(`Failed to forward gateway event: ${err.message}`);
|
|
12098
|
-
});
|
|
12099
|
-
}).catch(() => {
|
|
12100
|
-
});
|
|
12101
|
-
});
|
|
12102
|
-
}
|
|
12103
|
-
function stopGatewayPool() {
|
|
12104
|
-
if (gatewayPool) {
|
|
12105
|
-
gatewayPool.disconnectAll();
|
|
12106
|
-
gatewayPool = null;
|
|
12107
|
-
}
|
|
12108
|
-
}
|
|
12109
11019
|
var caffeinateProc = null;
|
|
12110
11020
|
async function startCaffeinate() {
|
|
12111
11021
|
if (process.platform !== "darwin") return;
|
|
@@ -12180,8 +11090,7 @@ function startPolling() {
|
|
|
12180
11090
|
hostFlagStore().init();
|
|
12181
11091
|
log(`Starting poll loop (interval=${config.intervalMs}ms, configDir=${config.configDir})`);
|
|
12182
11092
|
void killAllAgtTmuxSessions().catch(() => {
|
|
12183
|
-
}).then(() =>
|
|
12184
|
-
startGatewayPool();
|
|
11093
|
+
}).then(() => {
|
|
12185
11094
|
return pollCycle();
|
|
12186
11095
|
}).then(() => {
|
|
12187
11096
|
void driveArtifactStreaming();
|
|
@@ -12284,7 +11193,6 @@ async function stopPolling(opts = {}) {
|
|
|
12284
11193
|
const subsysStartedAt = Date.now();
|
|
12285
11194
|
stopCaffeinate();
|
|
12286
11195
|
stopRealtimeChat();
|
|
12287
|
-
stopGatewayPool();
|
|
12288
11196
|
log(formatDrainShutdownLine({ step: "stop-subsystems", elapsedMs: Date.now() - subsysStartedAt }));
|
|
12289
11197
|
for (const codeName of [...scheduledRunsByCode.keys()]) {
|
|
12290
11198
|
closeScheduledRunsForCode(codeName, "cancelled", "manager shutdown");
|
|
@@ -12293,8 +11201,6 @@ async function stopPolling(opts = {}) {
|
|
|
12293
11201
|
await killAllAgtTmuxSessions();
|
|
12294
11202
|
log("Stopping persistent sessions...");
|
|
12295
11203
|
await stopAllSessionsAndWait(log, { timeoutMs: 4e3 });
|
|
12296
|
-
log("Stopping gateway processes...");
|
|
12297
|
-
await stopAllGateways();
|
|
12298
11204
|
clearTimeout(shutdownTimer);
|
|
12299
11205
|
}
|
|
12300
11206
|
function startManager(opts) {
|