@integrity-labs/agt-cli 0.28.352 → 0.28.354
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +4 -4
- package/dist/{chunk-BERN3B42.js → chunk-4ITNBU3K.js} +41 -5
- package/dist/{chunk-BERN3B42.js.map → chunk-4ITNBU3K.js.map} +1 -1
- package/dist/{chunk-ZALWFOHO.js → chunk-LDIKBFDR.js} +10 -1
- package/dist/{chunk-ZALWFOHO.js.map → chunk-LDIKBFDR.js.map} +1 -1
- package/dist/{claude-pair-runtime-KO2HWC7E.js → claude-pair-runtime-LLUV4KX6.js} +2 -2
- package/dist/lib/manager-worker.js +182 -53
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +9 -0
- package/dist/mcp/origami.js +9 -0
- package/dist/mcp/slack-channel.js +9 -0
- package/dist/mcp/telegram-channel.js +9 -0
- package/dist/{persistent-session-WMQO3QKU.js → persistent-session-SZ5VHS4C.js} +2 -2
- package/dist/{responsiveness-probe-TCTSHDH3.js → responsiveness-probe-2D64EQAU.js} +2 -2
- package/package.json +1 -1
- /package/dist/{claude-pair-runtime-KO2HWC7E.js.map → claude-pair-runtime-LLUV4KX6.js.map} +0 -0
- /package/dist/{persistent-session-WMQO3QKU.js.map → persistent-session-SZ5VHS4C.js.map} +0 -0
- /package/dist/{responsiveness-probe-TCTSHDH3.js.map → responsiveness-probe-2D64EQAU.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-SZ5VHS4C.js");
|
|
104
104
|
const claudeBin = resolveClaudeBinary();
|
|
105
105
|
const pairEnv = {
|
|
106
106
|
...process.env,
|
|
@@ -373,4 +373,4 @@ export {
|
|
|
373
373
|
startClaudePair,
|
|
374
374
|
submitClaudePairCode
|
|
375
375
|
};
|
|
376
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
376
|
+
//# sourceMappingURL=claude-pair-runtime-LLUV4KX6.js.map
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
getHostId,
|
|
31
31
|
givenUpMcpServerKeys,
|
|
32
32
|
liveProxyExtraHeaderVars,
|
|
33
|
+
parseOpencodeModelRef,
|
|
33
34
|
pinAllowsUrgent,
|
|
34
35
|
provision,
|
|
35
36
|
provisionAutoKanbanProgressHook,
|
|
@@ -47,7 +48,7 @@ import {
|
|
|
47
48
|
safeWriteJsonAtomic,
|
|
48
49
|
setConfigHash,
|
|
49
50
|
toOpencodeModel
|
|
50
|
-
} from "../chunk-
|
|
51
|
+
} from "../chunk-4ITNBU3K.js";
|
|
51
52
|
import {
|
|
52
53
|
getProjectDir as getProjectDir2,
|
|
53
54
|
getReadyTasks,
|
|
@@ -138,16 +139,16 @@ import {
|
|
|
138
139
|
takeZombieDetection,
|
|
139
140
|
transcriptActivityAgeSeconds,
|
|
140
141
|
writeEgressAllowlist
|
|
141
|
-
} from "../chunk-
|
|
142
|
+
} from "../chunk-LDIKBFDR.js";
|
|
142
143
|
import {
|
|
143
144
|
reapOrphanChannelMcps
|
|
144
145
|
} from "../chunk-XWVM4KPK.js";
|
|
145
146
|
|
|
146
147
|
// src/lib/manager-worker.ts
|
|
147
148
|
import { createHash as createHash14 } from "crypto";
|
|
148
|
-
import { readFileSync as readFileSync19, writeFileSync as
|
|
149
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync12, mkdirSync as mkdirSync10, existsSync as existsSync13, rmSync as rmSync5, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
|
|
149
150
|
import { execFileSync as syncExecFile } from "child_process";
|
|
150
|
-
import { join as join23, dirname as
|
|
151
|
+
import { join as join23, dirname as dirname7, delimiter as pathDelimiter } from "path";
|
|
151
152
|
import { homedir as homedir12 } from "os";
|
|
152
153
|
import { fileURLToPath } from "url";
|
|
153
154
|
|
|
@@ -807,6 +808,19 @@ function countByClass(events) {
|
|
|
807
808
|
}
|
|
808
809
|
return { crash, provisioning, "credential-rotation": credentialRotation };
|
|
809
810
|
}
|
|
811
|
+
function maxProvisioningBucket(events) {
|
|
812
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
813
|
+
for (const e of events) {
|
|
814
|
+
if (!isProvisioningReloadReason(e.reason)) continue;
|
|
815
|
+
const key = e.integrationKey ?? "";
|
|
816
|
+
buckets.set(key, (buckets.get(key) ?? 0) + 1);
|
|
817
|
+
}
|
|
818
|
+
let best = { count: 0, key: "" };
|
|
819
|
+
for (const [key, count] of buckets) {
|
|
820
|
+
if (count > best.count) best = { count, key };
|
|
821
|
+
}
|
|
822
|
+
return best;
|
|
823
|
+
}
|
|
810
824
|
var DEFAULT_MAX = 2;
|
|
811
825
|
var DEFAULT_WINDOW_MS = 6e5;
|
|
812
826
|
var DEFAULT_PROVISIONING_MAX = 5;
|
|
@@ -863,20 +877,25 @@ var RestartBreaker = class {
|
|
|
863
877
|
* without double-counting events. Callers may still record the reason
|
|
864
878
|
* via the decision-log for forensics.
|
|
865
879
|
*/
|
|
866
|
-
record(codeName, reason) {
|
|
880
|
+
record(codeName, reason, integrationKey) {
|
|
867
881
|
const existing = this.trips.get(codeName);
|
|
868
882
|
if (existing) {
|
|
883
|
+
const bucket = maxProvisioningBucket(existing.eventsAtTrip);
|
|
869
884
|
return {
|
|
870
885
|
tripped: false,
|
|
871
886
|
trip: existing,
|
|
872
887
|
windowCount: existing.eventsAtTrip.length,
|
|
873
|
-
classCounts: countByClass(existing.eventsAtTrip)
|
|
888
|
+
classCounts: countByClass(existing.eventsAtTrip),
|
|
889
|
+
maxProvisioningBucket: bucket.count,
|
|
890
|
+
maxProvisioningBucketKey: bucket.key
|
|
874
891
|
};
|
|
875
892
|
}
|
|
876
893
|
const at = this.now();
|
|
877
894
|
const retentionCutoff = at - this.retentionMs;
|
|
878
895
|
const prior = (this.events.get(codeName) ?? []).filter((e) => e.at >= retentionCutoff);
|
|
879
|
-
prior.push(
|
|
896
|
+
prior.push(
|
|
897
|
+
isProvisioningReloadReason(reason) && integrationKey ? { reason, at, integrationKey } : { reason, at }
|
|
898
|
+
);
|
|
880
899
|
this.events.set(codeName, prior);
|
|
881
900
|
const crashCount = prior.filter(
|
|
882
901
|
(e) => e.at >= at - this.windowMs && restartReasonClass(e.reason) === "crash"
|
|
@@ -893,6 +912,7 @@ var RestartBreaker = class {
|
|
|
893
912
|
provisioning: provEvents.length,
|
|
894
913
|
"credential-rotation": credRotCount
|
|
895
914
|
};
|
|
915
|
+
const provBucket = maxProvisioningBucket(provEvents);
|
|
896
916
|
let trippedClass;
|
|
897
917
|
let tripEvents;
|
|
898
918
|
let tripWindowMs = this.windowMs;
|
|
@@ -902,22 +922,36 @@ var RestartBreaker = class {
|
|
|
902
922
|
(e) => e.at >= at - this.windowMs && restartReasonClass(e.reason) === "crash"
|
|
903
923
|
);
|
|
904
924
|
tripWindowMs = this.windowMs;
|
|
905
|
-
} else if (
|
|
925
|
+
} else if (provBucket.count > this.provisioningMax) {
|
|
906
926
|
trippedClass = "provisioning";
|
|
907
|
-
tripEvents = provEvents;
|
|
927
|
+
tripEvents = provEvents.filter((e) => (e.integrationKey ?? "") === provBucket.key);
|
|
908
928
|
tripWindowMs = this.provisioningWindowMs;
|
|
909
929
|
}
|
|
910
930
|
if (trippedClass && tripEvents) {
|
|
911
931
|
const trip = {
|
|
912
932
|
trippedAt: at,
|
|
913
933
|
eventsAtTrip: [...tripEvents],
|
|
914
|
-
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass)
|
|
934
|
+
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key)
|
|
915
935
|
};
|
|
916
936
|
this.trips.set(codeName, trip);
|
|
917
937
|
this.events.delete(codeName);
|
|
918
|
-
return {
|
|
938
|
+
return {
|
|
939
|
+
tripped: true,
|
|
940
|
+
trip,
|
|
941
|
+
windowCount,
|
|
942
|
+
classCounts,
|
|
943
|
+
trippedClass,
|
|
944
|
+
maxProvisioningBucket: provBucket.count,
|
|
945
|
+
maxProvisioningBucketKey: provBucket.key
|
|
946
|
+
};
|
|
919
947
|
}
|
|
920
|
-
return {
|
|
948
|
+
return {
|
|
949
|
+
tripped: false,
|
|
950
|
+
windowCount,
|
|
951
|
+
classCounts,
|
|
952
|
+
maxProvisioningBucket: provBucket.count,
|
|
953
|
+
maxProvisioningBucketKey: provBucket.key
|
|
954
|
+
};
|
|
921
955
|
}
|
|
922
956
|
/** Operator-initiated reset: drops the trip + the events log for this agent. */
|
|
923
957
|
clear(codeName) {
|
|
@@ -948,14 +982,15 @@ var RestartBreaker = class {
|
|
|
948
982
|
return (this.events.get(codeName) ?? []).filter((e) => e.at >= cutoff).length;
|
|
949
983
|
}
|
|
950
984
|
};
|
|
951
|
-
function formatStatusMessage(events, windowMs, klass = "crash") {
|
|
985
|
+
function formatStatusMessage(events, windowMs, klass = "crash", integrationKey = "") {
|
|
952
986
|
const last = events[events.length - 1];
|
|
953
987
|
const windowLabel = windowMs < 6e4 ? `${Math.round(windowMs / 1e3)}s` : `${(windowMs / 6e4).toFixed(1).replace(/\.0$/, "")}min`;
|
|
954
988
|
const reasonCounts = /* @__PURE__ */ new Map();
|
|
955
989
|
for (const e of events) reasonCounts.set(e.reason, (reasonCounts.get(e.reason) ?? 0) + 1);
|
|
956
990
|
const breakdown = Array.from(reasonCounts.entries()).map(([r, n]) => `${r}=${n}`).join(", ");
|
|
957
991
|
const classLabel = klass === "provisioning" ? "provisioning-reload " : "";
|
|
958
|
-
|
|
992
|
+
const integrationLabel = klass === "provisioning" && integrationKey ? ` for integration '${integrationKey}'` : "";
|
|
993
|
+
return `Circuit breaker tripped: ${events.length} ${classLabel}restarts in ${windowLabel}${integrationLabel} (${breakdown}); most recent=${last.reason} at ${new Date(last.at).toISOString()}`;
|
|
959
994
|
}
|
|
960
995
|
|
|
961
996
|
// src/lib/mcp-flap-dampener.ts
|
|
@@ -3769,6 +3804,17 @@ var agentState = {
|
|
|
3769
3804
|
knownModels: /* @__PURE__ */ new Map(),
|
|
3770
3805
|
knownTasksHashes: /* @__PURE__ */ new Map(),
|
|
3771
3806
|
knownIntegrationHashes: /* @__PURE__ */ new Map(),
|
|
3807
|
+
/**
|
|
3808
|
+
* ENG-7812: the integration MEMBERSHIP (sorted `definition_id`s, credential/
|
|
3809
|
+
* config churn ignored) observed on the previous refresh. Diffed against the
|
|
3810
|
+
* current membership each poll to derive which integration(s) an
|
|
3811
|
+
* `integration-change` / `hot-reload-mcp` restart is attributable to, which the
|
|
3812
|
+
* restart breaker buckets its provisioning trip by (so onboarding many distinct
|
|
3813
|
+
* integrations doesn't auto-pause a healthy new agent). In-memory only: a
|
|
3814
|
+
* manager restart re-seeds it on the first poll (that first delta is treated as
|
|
3815
|
+
* "no attribution", which is safe: it only widens, never narrows, the trip).
|
|
3816
|
+
*/
|
|
3817
|
+
knownIntegrationMembership: /* @__PURE__ */ new Map(),
|
|
3772
3818
|
knownManagedMcpHashes: /* @__PURE__ */ new Map(),
|
|
3773
3819
|
knownManagedMcpStructure: /* @__PURE__ */ new Map(),
|
|
3774
3820
|
/**
|
|
@@ -3804,6 +3850,16 @@ var agentState = {
|
|
|
3804
3850
|
// ---------------------------------------------------------------------------
|
|
3805
3851
|
agentDisplayNames: /* @__PURE__ */ new Map(),
|
|
3806
3852
|
codeNameToAgentId: /* @__PURE__ */ new Map(),
|
|
3853
|
+
/**
|
|
3854
|
+
* ENG-7812: the most recent integration-membership delta for this agent, used
|
|
3855
|
+
* to attribute a provisioning-reload restart to the integration that caused it.
|
|
3856
|
+
* Set when a poll observes an integration add/remove (the changed
|
|
3857
|
+
* `definition_id`s, `+`-joined); read by `recordRestartForBreaker` when a
|
|
3858
|
+
* provisioning restart fires shortly after. `at` bounds its freshness to the
|
|
3859
|
+
* breaker's provisioning window so a stale delta can't mis-attribute a much
|
|
3860
|
+
* later reprovision (those fall through to the shared unattributed bucket).
|
|
3861
|
+
*/
|
|
3862
|
+
provisioningAttribution: /* @__PURE__ */ new Map(),
|
|
3807
3863
|
/**
|
|
3808
3864
|
* Set of code_names with a live persistent session managed by this worker.
|
|
3809
3865
|
* Borderline ownership: written from pollCycle and the persistent-session
|
|
@@ -3841,6 +3897,7 @@ function clearAgentState(agentId, codeName) {
|
|
|
3841
3897
|
agentState.knownModels.delete(agentId);
|
|
3842
3898
|
agentState.knownTasksHashes.delete(agentId);
|
|
3843
3899
|
agentState.knownIntegrationHashes.delete(agentId);
|
|
3900
|
+
agentState.knownIntegrationMembership.delete(agentId);
|
|
3844
3901
|
agentState.knownManagedMcpHashes.delete(agentId);
|
|
3845
3902
|
agentState.knownManagedMcpStructure.delete(agentId);
|
|
3846
3903
|
agentState.knownSenderPolicyHashes.delete(agentId);
|
|
@@ -3849,6 +3906,7 @@ function clearAgentState(agentId, codeName) {
|
|
|
3849
3906
|
agentState.knownGlobalSkillIds.delete(agentId);
|
|
3850
3907
|
agentState.agentDisplayNames.delete(codeName);
|
|
3851
3908
|
agentState.codeNameToAgentId.delete(codeName);
|
|
3909
|
+
agentState.provisioningAttribution.delete(codeName);
|
|
3852
3910
|
let channelCacheMutated = false;
|
|
3853
3911
|
for (const key of agentState.knownChannelConfigHashes.keys()) {
|
|
3854
3912
|
if (key.startsWith(`${agentId}:`)) {
|
|
@@ -5579,9 +5637,9 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
5579
5637
|
import { spawn, execSync } from "child_process";
|
|
5580
5638
|
import { createServer } from "net";
|
|
5581
5639
|
import { randomBytes } from "crypto";
|
|
5582
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync16 } from "fs";
|
|
5640
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "fs";
|
|
5583
5641
|
import { homedir as homedir10, userInfo } from "os";
|
|
5584
|
-
import { join as join20 } from "path";
|
|
5642
|
+
import { join as join20, dirname as dirname6 } from "path";
|
|
5585
5643
|
var OPENCODE_BIN = process.env["AGT_OPENCODE_BIN"]?.trim() || "opencode";
|
|
5586
5644
|
var sessions = /* @__PURE__ */ new Map();
|
|
5587
5645
|
var bridges = /* @__PURE__ */ new Map();
|
|
@@ -5592,14 +5650,43 @@ function opencodePaneLogPath(codeName) {
|
|
|
5592
5650
|
return join20(homedir10(), ".augmented", codeName, "opencode-serve.log");
|
|
5593
5651
|
}
|
|
5594
5652
|
function readProvisionedOpencodeModel(agentDir) {
|
|
5653
|
+
return readOpencodeModelString(join20(agentDir, "provision", "opencode.json"));
|
|
5654
|
+
}
|
|
5655
|
+
function readOpencodeModelString(configPath) {
|
|
5595
5656
|
try {
|
|
5596
|
-
const
|
|
5597
|
-
const parsed = JSON.parse(raw);
|
|
5657
|
+
const parsed = JSON.parse(readFileSync16(configPath, "utf-8"));
|
|
5598
5658
|
return typeof parsed.model === "string" ? parsed.model : null;
|
|
5599
5659
|
} catch {
|
|
5600
5660
|
return null;
|
|
5601
5661
|
}
|
|
5602
5662
|
}
|
|
5663
|
+
function readOpencodeModelFromConfigDir(configDir) {
|
|
5664
|
+
return parseOpencodeModelRef(readOpencodeModelString(join20(configDir, "opencode.json")));
|
|
5665
|
+
}
|
|
5666
|
+
function materializeEnvPlaceholders(raw, env) {
|
|
5667
|
+
return raw.replace(/\{env:([A-Za-z_][A-Za-z0-9_]*)\}/g, (whole, name) => {
|
|
5668
|
+
const v = env[name];
|
|
5669
|
+
return typeof v === "string" && v.length > 0 ? v : whole;
|
|
5670
|
+
});
|
|
5671
|
+
}
|
|
5672
|
+
function deliverOpencodeConfigToXdg(codeName, projectDir, serveEnv, log2) {
|
|
5673
|
+
let raw;
|
|
5674
|
+
try {
|
|
5675
|
+
raw = readFileSync16(join20(projectDir, "opencode.json"), "utf-8");
|
|
5676
|
+
} catch {
|
|
5677
|
+
return null;
|
|
5678
|
+
}
|
|
5679
|
+
const materialized = materializeEnvPlaceholders(raw, serveEnv);
|
|
5680
|
+
const xdgConfigHome = join20(dirname6(projectDir), "opencode-xdg");
|
|
5681
|
+
try {
|
|
5682
|
+
mkdirSync7(join20(xdgConfigHome, "opencode"), { recursive: true });
|
|
5683
|
+
writeFileSync9(join20(xdgConfigHome, "opencode", "opencode.json"), materialized, { mode: 384 });
|
|
5684
|
+
return xdgConfigHome;
|
|
5685
|
+
} catch (err) {
|
|
5686
|
+
log2(`[opencode-session] failed to deliver opencode config to XDG for '${codeName}': ${err.message}`);
|
|
5687
|
+
return null;
|
|
5688
|
+
}
|
|
5689
|
+
}
|
|
5603
5690
|
function baseUrlFor(port) {
|
|
5604
5691
|
return `http://127.0.0.1:${port}`;
|
|
5605
5692
|
}
|
|
@@ -5638,7 +5725,8 @@ async function startOpencodeSession(config2) {
|
|
|
5638
5725
|
status: "crashed",
|
|
5639
5726
|
port: null,
|
|
5640
5727
|
password: null,
|
|
5641
|
-
lastFailureTail: "opencode isolation not implemented (ADR-0047)"
|
|
5728
|
+
lastFailureTail: "opencode isolation not implemented (ADR-0047)",
|
|
5729
|
+
model: null
|
|
5642
5730
|
};
|
|
5643
5731
|
sessions.set(codeName, blocked);
|
|
5644
5732
|
return blocked;
|
|
@@ -5650,7 +5738,11 @@ async function startOpencodeSession(config2) {
|
|
|
5650
5738
|
status: "starting",
|
|
5651
5739
|
port: null,
|
|
5652
5740
|
password: null,
|
|
5653
|
-
lastFailureTail: existing?.lastFailureTail ?? null
|
|
5741
|
+
lastFailureTail: existing?.lastFailureTail ?? null,
|
|
5742
|
+
// ENG-7931: parse the resolved model from the provisioned opencode.json
|
|
5743
|
+
// (config.projectDir IS the provision dir the serve reads) so the bridge can
|
|
5744
|
+
// pass it explicitly on session-create + prompt.
|
|
5745
|
+
model: readOpencodeModelFromConfigDir(config2.projectDir)
|
|
5654
5746
|
};
|
|
5655
5747
|
sessions.set(codeName, session);
|
|
5656
5748
|
try {
|
|
@@ -5686,6 +5778,8 @@ async function spawnServe(config2, session) {
|
|
|
5686
5778
|
};
|
|
5687
5779
|
if (config2.runId) serveEnv["AGT_RUN_ID"] = config2.runId;
|
|
5688
5780
|
if (config2.agentTimezone) serveEnv["TZ"] = config2.agentTimezone;
|
|
5781
|
+
const xdgConfigHome = deliverOpencodeConfigToXdg(codeName, projectDir, serveEnv, log2);
|
|
5782
|
+
if (xdgConfigHome) serveEnv["XDG_CONFIG_HOME"] = xdgConfigHome;
|
|
5689
5783
|
const serveCmd = `${OPENCODE_BIN} serve --hostname 127.0.0.1 --port ${port} --print-logs`;
|
|
5690
5784
|
log2(`[opencode-session] starting '${tmuxSession}' for '${codeName}' on 127.0.0.1:${port}`);
|
|
5691
5785
|
const child = spawn(
|
|
@@ -5756,7 +5850,11 @@ function getBridge(codeName, port, password) {
|
|
|
5756
5850
|
const cached = bridges.get(codeName);
|
|
5757
5851
|
if (cached && cached.port === port && cached.password === password) return cached.bridge;
|
|
5758
5852
|
const client2 = new HttpOpencodeClient({ baseUrl: baseUrlFor(port), password });
|
|
5759
|
-
const
|
|
5853
|
+
const model = sessions.get(codeName)?.model ?? null;
|
|
5854
|
+
const bridge = new OpencodeInboundBridge({
|
|
5855
|
+
client: client2,
|
|
5856
|
+
sessionDefaults: model ? { model } : void 0
|
|
5857
|
+
});
|
|
5760
5858
|
bridges.set(codeName, { port, password, bridge });
|
|
5761
5859
|
return bridge;
|
|
5762
5860
|
}
|
|
@@ -6915,7 +7013,7 @@ async function fireOpencodeScheduledTask(agent, task) {
|
|
|
6915
7013
|
|
|
6916
7014
|
// src/lib/opencode-telegram-ingest.ts
|
|
6917
7015
|
import { createHash as createHash13 } from "crypto";
|
|
6918
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync2, unlinkSync, writeFileSync as
|
|
7016
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync10 } from "fs";
|
|
6919
7017
|
import { randomUUID } from "crypto";
|
|
6920
7018
|
import { join as join21 } from "path";
|
|
6921
7019
|
|
|
@@ -7493,7 +7591,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
|
|
|
7493
7591
|
const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
7494
7592
|
try {
|
|
7495
7593
|
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
7496
|
-
|
|
7594
|
+
writeFileSync10(
|
|
7497
7595
|
tmpPath,
|
|
7498
7596
|
JSON.stringify({
|
|
7499
7597
|
offset,
|
|
@@ -7724,7 +7822,7 @@ function partitionActionableByPoison(actionable, states, config2) {
|
|
|
7724
7822
|
}
|
|
7725
7823
|
|
|
7726
7824
|
// src/lib/restart-flags.ts
|
|
7727
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync9, readdirSync as readdirSync4, readFileSync as readFileSync18, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as
|
|
7825
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync9, readdirSync as readdirSync4, readFileSync as readFileSync18, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
7728
7826
|
import { homedir as homedir11 } from "os";
|
|
7729
7827
|
import { join as join22 } from "path";
|
|
7730
7828
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -8472,6 +8570,10 @@ var pendingRestartVerifications = /* @__PURE__ */ new Map();
|
|
|
8472
8570
|
var restartBreaker = new RestartBreaker();
|
|
8473
8571
|
var reportedTrips = /* @__PURE__ */ new Map();
|
|
8474
8572
|
var RESTART_BREAKER_PROVISIONING_MAX = readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_MAX", 5);
|
|
8573
|
+
var RESTART_BREAKER_PROVISIONING_WINDOW_MS = readEnvNumber(
|
|
8574
|
+
"AGT_RESTART_BREAKER_PROVISIONING_WINDOW_MS",
|
|
8575
|
+
18e5
|
|
8576
|
+
);
|
|
8475
8577
|
var mcpFlapDampener = new McpFlapDampener();
|
|
8476
8578
|
var FLAP_BREAKER_COOLDOWN_MS = readEnvNumber2(
|
|
8477
8579
|
"AGT_MCP_FLAP_BREAKER_COOLDOWN_MS",
|
|
@@ -8510,11 +8612,19 @@ function recordRestartForBreaker(codeName, reason) {
|
|
|
8510
8612
|
);
|
|
8511
8613
|
return;
|
|
8512
8614
|
}
|
|
8513
|
-
|
|
8615
|
+
let integrationKey;
|
|
8616
|
+
if (isProvisioningReloadReason(reason)) {
|
|
8617
|
+
const attribution = agentState.provisioningAttribution.get(codeName);
|
|
8618
|
+
if (attribution && Date.now() - attribution.at <= RESTART_BREAKER_PROVISIONING_WINDOW_MS) {
|
|
8619
|
+
integrationKey = attribution.key;
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
const result = restartBreaker.record(codeName, reason, integrationKey);
|
|
8514
8623
|
if (!result.tripped || !result.trip) {
|
|
8515
|
-
if (isProvisioningReloadReason(reason) && result.
|
|
8624
|
+
if (isProvisioningReloadReason(reason) && result.maxProvisioningBucket >= RESTART_BREAKER_PROVISIONING_MAX) {
|
|
8625
|
+
const culprit = result.maxProvisioningBucketKey ? ` [${result.maxProvisioningBucketKey}]` : "";
|
|
8516
8626
|
log(
|
|
8517
|
-
`[restart-breaker] agent=${codeName} provisioning-reload churn at the trip bar: ${result.
|
|
8627
|
+
`[restart-breaker] agent=${codeName} provisioning-reload churn at the trip bar: ${result.maxProvisioningBucket} restarts for one integration${culprit} in window (reason=${reason}); one more will auto-pause the agent; that integration is likely churning (ENG-7560, ENG-7812)`
|
|
8518
8628
|
);
|
|
8519
8629
|
}
|
|
8520
8630
|
return;
|
|
@@ -9342,7 +9452,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9342
9452
|
var lastVersionCheckAt = 0;
|
|
9343
9453
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9344
9454
|
var lastResponsivenessProbeAt = 0;
|
|
9345
|
-
var agtCliVersion = true ? "0.28.
|
|
9455
|
+
var agtCliVersion = true ? "0.28.354" : "dev";
|
|
9346
9456
|
function resolveBrewPath(execFileSync2) {
|
|
9347
9457
|
try {
|
|
9348
9458
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -9437,7 +9547,7 @@ async function ensureToolkitCli(toolkitSlug) {
|
|
|
9437
9547
|
toolkitCliEnsured.add(toolkitSlug);
|
|
9438
9548
|
return;
|
|
9439
9549
|
}
|
|
9440
|
-
brewBinDir =
|
|
9550
|
+
brewBinDir = dirname7(brewPath);
|
|
9441
9551
|
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
9442
9552
|
log(`[toolkit-install] ${toolkitSlug}: installing via brew (${pkg})\u2026`);
|
|
9443
9553
|
if (isRoot) {
|
|
@@ -9537,8 +9647,8 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
|
|
|
9537
9647
|
}
|
|
9538
9648
|
if (settings.channelsEnabled === true) return "ok";
|
|
9539
9649
|
settings.channelsEnabled = true;
|
|
9540
|
-
mkdirSync10(
|
|
9541
|
-
|
|
9650
|
+
mkdirSync10(dirname7(path), { recursive: true });
|
|
9651
|
+
writeFileSync12(path, `${JSON.stringify(settings, null, 2)}
|
|
9542
9652
|
`);
|
|
9543
9653
|
log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
|
|
9544
9654
|
return "ok";
|
|
@@ -9633,7 +9743,7 @@ async function ensureFrameworkBinary(frameworkId) {
|
|
|
9633
9743
|
log(`Claude Code install failed: ${err.message}`);
|
|
9634
9744
|
return;
|
|
9635
9745
|
}
|
|
9636
|
-
const brewBinDir =
|
|
9746
|
+
const brewBinDir = dirname7(brewPath);
|
|
9637
9747
|
if (!process.env.PATH?.split(":").includes(brewBinDir)) {
|
|
9638
9748
|
process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
|
|
9639
9749
|
}
|
|
@@ -10071,7 +10181,7 @@ function ensureEvalEmptyMcpConfig() {
|
|
|
10071
10181
|
} catch {
|
|
10072
10182
|
}
|
|
10073
10183
|
const p = join23(dir, ".eval-empty-mcp.json");
|
|
10074
|
-
|
|
10184
|
+
writeFileSync12(p, JSON.stringify({ mcpServers: {} }));
|
|
10075
10185
|
evalEmptyMcpConfigPath = p;
|
|
10076
10186
|
return p;
|
|
10077
10187
|
}
|
|
@@ -10292,7 +10402,7 @@ function parseSkillFrontmatter(content) {
|
|
|
10292
10402
|
return out;
|
|
10293
10403
|
}
|
|
10294
10404
|
async function refreshSkillsIndexInClaudeMd(configDir, codeName, log2) {
|
|
10295
|
-
const { readdirSync: readdirSync6, readFileSync: rfs, existsSync: ex, writeFileSync:
|
|
10405
|
+
const { readdirSync: readdirSync6, readFileSync: rfs, existsSync: ex, writeFileSync: writeFileSync13 } = await import("fs");
|
|
10296
10406
|
const skillsDir = join23(configDir, codeName, "project", ".claude", "skills");
|
|
10297
10407
|
const claudeMdPath = join23(configDir, codeName, "project", "CLAUDE.md");
|
|
10298
10408
|
if (!ex(skillsDir) || !ex(claudeMdPath)) return;
|
|
@@ -10340,7 +10450,7 @@ ${SKILLS_INDEX_END}`;
|
|
|
10340
10450
|
next = current.trimEnd() + "\n\n" + section + "\n";
|
|
10341
10451
|
}
|
|
10342
10452
|
if (next !== current) {
|
|
10343
|
-
|
|
10453
|
+
writeFileSync13(claudeMdPath, next, "utf-8");
|
|
10344
10454
|
log2(`Refreshed skills index in CLAUDE.md for '${codeName}' (${entries.length} skills)`);
|
|
10345
10455
|
}
|
|
10346
10456
|
}
|
|
@@ -10361,7 +10471,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
10361
10471
|
if (codeNames.length === 0) return;
|
|
10362
10472
|
void (async () => {
|
|
10363
10473
|
try {
|
|
10364
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10474
|
+
const { collectDiagnostics } = await import("../persistent-session-SZ5VHS4C.js");
|
|
10365
10475
|
await api.post("/host/heartbeat", {
|
|
10366
10476
|
host_id: hostId,
|
|
10367
10477
|
agent_diagnostics: collectDiagnostics(codeNames)
|
|
@@ -10460,7 +10570,7 @@ async function pollCycle() {
|
|
|
10460
10570
|
}
|
|
10461
10571
|
try {
|
|
10462
10572
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
10463
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10573
|
+
const { collectDiagnostics } = await import("../persistent-session-SZ5VHS4C.js");
|
|
10464
10574
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
10465
10575
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
10466
10576
|
let tailscaleHostname;
|
|
@@ -10615,7 +10725,7 @@ async function pollCycle() {
|
|
|
10615
10725
|
const {
|
|
10616
10726
|
collectResponsivenessProbes,
|
|
10617
10727
|
getResponsivenessIntervalMs
|
|
10618
|
-
} = await import("../responsiveness-probe-
|
|
10728
|
+
} = await import("../responsiveness-probe-2D64EQAU.js");
|
|
10619
10729
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
10620
10730
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
10621
10731
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -10647,7 +10757,7 @@ async function pollCycle() {
|
|
|
10647
10757
|
collectResponsivenessProbes,
|
|
10648
10758
|
livePendingInboundOldestAgeSeconds,
|
|
10649
10759
|
parkPendingInbound
|
|
10650
|
-
} = await import("../responsiveness-probe-
|
|
10760
|
+
} = await import("../responsiveness-probe-2D64EQAU.js");
|
|
10651
10761
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-HYOOQV4A.js");
|
|
10652
10762
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
10653
10763
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -11517,11 +11627,11 @@ async function processAgent(agent, agentStates) {
|
|
|
11517
11627
|
log(`${verb} '${agent.code_name}': ${fileNames}`);
|
|
11518
11628
|
for (const file of changedFiles) {
|
|
11519
11629
|
const filePath = join23(agentDir, file.relativePath);
|
|
11520
|
-
mkdirSync10(
|
|
11630
|
+
mkdirSync10(dirname7(filePath), { recursive: true });
|
|
11521
11631
|
if (file.relativePath === ".mcp.json") {
|
|
11522
11632
|
safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
|
|
11523
11633
|
} else {
|
|
11524
|
-
|
|
11634
|
+
writeFileSync12(filePath, file.content);
|
|
11525
11635
|
}
|
|
11526
11636
|
}
|
|
11527
11637
|
try {
|
|
@@ -12231,6 +12341,25 @@ async function processAgent(agent, agentStates) {
|
|
|
12231
12341
|
}
|
|
12232
12342
|
}
|
|
12233
12343
|
}
|
|
12344
|
+
const currentIntIds = integrations.map((i) => i.definition_id);
|
|
12345
|
+
const prevIntIds = agentState.knownIntegrationMembership.get(agent.agent_id) ?? [];
|
|
12346
|
+
const prevIntSet = new Set(prevIntIds);
|
|
12347
|
+
const curIntSet = new Set(currentIntIds);
|
|
12348
|
+
const changedIntIds = Array.from(
|
|
12349
|
+
/* @__PURE__ */ new Set([
|
|
12350
|
+
...currentIntIds.filter((id) => !prevIntSet.has(id)),
|
|
12351
|
+
// added
|
|
12352
|
+
...prevIntIds.filter((id) => !curIntSet.has(id))
|
|
12353
|
+
// removed
|
|
12354
|
+
])
|
|
12355
|
+
).sort();
|
|
12356
|
+
if (changedIntIds.length > 0) {
|
|
12357
|
+
agentState.provisioningAttribution.set(agent.code_name, {
|
|
12358
|
+
key: changedIntIds.join("+"),
|
|
12359
|
+
at: Date.now()
|
|
12360
|
+
});
|
|
12361
|
+
}
|
|
12362
|
+
agentState.knownIntegrationMembership.set(agent.agent_id, currentIntIds);
|
|
12234
12363
|
if (integrations.length > 0) {
|
|
12235
12364
|
const intHash = computeIntegrationsHash(integrations);
|
|
12236
12365
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
@@ -13783,7 +13912,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
13783
13912
|
void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
|
|
13784
13913
|
void (async () => {
|
|
13785
13914
|
try {
|
|
13786
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
13915
|
+
const { collectDiagnostics } = await import("../persistent-session-SZ5VHS4C.js");
|
|
13787
13916
|
await api.post("/host/heartbeat", {
|
|
13788
13917
|
host_id: hostId,
|
|
13789
13918
|
agent_diagnostics: collectDiagnostics([codeName])
|
|
@@ -13833,7 +13962,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
13833
13962
|
}
|
|
13834
13963
|
try {
|
|
13835
13964
|
const hostId = await getHostId();
|
|
13836
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
13965
|
+
const { collectDiagnostics } = await import("../persistent-session-SZ5VHS4C.js");
|
|
13837
13966
|
await api.post("/host/heartbeat", {
|
|
13838
13967
|
host_id: hostId,
|
|
13839
13968
|
agent_diagnostics: collectDiagnostics([codeName])
|
|
@@ -14119,8 +14248,8 @@ async function processDirectChatMessage(agent, msg) {
|
|
|
14119
14248
|
if (useDoorbell) {
|
|
14120
14249
|
try {
|
|
14121
14250
|
const doorbell = directChatDoorbellPath(agent.agentId, homedir12());
|
|
14122
|
-
mkdirSync10(
|
|
14123
|
-
|
|
14251
|
+
mkdirSync10(dirname7(doorbell), { recursive: true });
|
|
14252
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
14124
14253
|
log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
|
|
14125
14254
|
return;
|
|
14126
14255
|
} catch (err) {
|
|
@@ -14229,8 +14358,8 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
|
|
|
14229
14358
|
if (run_id) openInjectedRunByCode.set(codeName, run_id);
|
|
14230
14359
|
try {
|
|
14231
14360
|
const doorbell = directChatDoorbellPath(agentId, homedir12());
|
|
14232
|
-
mkdirSync10(
|
|
14233
|
-
|
|
14361
|
+
mkdirSync10(dirname7(doorbell), { recursive: true });
|
|
14362
|
+
writeFileSync12(doorbell, String(Date.now()));
|
|
14234
14363
|
} catch (err) {
|
|
14235
14364
|
log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
|
|
14236
14365
|
}
|
|
@@ -14331,7 +14460,7 @@ async function processClaudePairSessions(agents) {
|
|
|
14331
14460
|
killPairSession,
|
|
14332
14461
|
pairTmuxSession,
|
|
14333
14462
|
finalizeClaudePairOnboarding
|
|
14334
|
-
} = await import("../claude-pair-runtime-
|
|
14463
|
+
} = await import("../claude-pair-runtime-LLUV4KX6.js");
|
|
14335
14464
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
14336
14465
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
14337
14466
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -14676,10 +14805,10 @@ ${mem.content}
|
|
|
14676
14805
|
} catch {
|
|
14677
14806
|
}
|
|
14678
14807
|
if (existing === desired) continue;
|
|
14679
|
-
|
|
14808
|
+
writeFileSync12(filePath, desired);
|
|
14680
14809
|
overwritten++;
|
|
14681
14810
|
} else {
|
|
14682
|
-
|
|
14811
|
+
writeFileSync12(filePath, desired);
|
|
14683
14812
|
written++;
|
|
14684
14813
|
}
|
|
14685
14814
|
}
|
|
@@ -15081,7 +15210,7 @@ function restartRunningChannelMcps(basenames) {
|
|
|
15081
15210
|
function deployMcpAssets() {
|
|
15082
15211
|
const targetDir = join23(homedir12(), ".augmented", "_mcp");
|
|
15083
15212
|
mkdirSync10(targetDir, { recursive: true });
|
|
15084
|
-
const moduleDir =
|
|
15213
|
+
const moduleDir = dirname7(fileURLToPath(import.meta.url));
|
|
15085
15214
|
let mcpSourceDir = "";
|
|
15086
15215
|
let dir = moduleDir;
|
|
15087
15216
|
for (let i = 0; i < 6; i++) {
|
|
@@ -15090,7 +15219,7 @@ function deployMcpAssets() {
|
|
|
15090
15219
|
mcpSourceDir = candidate;
|
|
15091
15220
|
break;
|
|
15092
15221
|
}
|
|
15093
|
-
const parent =
|
|
15222
|
+
const parent = dirname7(dir);
|
|
15094
15223
|
if (parent === dir) break;
|
|
15095
15224
|
dir = parent;
|
|
15096
15225
|
}
|
|
@@ -15201,7 +15330,7 @@ function deployMcpAssets() {
|
|
|
15201
15330
|
if (!augServer) continue;
|
|
15202
15331
|
augServer.command = "node";
|
|
15203
15332
|
augServer.args = [localMcpPath];
|
|
15204
|
-
|
|
15333
|
+
writeFileSync12(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
15205
15334
|
log(`[manager] Patched ${entry.name}/${subdir}/.mcp.json: npx \u2192 node`);
|
|
15206
15335
|
} catch {
|
|
15207
15336
|
}
|