@integrity-labs/agt-cli 0.19.13 → 0.19.14
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 +3 -3
- package/dist/{chunk-QFWR2NV5.js → chunk-HA4IUBVC.js} +101 -7
- package/dist/chunk-HA4IUBVC.js.map +1 -0
- package/dist/{chunk-SUUTWC6M.js → chunk-KLNFWXOI.js} +45 -5
- package/dist/chunk-KLNFWXOI.js.map +1 -0
- package/dist/{claude-pair-runtime-SJDLJNYF.js → claude-pair-runtime-VXN4NVGR.js} +2 -2
- package/dist/lib/manager-worker.js +95 -11
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-XBRQN7XE.js → persistent-session-CFDGW7QE.js} +2 -2
- package/mcp/index.js +1 -1
- package/mcp/slack-channel.js +105 -1
- package/package.json +1 -1
- package/dist/chunk-QFWR2NV5.js.map +0 -1
- package/dist/chunk-SUUTWC6M.js.map +0 -1
- /package/dist/{claude-pair-runtime-SJDLJNYF.js.map → claude-pair-runtime-VXN4NVGR.js.map} +0 -0
- /package/dist/{persistent-session-XBRQN7XE.js.map → persistent-session-CFDGW7QE.js.map} +0 -0
|
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
|
|
|
100
100
|
return { ok: true };
|
|
101
101
|
} catch {
|
|
102
102
|
}
|
|
103
|
-
const { resolveClaudeBinary } = await import("./persistent-session-
|
|
103
|
+
const { resolveClaudeBinary } = await import("./persistent-session-CFDGW7QE.js");
|
|
104
104
|
const claudeBin = resolveClaudeBinary();
|
|
105
105
|
try {
|
|
106
106
|
await execFileAsync("tmux", [
|
|
@@ -357,4 +357,4 @@ export {
|
|
|
357
357
|
startClaudePair,
|
|
358
358
|
submitClaudePairCode
|
|
359
359
|
};
|
|
360
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
360
|
+
//# sourceMappingURL=claude-pair-runtime-VXN4NVGR.js.map
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveChannels,
|
|
23
23
|
resolveDmTarget,
|
|
24
24
|
wrapScheduledTaskPrompt
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-KLNFWXOI.js";
|
|
26
26
|
import {
|
|
27
27
|
findTaskByTemplate,
|
|
28
28
|
getProjectDir,
|
|
@@ -41,13 +41,14 @@ import {
|
|
|
41
41
|
isStaleForToday,
|
|
42
42
|
peekCurrentSession,
|
|
43
43
|
prepareForRespawn,
|
|
44
|
+
reapOrphanChannelMcps,
|
|
44
45
|
resetRestartCount,
|
|
45
46
|
resolveClaudeBinary,
|
|
46
47
|
sanitizeMcpJson,
|
|
47
48
|
startPersistentSession,
|
|
48
49
|
stopAllSessionsAndWait,
|
|
49
50
|
stopPersistentSession
|
|
50
|
-
} from "../chunk-
|
|
51
|
+
} from "../chunk-HA4IUBVC.js";
|
|
51
52
|
|
|
52
53
|
// src/lib/manager-worker.ts
|
|
53
54
|
import { createHash } from "crypto";
|
|
@@ -58,6 +59,34 @@ import { join as join4, dirname } from "path";
|
|
|
58
59
|
import { homedir as homedir3 } from "os";
|
|
59
60
|
import { fileURLToPath } from "url";
|
|
60
61
|
|
|
62
|
+
// src/lib/channel-restart-decision.ts
|
|
63
|
+
function launchableChannelIds(channelConfigs) {
|
|
64
|
+
if (!channelConfigs) return /* @__PURE__ */ new Set();
|
|
65
|
+
const result = /* @__PURE__ */ new Set();
|
|
66
|
+
for (const [channelId, entry] of Object.entries(channelConfigs)) {
|
|
67
|
+
if (!entry) continue;
|
|
68
|
+
if (entry.config == null) continue;
|
|
69
|
+
if (entry.status !== "active" && entry.status !== "pending") continue;
|
|
70
|
+
result.add(channelId);
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
function decideChannelRestart(input) {
|
|
75
|
+
const { previousChannelIds, currentChannelIds, sessionMode, framework, sessionHealthy } = input;
|
|
76
|
+
if (previousChannelIds === void 0) {
|
|
77
|
+
return { restart: false, added: [], removed: [] };
|
|
78
|
+
}
|
|
79
|
+
const added = [...currentChannelIds].filter((c) => !previousChannelIds.has(c));
|
|
80
|
+
const removed = [...previousChannelIds].filter((c) => !currentChannelIds.has(c));
|
|
81
|
+
if (added.length === 0 && removed.length === 0) {
|
|
82
|
+
return { restart: false, added, removed };
|
|
83
|
+
}
|
|
84
|
+
if (sessionMode !== "persistent") return { restart: false, added, removed };
|
|
85
|
+
if (framework !== "claude-code") return { restart: false, added, removed };
|
|
86
|
+
if (!sessionHealthy) return { restart: false, added, removed };
|
|
87
|
+
return { restart: true, added, removed };
|
|
88
|
+
}
|
|
89
|
+
|
|
61
90
|
// src/lib/integration-context-render.ts
|
|
62
91
|
var PLUGIN_CONTEXT_PLACEHOLDER_RE = /\{\{\s*context\.([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
63
92
|
var TEAM_OVERRIDES_HEADER = "## Team Overrides\n\n> **The following overrides anything you've read above.** If any rule here conflicts with earlier instructions in this skill, follow what is written here. These are user-supplied directives that take precedence over the plugin's default guidance.\n";
|
|
@@ -1554,6 +1583,28 @@ var KNOWN_SAFE_TAIL_SIGNATURES = /* @__PURE__ */ new Set(["session_id_in_use"]);
|
|
|
1554
1583
|
var knownVersions = /* @__PURE__ */ new Map();
|
|
1555
1584
|
var knownStatuses = /* @__PURE__ */ new Map();
|
|
1556
1585
|
var knownChannels = /* @__PURE__ */ new Map();
|
|
1586
|
+
var pendingSessionRestarts = /* @__PURE__ */ new Map();
|
|
1587
|
+
function scheduleSessionRestart(codeName, delayMs, reason) {
|
|
1588
|
+
const existing = pendingSessionRestarts.get(codeName);
|
|
1589
|
+
if (existing) {
|
|
1590
|
+
clearTimeout(existing);
|
|
1591
|
+
log(`[hot-reload] Coalesced restart for '${codeName}': replacing pending timer with ${reason}`);
|
|
1592
|
+
}
|
|
1593
|
+
const timer = setTimeout(() => {
|
|
1594
|
+
pendingSessionRestarts.delete(codeName);
|
|
1595
|
+
stopPersistentSession(codeName, log);
|
|
1596
|
+
log(`[hot-reload] Session stopped for '${codeName}' \u2014 will respawn with ${reason}`);
|
|
1597
|
+
}, delayMs);
|
|
1598
|
+
timer.unref?.();
|
|
1599
|
+
pendingSessionRestarts.set(codeName, timer);
|
|
1600
|
+
}
|
|
1601
|
+
function cancelPendingSessionRestart(codeName) {
|
|
1602
|
+
const existing = pendingSessionRestarts.get(codeName);
|
|
1603
|
+
if (!existing) return;
|
|
1604
|
+
clearTimeout(existing);
|
|
1605
|
+
pendingSessionRestarts.delete(codeName);
|
|
1606
|
+
log(`[hot-reload] Cancelled pending restart timer for '${codeName}' (another teardown path is handling it)`);
|
|
1607
|
+
}
|
|
1557
1608
|
var writtenHashes = /* @__PURE__ */ new Map();
|
|
1558
1609
|
var knownSecretsHashes = /* @__PURE__ */ new Map();
|
|
1559
1610
|
var knownChannelConfigHashes = /* @__PURE__ */ new Map();
|
|
@@ -1630,7 +1681,7 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
1630
1681
|
var cachedFrameworkVersion = null;
|
|
1631
1682
|
var lastVersionCheckAt = 0;
|
|
1632
1683
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
1633
|
-
var agtCliVersion = true ? "0.19.
|
|
1684
|
+
var agtCliVersion = true ? "0.19.14" : "dev";
|
|
1634
1685
|
function resolveBrewPath(execFileSync2) {
|
|
1635
1686
|
try {
|
|
1636
1687
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -2473,6 +2524,7 @@ async function pollCycle() {
|
|
|
2473
2524
|
log,
|
|
2474
2525
|
resolveFramework: (codeName) => agentFrameworkCache.get(codeName) ?? null,
|
|
2475
2526
|
stopSession: (codeName) => {
|
|
2527
|
+
cancelPendingSessionRestart(codeName);
|
|
2476
2528
|
stopPersistentSession(codeName, log);
|
|
2477
2529
|
persistentSessionAgents.delete(codeName);
|
|
2478
2530
|
claudeAuthTupleBySession.delete(codeName);
|
|
@@ -2533,7 +2585,7 @@ async function pollCycle() {
|
|
|
2533
2585
|
}
|
|
2534
2586
|
try {
|
|
2535
2587
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
2536
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
2588
|
+
const { collectDiagnostics } = await import("../persistent-session-CFDGW7QE.js");
|
|
2537
2589
|
const diagCodeNames = [...persistentSessionAgents];
|
|
2538
2590
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
2539
2591
|
let tailscaleHostname;
|
|
@@ -2633,6 +2685,7 @@ async function pollCycle() {
|
|
|
2633
2685
|
log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
|
|
2634
2686
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
2635
2687
|
await stopGatewayIfRunning(prev.codeName, adapter);
|
|
2688
|
+
cancelPendingSessionRestart(prev.codeName);
|
|
2636
2689
|
stopPersistentSession(prev.codeName, log);
|
|
2637
2690
|
try {
|
|
2638
2691
|
const { execSync: es } = await import("child_process");
|
|
@@ -2770,6 +2823,7 @@ async function processAgent(agent, agentStates) {
|
|
|
2770
2823
|
if (agent.status === "draft" || agent.status === "paused") {
|
|
2771
2824
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
2772
2825
|
await stopGatewayIfRunning(agent.code_name, adapter);
|
|
2826
|
+
cancelPendingSessionRestart(agent.code_name);
|
|
2773
2827
|
stopPersistentSession(agent.code_name, log);
|
|
2774
2828
|
try {
|
|
2775
2829
|
const { execSync: es } = await import("child_process");
|
|
@@ -2798,6 +2852,7 @@ async function processAgent(agent, agentStates) {
|
|
|
2798
2852
|
if (agent.status === "revoked") {
|
|
2799
2853
|
log(`Agent '${agent.code_name}' is revoked, cleaning up`);
|
|
2800
2854
|
await stopGatewayIfRunning(agent.code_name, adapter);
|
|
2855
|
+
cancelPendingSessionRestart(agent.code_name);
|
|
2801
2856
|
stopPersistentSession(agent.code_name, log);
|
|
2802
2857
|
try {
|
|
2803
2858
|
const { execSync: es } = await import("child_process");
|
|
@@ -2905,9 +2960,10 @@ async function processAgent(agent, agentStates) {
|
|
|
2905
2960
|
const toolsVersion = refreshData.tools.version;
|
|
2906
2961
|
const known = knownVersions.get(agent.agent_id);
|
|
2907
2962
|
let lastProvisionAt = state.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
|
|
2908
|
-
const currentChannelIds =
|
|
2963
|
+
const currentChannelIds = launchableChannelIds(refreshData.channel_configs);
|
|
2909
2964
|
const previousChannelIds = knownChannels.get(agent.agent_id);
|
|
2910
2965
|
const channelsChanged = !previousChannelIds || currentChannelIds.size !== previousChannelIds.size || [...currentChannelIds].some((ch) => !previousChannelIds.has(ch)) || [...previousChannelIds].some((ch) => !currentChannelIds.has(ch));
|
|
2966
|
+
let channelConfigConverged = true;
|
|
2911
2967
|
if (previousChannelIds && channelsChanged && frameworkAdapter.removeChannelCredentials) {
|
|
2912
2968
|
for (const ch of previousChannelIds) {
|
|
2913
2969
|
if (!currentChannelIds.has(ch)) {
|
|
@@ -2915,12 +2971,12 @@ async function processAgent(agent, agentStates) {
|
|
|
2915
2971
|
frameworkAdapter.removeChannelCredentials(agent.code_name, ch);
|
|
2916
2972
|
log(`Removed ${ch} credentials for '${agent.code_name}'`);
|
|
2917
2973
|
} catch (err) {
|
|
2974
|
+
channelConfigConverged = false;
|
|
2918
2975
|
log(`Failed to remove ${ch} credentials for '${agent.code_name}': ${err.message}`);
|
|
2919
2976
|
}
|
|
2920
2977
|
}
|
|
2921
2978
|
}
|
|
2922
2979
|
}
|
|
2923
|
-
knownChannels.set(agent.agent_id, currentChannelIds);
|
|
2924
2980
|
try {
|
|
2925
2981
|
const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter);
|
|
2926
2982
|
const changedFiles = [];
|
|
@@ -3133,6 +3189,7 @@ async function processAgent(agent, agentStates) {
|
|
|
3133
3189
|
saveChannelHashCache2();
|
|
3134
3190
|
log(`Channel credentials written for '${agent.code_name}/${channelId}' (reason=${reason}, hash=${configHash.slice(0, 8)}${prevHash ? `, prev=${prevHash.slice(0, 8)}` : ""})`);
|
|
3135
3191
|
} catch (err) {
|
|
3192
|
+
channelConfigConverged = false;
|
|
3136
3193
|
log(`Failed to write channel credentials for '${agent.code_name}/${channelId}': ${err.message}`);
|
|
3137
3194
|
}
|
|
3138
3195
|
}
|
|
@@ -3145,6 +3202,32 @@ async function processAgent(agent, agentStates) {
|
|
|
3145
3202
|
}
|
|
3146
3203
|
}
|
|
3147
3204
|
}
|
|
3205
|
+
if (channelConfigConverged) {
|
|
3206
|
+
knownChannels.set(agent.agent_id, currentChannelIds);
|
|
3207
|
+
} else {
|
|
3208
|
+
log(`[channels] Credential sync did not converge for '${agent.code_name}' \u2014 leaving diff live for next tick retry`);
|
|
3209
|
+
}
|
|
3210
|
+
const restartDecision = channelConfigConverged ? decideChannelRestart({
|
|
3211
|
+
previousChannelIds,
|
|
3212
|
+
currentChannelIds,
|
|
3213
|
+
sessionMode: refreshData.agent.session_mode,
|
|
3214
|
+
framework: agentFrameworkCache.get(agent.code_name) ?? "openclaw",
|
|
3215
|
+
sessionHealthy: isSessionHealthy(agent.code_name)
|
|
3216
|
+
}) : { restart: false, added: [], removed: [] };
|
|
3217
|
+
if (restartDecision.restart) {
|
|
3218
|
+
const reasonParts = [];
|
|
3219
|
+
if (restartDecision.added.length > 0) reasonParts.push(`added=${restartDecision.added.join(",")}`);
|
|
3220
|
+
if (restartDecision.removed.length > 0) reasonParts.push(`removed=${restartDecision.removed.join(",")}`);
|
|
3221
|
+
const reason = reasonParts.join(" ");
|
|
3222
|
+
log(`[hot-reload] Channel set changed for '${agent.code_name}' (${reason}) \u2014 restarting session`);
|
|
3223
|
+
const restartNotice = restartDecision.added.length > 0 ? `New channels have been wired up (${restartDecision.added.join(", ")}). Note: channels require a session restart to attach their MCP servers as channel listeners. Your manager will restart your session shortly.` : `Channels were removed (${restartDecision.removed.join(", ")}). Your manager will restart your session shortly so the launch flags drop those channels.`;
|
|
3224
|
+
const delivered = await injectMessage(agent.code_name, "system", restartNotice, { task_name: "channel-update" }, log).catch(() => false);
|
|
3225
|
+
const delay = delivered ? 8e3 : 3e3;
|
|
3226
|
+
if (!delivered) {
|
|
3227
|
+
log(`[hot-reload] Inject notification unconfirmed for '${agent.code_name}' \u2014 proceeding with shorter delay`);
|
|
3228
|
+
}
|
|
3229
|
+
scheduleSessionRestart(agent.code_name, delay, "new channel set");
|
|
3230
|
+
}
|
|
3148
3231
|
const agentSessionMode = refreshData.agent.session_mode;
|
|
3149
3232
|
if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? "openclaw") === "claude-code") {
|
|
3150
3233
|
try {
|
|
@@ -3334,10 +3417,7 @@ async function processAgent(agent, agentStates) {
|
|
|
3334
3417
|
if (!delivered) {
|
|
3335
3418
|
log(`[hot-reload] Inject notification unconfirmed for '${agent.code_name}' \u2014 proceeding with shorter delay`);
|
|
3336
3419
|
}
|
|
3337
|
-
|
|
3338
|
-
stopPersistentSession(agent.code_name, log);
|
|
3339
|
-
log(`[hot-reload] Session stopped for '${agent.code_name}' \u2014 will respawn with new MCP servers`);
|
|
3340
|
-
}, delay);
|
|
3420
|
+
scheduleSessionRestart(agent.code_name, delay, "new MCP servers");
|
|
3341
3421
|
}
|
|
3342
3422
|
}
|
|
3343
3423
|
} catch (err) {
|
|
@@ -4327,6 +4407,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
4327
4407
|
const msg = err.message;
|
|
4328
4408
|
log(`[persistent-session] Failed to resolve auth for '${codeName}': ${msg} \u2014 refusing to spawn`);
|
|
4329
4409
|
if (isSessionHealthy(codeName)) {
|
|
4410
|
+
cancelPendingSessionRestart(codeName);
|
|
4330
4411
|
stopPersistentSession(codeName, log);
|
|
4331
4412
|
persistentSessionAgents.delete(codeName);
|
|
4332
4413
|
claudeAuthTupleBySession.delete(codeName);
|
|
@@ -4349,6 +4430,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
4349
4430
|
const recordedAuthTuple = claudeAuthTupleBySession.get(codeName);
|
|
4350
4431
|
if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && isSessionHealthy(codeName)) {
|
|
4351
4432
|
log(`[persistent-session] Auth config changed for '${codeName}' (${recordedAuthTuple} \u2192 ${currentAuthTuple}) \u2014 restarting session`);
|
|
4433
|
+
cancelPendingSessionRestart(codeName);
|
|
4352
4434
|
stopPersistentSession(codeName, log);
|
|
4353
4435
|
persistentSessionAgents.delete(codeName);
|
|
4354
4436
|
}
|
|
@@ -4360,6 +4442,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
|
|
|
4360
4442
|
log(
|
|
4361
4443
|
`[persistent-session] Day rollover for '${codeName}' (yesterday=${current.date}) \u2014 agent idle, restarting to mint fresh session`
|
|
4362
4444
|
);
|
|
4445
|
+
cancelPendingSessionRestart(codeName);
|
|
4363
4446
|
stopPersistentSession(codeName, log);
|
|
4364
4447
|
persistentSessionAgents.delete(codeName);
|
|
4365
4448
|
} else {
|
|
@@ -5739,7 +5822,7 @@ async function processClaudePairSessions(agents) {
|
|
|
5739
5822
|
killPairSession,
|
|
5740
5823
|
pairTmuxSession,
|
|
5741
5824
|
finalizeClaudePairOnboarding
|
|
5742
|
-
} = await import("../claude-pair-runtime-
|
|
5825
|
+
} = await import("../claude-pair-runtime-VXN4NVGR.js");
|
|
5743
5826
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
5744
5827
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
5745
5828
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -6301,6 +6384,7 @@ function startManager(opts) {
|
|
|
6301
6384
|
`[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join4(homedir3(), ".augmented", "manager.log")}`
|
|
6302
6385
|
);
|
|
6303
6386
|
deployMcpAssets();
|
|
6387
|
+
reapOrphanChannelMcps({ log });
|
|
6304
6388
|
void ensureHostFrameworkBinaries();
|
|
6305
6389
|
startPolling();
|
|
6306
6390
|
}
|