@integrity-labs/agt-cli 0.28.448 → 0.28.450
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-JUUAHLX5.js → chunk-NJZI6BPI.js} +2 -2
- package/dist/lib/manager-worker.js +4 -4
- package/dist/mcp/slack-channel.js +587 -168
- package/dist/mcp/telegram-channel.js +488 -103
- package/dist/{responsiveness-probe-FJ7TRQE2.js → responsiveness-probe-AIA7ZEBW.js} +58 -1
- package/dist/responsiveness-probe-AIA7ZEBW.js.map +1 -0
- package/package.json +1 -1
- package/dist/responsiveness-probe-FJ7TRQE2.js.map +0 -1
- /package/dist/{chunk-JUUAHLX5.js.map → chunk-NJZI6BPI.js.map} +0 -0
|
@@ -18870,7 +18870,7 @@ var require_filters = __commonJS({
|
|
|
18870
18870
|
return r.copySafeness(str, res);
|
|
18871
18871
|
}
|
|
18872
18872
|
_exports.indent = indent;
|
|
18873
|
-
function
|
|
18873
|
+
function join21(arr, del, attr) {
|
|
18874
18874
|
del = del || "";
|
|
18875
18875
|
if (attr) {
|
|
18876
18876
|
arr = lib.map(arr, function(v) {
|
|
@@ -18879,7 +18879,7 @@ var require_filters = __commonJS({
|
|
|
18879
18879
|
}
|
|
18880
18880
|
return arr.join(del);
|
|
18881
18881
|
}
|
|
18882
|
-
_exports.join =
|
|
18882
|
+
_exports.join = join21;
|
|
18883
18883
|
function last(arr) {
|
|
18884
18884
|
return arr[arr.length - 1];
|
|
18885
18885
|
}
|
|
@@ -22480,11 +22480,11 @@ async function waitForResolution(cfg, callbackId, opts) {
|
|
|
22480
22480
|
}
|
|
22481
22481
|
} catch {
|
|
22482
22482
|
}
|
|
22483
|
-
await
|
|
22483
|
+
await sleep2(interval);
|
|
22484
22484
|
}
|
|
22485
22485
|
return { kind: "timeout" };
|
|
22486
22486
|
}
|
|
22487
|
-
function
|
|
22487
|
+
function sleep2(ms) {
|
|
22488
22488
|
return new Promise((r) => setTimeout(r, ms));
|
|
22489
22489
|
}
|
|
22490
22490
|
function generateOptionToken() {
|
|
@@ -30393,6 +30393,40 @@ function resolveSlackScheduledChannelGuardMode(opts) {
|
|
|
30393
30393
|
if (cached2 !== void 0) return clampScheduledChannelGuardMode(cached2);
|
|
30394
30394
|
return "shadow";
|
|
30395
30395
|
}
|
|
30396
|
+
var USAGE_LIMIT_REACTIVE_FLAG_KEY = "usage-limit-reactive-notice";
|
|
30397
|
+
function parseUsageLimitReactiveMode(raw) {
|
|
30398
|
+
if (raw === void 0) return void 0;
|
|
30399
|
+
const v = raw.trim().toLowerCase();
|
|
30400
|
+
if (v === "") return void 0;
|
|
30401
|
+
if (v === "off" || v === "shadow" || v === "enforce") return v;
|
|
30402
|
+
const b = envBoolean(raw);
|
|
30403
|
+
if (b === true) return "enforce";
|
|
30404
|
+
if (b === false) return "off";
|
|
30405
|
+
return void 0;
|
|
30406
|
+
}
|
|
30407
|
+
function cachedUsageLimitReactiveMode(path) {
|
|
30408
|
+
try {
|
|
30409
|
+
if (!existsSync(path)) return void 0;
|
|
30410
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
30411
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
30412
|
+
const flags = parsed.flags;
|
|
30413
|
+
if (!flags || typeof flags !== "object") return void 0;
|
|
30414
|
+
const value = flags[USAGE_LIMIT_REACTIVE_FLAG_KEY];
|
|
30415
|
+
if (typeof value === "string") return parseUsageLimitReactiveMode(value);
|
|
30416
|
+
if (typeof value === "boolean") return value ? "enforce" : "off";
|
|
30417
|
+
return void 0;
|
|
30418
|
+
} catch {
|
|
30419
|
+
return void 0;
|
|
30420
|
+
}
|
|
30421
|
+
}
|
|
30422
|
+
function resolveUsageLimitReactiveMode(opts) {
|
|
30423
|
+
const env2 = opts?.env ?? process.env;
|
|
30424
|
+
const modeOverride = parseUsageLimitReactiveMode(env2["AGT_USAGE_LIMIT_REACTIVE_MODE"]);
|
|
30425
|
+
if (modeOverride !== void 0) return modeOverride;
|
|
30426
|
+
const cached2 = cachedUsageLimitReactiveMode(opts?.cachePath ?? defaultFlagsCachePath());
|
|
30427
|
+
if (cached2 !== void 0) return cached2;
|
|
30428
|
+
return "off";
|
|
30429
|
+
}
|
|
30396
30430
|
|
|
30397
30431
|
// src/maintenance-mode.ts
|
|
30398
30432
|
var FLAG_KEY = "platform-maintenance-mode";
|
|
@@ -33734,7 +33768,113 @@ var BANNER_PATTERNS = [
|
|
|
33734
33768
|
// pct=100.
|
|
33735
33769
|
new RegExp(`${SUBJECT}hit\\s+your\\s+(?:[a-z0-9-]+\\s+)?limit${SEP}resets\\s+(${RESET_DATE})`, "i")
|
|
33736
33770
|
];
|
|
33771
|
+
function parseUsageBanner(text, now = /* @__PURE__ */ new Date()) {
|
|
33772
|
+
let bestIndex = -1;
|
|
33773
|
+
let best = null;
|
|
33774
|
+
for (let i = 0; i < BANNER_PATTERNS.length; i++) {
|
|
33775
|
+
const pattern = new RegExp(BANNER_PATTERNS[i].source, "gi");
|
|
33776
|
+
let match;
|
|
33777
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
33778
|
+
if (match.index === pattern.lastIndex)
|
|
33779
|
+
pattern.lastIndex++;
|
|
33780
|
+
let pct;
|
|
33781
|
+
let resetStr;
|
|
33782
|
+
if (i === 0) {
|
|
33783
|
+
pct = Number.parseInt(match[1], 10);
|
|
33784
|
+
resetStr = match[2];
|
|
33785
|
+
} else {
|
|
33786
|
+
pct = 100;
|
|
33787
|
+
resetStr = match[1];
|
|
33788
|
+
}
|
|
33789
|
+
if (!Number.isFinite(pct) || pct < 0 || pct > 100)
|
|
33790
|
+
continue;
|
|
33791
|
+
const nextChar = text[match.index + match[0].length];
|
|
33792
|
+
if (nextChar !== void 0 && /[A-Za-z0-9]/.test(nextChar))
|
|
33793
|
+
continue;
|
|
33794
|
+
const weekResetsAt = parseResetDateTime(resetStr, now);
|
|
33795
|
+
if (!weekResetsAt)
|
|
33796
|
+
continue;
|
|
33797
|
+
if (match.index >= bestIndex) {
|
|
33798
|
+
bestIndex = match.index;
|
|
33799
|
+
best = { pct, weekResetsAt };
|
|
33800
|
+
}
|
|
33801
|
+
}
|
|
33802
|
+
}
|
|
33803
|
+
return best;
|
|
33804
|
+
}
|
|
33805
|
+
var MONTHS = [
|
|
33806
|
+
"jan",
|
|
33807
|
+
"feb",
|
|
33808
|
+
"mar",
|
|
33809
|
+
"apr",
|
|
33810
|
+
"may",
|
|
33811
|
+
"jun",
|
|
33812
|
+
"jul",
|
|
33813
|
+
"aug",
|
|
33814
|
+
"sep",
|
|
33815
|
+
"oct",
|
|
33816
|
+
"nov",
|
|
33817
|
+
"dec"
|
|
33818
|
+
];
|
|
33819
|
+
var TIME_TAIL = /,\s*(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(?UTC\)?)?\s*$/i;
|
|
33820
|
+
var TIME_ONLY = /^(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(?UTC\)?)?$/i;
|
|
33737
33821
|
var MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
33822
|
+
function parseAmPm(hourStr, minStr, ampm) {
|
|
33823
|
+
const rawHour = Number.parseInt(hourStr, 10);
|
|
33824
|
+
if (!Number.isFinite(rawHour) || rawHour < 1 || rawHour > 12)
|
|
33825
|
+
return null;
|
|
33826
|
+
let minute = 0;
|
|
33827
|
+
if (minStr) {
|
|
33828
|
+
minute = Number.parseInt(minStr, 10);
|
|
33829
|
+
if (!Number.isFinite(minute) || minute < 0 || minute > 59)
|
|
33830
|
+
return null;
|
|
33831
|
+
}
|
|
33832
|
+
const isPm = ampm.toLowerCase() === "pm";
|
|
33833
|
+
return { hour: rawHour % 12 + (isPm ? 12 : 0), minute };
|
|
33834
|
+
}
|
|
33835
|
+
function parseResetDateTime(humanDate, now) {
|
|
33836
|
+
const trimmed = humanDate.trim();
|
|
33837
|
+
const timeOnly = trimmed.match(TIME_ONLY);
|
|
33838
|
+
if (timeOnly) {
|
|
33839
|
+
const hm = parseAmPm(timeOnly[1], timeOnly[2], timeOnly[3]);
|
|
33840
|
+
if (!hm)
|
|
33841
|
+
return null;
|
|
33842
|
+
const todayAt = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), hm.hour, hm.minute);
|
|
33843
|
+
return new Date(todayAt <= now.getTime() ? todayAt + MS_PER_DAY : todayAt);
|
|
33844
|
+
}
|
|
33845
|
+
const timeMatch = trimmed.match(TIME_TAIL);
|
|
33846
|
+
const dateOnly = timeMatch ? trimmed.slice(0, timeMatch.index).trim() : trimmed;
|
|
33847
|
+
const parts = dateOnly.split(/\s+/);
|
|
33848
|
+
if (parts.length !== 2)
|
|
33849
|
+
return null;
|
|
33850
|
+
const month = MONTHS.indexOf(parts[0].slice(0, 3).toLowerCase());
|
|
33851
|
+
if (month < 0)
|
|
33852
|
+
return null;
|
|
33853
|
+
const day = Number.parseInt(parts[1], 10);
|
|
33854
|
+
if (!Number.isFinite(day) || day < 1 || day > 31)
|
|
33855
|
+
return null;
|
|
33856
|
+
let hour = 0;
|
|
33857
|
+
let minute = 0;
|
|
33858
|
+
if (timeMatch) {
|
|
33859
|
+
const hm = parseAmPm(timeMatch[1], timeMatch[2], timeMatch[3]);
|
|
33860
|
+
if (!hm)
|
|
33861
|
+
return null;
|
|
33862
|
+
hour = hm.hour;
|
|
33863
|
+
minute = hm.minute;
|
|
33864
|
+
}
|
|
33865
|
+
const baseYear = now.getUTCFullYear();
|
|
33866
|
+
let resolved = null;
|
|
33867
|
+
let bestDelta = Number.POSITIVE_INFINITY;
|
|
33868
|
+
for (const y of [baseYear - 1, baseYear, baseYear + 1]) {
|
|
33869
|
+
const candidate = new Date(Date.UTC(y, month, day, hour, minute));
|
|
33870
|
+
const delta = Math.abs(candidate.getTime() - now.getTime());
|
|
33871
|
+
if (delta < bestDelta) {
|
|
33872
|
+
bestDelta = delta;
|
|
33873
|
+
resolved = candidate;
|
|
33874
|
+
}
|
|
33875
|
+
}
|
|
33876
|
+
return resolved;
|
|
33877
|
+
}
|
|
33738
33878
|
|
|
33739
33879
|
// ../core/dist/claude-code-usage/usage-limit-marker.js
|
|
33740
33880
|
var USAGE_LIMIT_MARKER_FILENAME = "claude-usage-limit.json";
|
|
@@ -33779,6 +33919,101 @@ var UNKNOWN_RATE_LIMIT = Object.freeze({
|
|
|
33779
33919
|
resetsAt: null,
|
|
33780
33920
|
text: null
|
|
33781
33921
|
});
|
|
33922
|
+
function contentText(record2) {
|
|
33923
|
+
const candidates = [record2.content];
|
|
33924
|
+
const message = record2.message;
|
|
33925
|
+
if (typeof message === "object" && message !== null) {
|
|
33926
|
+
candidates.push(message.content);
|
|
33927
|
+
}
|
|
33928
|
+
const parts = [];
|
|
33929
|
+
for (const candidate of candidates) {
|
|
33930
|
+
if (typeof candidate === "string") {
|
|
33931
|
+
if (candidate)
|
|
33932
|
+
parts.push(candidate);
|
|
33933
|
+
continue;
|
|
33934
|
+
}
|
|
33935
|
+
if (!Array.isArray(candidate))
|
|
33936
|
+
continue;
|
|
33937
|
+
for (const block of candidate) {
|
|
33938
|
+
if (typeof block === "string") {
|
|
33939
|
+
if (block)
|
|
33940
|
+
parts.push(block);
|
|
33941
|
+
continue;
|
|
33942
|
+
}
|
|
33943
|
+
if (typeof block !== "object" || block === null)
|
|
33944
|
+
continue;
|
|
33945
|
+
const text = block.text;
|
|
33946
|
+
if (typeof text === "string" && text)
|
|
33947
|
+
parts.push(text);
|
|
33948
|
+
}
|
|
33949
|
+
}
|
|
33950
|
+
const joined = parts.join("\n").trim();
|
|
33951
|
+
return joined ? joined : null;
|
|
33952
|
+
}
|
|
33953
|
+
function classifyTranscriptLine(line, startMs, endMs, now) {
|
|
33954
|
+
const trimmed = line.trim();
|
|
33955
|
+
if (!trimmed)
|
|
33956
|
+
return null;
|
|
33957
|
+
let obj;
|
|
33958
|
+
try {
|
|
33959
|
+
obj = JSON.parse(trimmed);
|
|
33960
|
+
} catch {
|
|
33961
|
+
return null;
|
|
33962
|
+
}
|
|
33963
|
+
if (typeof obj !== "object" || obj === null)
|
|
33964
|
+
return null;
|
|
33965
|
+
const record2 = obj;
|
|
33966
|
+
if (record2.type !== "assistant")
|
|
33967
|
+
return null;
|
|
33968
|
+
const ts = record2.timestamp;
|
|
33969
|
+
if (typeof ts !== "string" || !ts)
|
|
33970
|
+
return null;
|
|
33971
|
+
const tsMs = new Date(ts).getTime();
|
|
33972
|
+
if (!Number.isFinite(tsMs) || tsMs < startMs || tsMs > endMs)
|
|
33973
|
+
return null;
|
|
33974
|
+
if (record2.error === "rate_limit" || record2.apiErrorStatus === 429) {
|
|
33975
|
+
const text = contentText(record2);
|
|
33976
|
+
const observation = text ? parseUsageBanner(text, now ?? new Date(endMs)) : null;
|
|
33977
|
+
return { verdict: "capped", atMs: tsMs, resetsAt: observation?.weekResetsAt ?? null, text };
|
|
33978
|
+
}
|
|
33979
|
+
if (record2.isApiErrorMessage === true)
|
|
33980
|
+
return null;
|
|
33981
|
+
const message = record2.message;
|
|
33982
|
+
if (typeof message !== "object" || message === null)
|
|
33983
|
+
return null;
|
|
33984
|
+
const msg = message;
|
|
33985
|
+
if (msg.model === "<synthetic>")
|
|
33986
|
+
return null;
|
|
33987
|
+
const usage = msg.usage;
|
|
33988
|
+
if (typeof usage !== "object" || usage === null)
|
|
33989
|
+
return null;
|
|
33990
|
+
const u = usage;
|
|
33991
|
+
const spent = Number(u.input_tokens ?? 0) + Number(u.output_tokens ?? 0) + Number(u.cache_creation_input_tokens ?? 0) + Number(u.cache_read_input_tokens ?? 0);
|
|
33992
|
+
if (!Number.isFinite(spent) || spent <= 0)
|
|
33993
|
+
return null;
|
|
33994
|
+
return { verdict: "serving", atMs: tsMs, resetsAt: null, text: null };
|
|
33995
|
+
}
|
|
33996
|
+
function pickNewerClassification(current, next) {
|
|
33997
|
+
if (next.verdict === "unknown")
|
|
33998
|
+
return current;
|
|
33999
|
+
if (current.verdict === "unknown")
|
|
34000
|
+
return next;
|
|
34001
|
+
return next.atMs >= current.atMs ? next : current;
|
|
34002
|
+
}
|
|
34003
|
+
function classifyTranscriptRateLimit(jsonl, startMs, endMs, now) {
|
|
34004
|
+
let newest = UNKNOWN_RATE_LIMIT;
|
|
34005
|
+
for (const line of jsonl.split("\n")) {
|
|
34006
|
+
const classified = classifyTranscriptLine(line, startMs, endMs, now);
|
|
34007
|
+
if (classified)
|
|
34008
|
+
newest = pickNewerClassification(newest, classified);
|
|
34009
|
+
}
|
|
34010
|
+
return newest;
|
|
34011
|
+
}
|
|
34012
|
+
|
|
34013
|
+
// ../core/dist/claude-code-usage/transcript-location.js
|
|
34014
|
+
function encodeClaudeProjectPath(projectDir) {
|
|
34015
|
+
return "-" + projectDir.replace(/^\//, "").replace(/[/.]/g, "-");
|
|
34016
|
+
}
|
|
33782
34017
|
|
|
33783
34018
|
// ../core/dist/account-enforcement/marker.js
|
|
33784
34019
|
var ACCOUNT_ENFORCEMENT_MARKER_FILENAME = "account-enforcement.json";
|
|
@@ -36309,11 +36544,102 @@ function emitToolCallMarkupRedactionTelemetry(channel) {
|
|
|
36309
36544
|
}
|
|
36310
36545
|
}
|
|
36311
36546
|
|
|
36547
|
+
// src/rate-limit-watch.ts
|
|
36548
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync } from "fs";
|
|
36549
|
+
import { homedir as homedir5 } from "os";
|
|
36550
|
+
import { join as join7 } from "path";
|
|
36551
|
+
var DEFAULT_WATCH_MS = 5e3;
|
|
36552
|
+
var DEFAULT_POLL_MS = 400;
|
|
36553
|
+
function agentTranscriptDir(opts) {
|
|
36554
|
+
const cwd = opts?.cwd ?? process.cwd();
|
|
36555
|
+
const home = opts?.home ?? homedir5();
|
|
36556
|
+
return join7(home, ".claude", "projects", encodeClaudeProjectPath(cwd));
|
|
36557
|
+
}
|
|
36558
|
+
function classifyTranscriptSince(opts) {
|
|
36559
|
+
const dir = opts.transcriptDir ?? agentTranscriptDir({ cwd: opts.cwd, home: opts.home });
|
|
36560
|
+
let entries;
|
|
36561
|
+
try {
|
|
36562
|
+
entries = readdirSync2(dir);
|
|
36563
|
+
} catch {
|
|
36564
|
+
return UNKNOWN_RATE_LIMIT;
|
|
36565
|
+
}
|
|
36566
|
+
let newest = UNKNOWN_RATE_LIMIT;
|
|
36567
|
+
for (const name of entries) {
|
|
36568
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
36569
|
+
const path = join7(dir, name);
|
|
36570
|
+
try {
|
|
36571
|
+
const st = statSync(path);
|
|
36572
|
+
if (!st.isFile() || st.mtimeMs < opts.sinceMs) continue;
|
|
36573
|
+
} catch {
|
|
36574
|
+
continue;
|
|
36575
|
+
}
|
|
36576
|
+
let content;
|
|
36577
|
+
try {
|
|
36578
|
+
content = readFileSync6(path, "utf-8");
|
|
36579
|
+
} catch {
|
|
36580
|
+
continue;
|
|
36581
|
+
}
|
|
36582
|
+
newest = pickNewerClassification(
|
|
36583
|
+
newest,
|
|
36584
|
+
classifyTranscriptRateLimit(content, opts.sinceMs, opts.nowMs, new Date(opts.nowMs))
|
|
36585
|
+
);
|
|
36586
|
+
}
|
|
36587
|
+
return newest;
|
|
36588
|
+
}
|
|
36589
|
+
var sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
36590
|
+
async function watchForRateLimitRefusal(opts) {
|
|
36591
|
+
const now = opts.now ?? (() => Date.now());
|
|
36592
|
+
const wait = opts.wait ?? sleep;
|
|
36593
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_WATCH_MS;
|
|
36594
|
+
const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
|
|
36595
|
+
const deadline = now() + timeoutMs;
|
|
36596
|
+
for (; ; ) {
|
|
36597
|
+
let result;
|
|
36598
|
+
try {
|
|
36599
|
+
result = classifyTranscriptSince({
|
|
36600
|
+
sinceMs: opts.sinceMs,
|
|
36601
|
+
nowMs: now(),
|
|
36602
|
+
transcriptDir: opts.transcriptDir,
|
|
36603
|
+
cwd: opts.cwd,
|
|
36604
|
+
home: opts.home
|
|
36605
|
+
});
|
|
36606
|
+
} catch {
|
|
36607
|
+
return null;
|
|
36608
|
+
}
|
|
36609
|
+
if (result.verdict === "capped") return result;
|
|
36610
|
+
if (result.verdict === "serving") return null;
|
|
36611
|
+
if (now() >= deadline) return null;
|
|
36612
|
+
await wait(pollMs);
|
|
36613
|
+
}
|
|
36614
|
+
}
|
|
36615
|
+
|
|
36616
|
+
// src/usage-limit-reactive-decision.ts
|
|
36617
|
+
import { createHash } from "crypto";
|
|
36618
|
+
function shouldReadPredictiveMarker(mode) {
|
|
36619
|
+
return mode !== "enforce";
|
|
36620
|
+
}
|
|
36621
|
+
function armedWatchMode(opts) {
|
|
36622
|
+
if (opts.mode === "off") return null;
|
|
36623
|
+
if (opts.isBot || !opts.replyOwed) return null;
|
|
36624
|
+
return opts.mode;
|
|
36625
|
+
}
|
|
36626
|
+
function decideRefusalAction(opts) {
|
|
36627
|
+
const { refusal } = opts;
|
|
36628
|
+
if (!refusal || refusal.verdict !== "capped") return "none";
|
|
36629
|
+
if (!refusal.resetsAt) return "missing-reset";
|
|
36630
|
+
return opts.mode === "shadow" ? "shadow-log" : "notify";
|
|
36631
|
+
}
|
|
36632
|
+
function describeUnparsedRefusal(text) {
|
|
36633
|
+
if (!text) return "refusal=absent";
|
|
36634
|
+
const hash = createHash("sha256").update(text).digest("hex").slice(0, 12);
|
|
36635
|
+
return `refusal_hash=${hash} refusal_len=${text.length}`;
|
|
36636
|
+
}
|
|
36637
|
+
|
|
36312
36638
|
// src/reply-intent-runtime.ts
|
|
36313
36639
|
import { execFile as execFile2 } from "child_process";
|
|
36314
36640
|
import { existsSync as existsSync3, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
36315
|
-
import { homedir as
|
|
36316
|
-
import { join as
|
|
36641
|
+
import { homedir as homedir6 } from "os";
|
|
36642
|
+
import { join as join8 } from "path";
|
|
36317
36643
|
var DEFAULT_CLAUDE_EVAL_MODEL = "claude-haiku-4-5-20251001";
|
|
36318
36644
|
var DEFAULT_ANTHROPIC_MESSAGES_URL = "https://api.anthropic.com/v1/messages";
|
|
36319
36645
|
var ANTHROPIC_API_VERSION = "2023-06-01";
|
|
@@ -36412,12 +36738,12 @@ async function runAnthropicMessages(prompt, opts) {
|
|
|
36412
36738
|
var emptyMcpConfigPath = null;
|
|
36413
36739
|
function ensureEmptyMcpConfig() {
|
|
36414
36740
|
if (emptyMcpConfigPath && existsSync3(emptyMcpConfigPath)) return emptyMcpConfigPath;
|
|
36415
|
-
const dir =
|
|
36741
|
+
const dir = join8(homedir6(), ".augmented");
|
|
36416
36742
|
try {
|
|
36417
36743
|
mkdirSync(dir, { recursive: true });
|
|
36418
36744
|
} catch {
|
|
36419
36745
|
}
|
|
36420
|
-
const p2 =
|
|
36746
|
+
const p2 = join8(dir, ".reply-intent-empty-mcp.json");
|
|
36421
36747
|
writeFileSync2(p2, JSON.stringify({ mcpServers: {} }));
|
|
36422
36748
|
emptyMcpConfigPath = p2;
|
|
36423
36749
|
return p2;
|
|
@@ -36442,7 +36768,7 @@ function runClaudeP(prompt, model) {
|
|
|
36442
36768
|
execFile2(
|
|
36443
36769
|
"claude",
|
|
36444
36770
|
args,
|
|
36445
|
-
{ cwd:
|
|
36771
|
+
{ cwd: homedir6(), timeout: CLASSIFY_TIMEOUT_MS, maxBuffer: 1 << 20 },
|
|
36446
36772
|
(err, stdout) => {
|
|
36447
36773
|
if (err) {
|
|
36448
36774
|
reject(err);
|
|
@@ -36564,8 +36890,8 @@ function emitTransientApiErrorTelemetry(channel, match, original) {
|
|
|
36564
36890
|
}
|
|
36565
36891
|
|
|
36566
36892
|
// src/slack-pending-inbound-cleanup.ts
|
|
36567
|
-
import { existsSync as existsSync4, readdirSync as
|
|
36568
|
-
import { join as
|
|
36893
|
+
import { existsSync as existsSync4, readdirSync as readdirSync3, statSync as statSync2, unlinkSync } from "fs";
|
|
36894
|
+
import { join as join9 } from "path";
|
|
36569
36895
|
function sanitizeMarkerSegment(value) {
|
|
36570
36896
|
return value.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
36571
36897
|
}
|
|
@@ -36579,9 +36905,9 @@ function applyToMatchingMarkers(dir, prefix, suffix, op) {
|
|
|
36579
36905
|
if (!dir) return 0;
|
|
36580
36906
|
let applied = 0;
|
|
36581
36907
|
try {
|
|
36582
|
-
for (const f of
|
|
36908
|
+
for (const f of readdirSync3(dir)) {
|
|
36583
36909
|
if (!f.startsWith(prefix) || !f.endsWith(suffix)) continue;
|
|
36584
|
-
op(
|
|
36910
|
+
op(join9(dir, f));
|
|
36585
36911
|
applied += 1;
|
|
36586
36912
|
}
|
|
36587
36913
|
} catch {
|
|
@@ -36610,11 +36936,11 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
|
|
|
36610
36936
|
if (!dir) return null;
|
|
36611
36937
|
const channelPrefix = `${sanitizeMarkerSegment(channel)}__`;
|
|
36612
36938
|
try {
|
|
36613
|
-
const entries =
|
|
36614
|
-
const full =
|
|
36939
|
+
const entries = readdirSync3(dir).filter((f) => f.startsWith(channelPrefix) && f.endsWith(".json")).map((f) => {
|
|
36940
|
+
const full = join9(dir, f);
|
|
36615
36941
|
let mtime = 0;
|
|
36616
36942
|
try {
|
|
36617
|
-
mtime =
|
|
36943
|
+
mtime = statSync2(full).mtimeMs;
|
|
36618
36944
|
} catch {
|
|
36619
36945
|
}
|
|
36620
36946
|
return { name: f, full, mtime };
|
|
@@ -36630,12 +36956,12 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
|
|
|
36630
36956
|
|
|
36631
36957
|
// src/recovery-ledger.ts
|
|
36632
36958
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
36633
|
-
import { join as
|
|
36959
|
+
import { join as join10 } from "path";
|
|
36634
36960
|
function recoveryLedgerEntryExists(ledgerDir, markerName, exists = (p2) => existsSync5(p2)) {
|
|
36635
36961
|
if (!ledgerDir || !markerName) return false;
|
|
36636
36962
|
if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return false;
|
|
36637
36963
|
try {
|
|
36638
|
-
return exists(
|
|
36964
|
+
return exists(join10(ledgerDir, markerName));
|
|
36639
36965
|
} catch {
|
|
36640
36966
|
return false;
|
|
36641
36967
|
}
|
|
@@ -36646,7 +36972,7 @@ function removeRecoveryLedgerEntry(ledgerDir, markerName, unlink = (p2) => {
|
|
|
36646
36972
|
if (!ledgerDir || !markerName) return;
|
|
36647
36973
|
if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
|
|
36648
36974
|
try {
|
|
36649
|
-
unlink(
|
|
36975
|
+
unlink(join10(ledgerDir, markerName));
|
|
36650
36976
|
} catch {
|
|
36651
36977
|
}
|
|
36652
36978
|
}
|
|
@@ -36882,8 +37208,36 @@ function applyHotThreadGuard(input) {
|
|
|
36882
37208
|
return { threadTs: void 0, guard: "root_no_hot_thread" };
|
|
36883
37209
|
}
|
|
36884
37210
|
|
|
37211
|
+
// src/slack-hot-thread-telemetry.ts
|
|
37212
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
|
|
37213
|
+
import { join as join11 } from "path";
|
|
37214
|
+
var HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX = "-hot-thread-classifications.json";
|
|
37215
|
+
function hotThreadKey(mode, outcome, proactive) {
|
|
37216
|
+
return `${mode}|${outcome}|${proactive ? "true" : "false"}`;
|
|
37217
|
+
}
|
|
37218
|
+
function recordHotThreadClassification(agentDir, channel, classification) {
|
|
37219
|
+
if (!agentDir || !channel) return;
|
|
37220
|
+
const path = join11(agentDir, `${channel}${HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
37221
|
+
let counts = {};
|
|
37222
|
+
try {
|
|
37223
|
+
const parsed = JSON.parse(readFileSync7(path, "utf-8"));
|
|
37224
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
37225
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
37226
|
+
if (typeof v === "number" && Number.isInteger(v) && v >= 0) counts[k] = v;
|
|
37227
|
+
}
|
|
37228
|
+
}
|
|
37229
|
+
} catch {
|
|
37230
|
+
}
|
|
37231
|
+
const key2 = hotThreadKey(classification.mode, classification.outcome, classification.proactive);
|
|
37232
|
+
counts[key2] = (counts[key2] ?? 0) + 1;
|
|
37233
|
+
try {
|
|
37234
|
+
writeFileSync3(path, JSON.stringify(counts), { mode: 384 });
|
|
37235
|
+
} catch {
|
|
37236
|
+
}
|
|
37237
|
+
}
|
|
37238
|
+
|
|
36885
37239
|
// src/restart-confirm.ts
|
|
36886
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as
|
|
37240
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync8, renameSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
36887
37241
|
import { dirname } from "path";
|
|
36888
37242
|
import { randomUUID } from "crypto";
|
|
36889
37243
|
var RESTART_CONFIRM_MAX_AGE_MS = 10 * 60 * 1e3;
|
|
@@ -36903,13 +37257,13 @@ function writeRestartConfirmMarker(filePath, marker) {
|
|
|
36903
37257
|
const dir = dirname(filePath);
|
|
36904
37258
|
if (!existsSync6(dir)) mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
36905
37259
|
const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
36906
|
-
|
|
37260
|
+
writeFileSync4(tmpPath, JSON.stringify(marker) + "\n", { encoding: "utf8", mode: 384 });
|
|
36907
37261
|
renameSync(tmpPath, filePath);
|
|
36908
37262
|
}
|
|
36909
37263
|
function readRestartConfirmMarker(filePath) {
|
|
36910
37264
|
try {
|
|
36911
37265
|
if (!existsSync6(filePath)) return null;
|
|
36912
|
-
const parsed = JSON.parse(
|
|
37266
|
+
const parsed = JSON.parse(readFileSync8(filePath, "utf8"));
|
|
36913
37267
|
if (!parsed || typeof parsed !== "object") return null;
|
|
36914
37268
|
return parsed;
|
|
36915
37269
|
} catch {
|
|
@@ -37054,21 +37408,21 @@ import {
|
|
|
37054
37408
|
ftruncateSync,
|
|
37055
37409
|
mkdirSync as mkdirSync9,
|
|
37056
37410
|
openSync,
|
|
37057
|
-
readFileSync as
|
|
37058
|
-
readdirSync as
|
|
37411
|
+
readFileSync as readFileSync20,
|
|
37412
|
+
readdirSync as readdirSync6,
|
|
37059
37413
|
renameSync as renameSync5,
|
|
37060
|
-
statSync as
|
|
37414
|
+
statSync as statSync4,
|
|
37061
37415
|
unlinkSync as unlinkSync7,
|
|
37062
37416
|
watch,
|
|
37063
|
-
writeFileSync as
|
|
37417
|
+
writeFileSync as writeFileSync14,
|
|
37064
37418
|
writeSync
|
|
37065
37419
|
} from "fs";
|
|
37066
|
-
import { basename, join as
|
|
37067
|
-
import { homedir as
|
|
37068
|
-
import { createHash as
|
|
37420
|
+
import { basename, join as join20, resolve as resolve2 } from "path";
|
|
37421
|
+
import { homedir as homedir7 } from "os";
|
|
37422
|
+
import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
|
|
37069
37423
|
|
|
37070
37424
|
// src/slack-thread-store.ts
|
|
37071
|
-
import { mkdirSync as mkdirSync3, readFileSync as
|
|
37425
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
37072
37426
|
import { dirname as dirname2 } from "path";
|
|
37073
37427
|
function isParticipatingThread(entry) {
|
|
37074
37428
|
if (!entry) return false;
|
|
@@ -37083,7 +37437,7 @@ function loadThreadStore(filePath, opts = {}) {
|
|
|
37083
37437
|
const ttlMs = ttlDays * 24 * 60 * 60 * 1e3;
|
|
37084
37438
|
let raw;
|
|
37085
37439
|
try {
|
|
37086
|
-
raw =
|
|
37440
|
+
raw = readFileSync9(filePath, "utf-8");
|
|
37087
37441
|
} catch {
|
|
37088
37442
|
return { threads: /* @__PURE__ */ new Map(), pruned: 0 };
|
|
37089
37443
|
}
|
|
@@ -37132,7 +37486,7 @@ function createThreadPersister(opts) {
|
|
|
37132
37486
|
const writeNow = (snap) => {
|
|
37133
37487
|
try {
|
|
37134
37488
|
mkdirSync3(dirname2(opts.filePath), { recursive: true });
|
|
37135
|
-
|
|
37489
|
+
writeFileSync5(opts.filePath, serializeThreadStore(snap), "utf-8");
|
|
37136
37490
|
lastWriteAt = Date.now();
|
|
37137
37491
|
} catch (err) {
|
|
37138
37492
|
opts.onError?.(
|
|
@@ -37184,7 +37538,7 @@ function isThreadEntry(value) {
|
|
|
37184
37538
|
}
|
|
37185
37539
|
|
|
37186
37540
|
// src/dm-restart-notice.ts
|
|
37187
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
37541
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
37188
37542
|
import { dirname as dirname3 } from "path";
|
|
37189
37543
|
var RECENT_DM_VERSION = 1;
|
|
37190
37544
|
var DEFAULT_RECENT_DM_TTL_MS = 30 * 60 * 1e3;
|
|
@@ -37208,7 +37562,7 @@ function loadRecentDms(filePath, opts = {}) {
|
|
|
37208
37562
|
const ttlMs = opts.ttlMs ?? DEFAULT_RECENT_DM_TTL_MS;
|
|
37209
37563
|
let raw;
|
|
37210
37564
|
try {
|
|
37211
|
-
raw =
|
|
37565
|
+
raw = readFileSync10(filePath, "utf-8");
|
|
37212
37566
|
} catch (err) {
|
|
37213
37567
|
const code = err.code;
|
|
37214
37568
|
if (code !== "ENOENT") {
|
|
@@ -37248,7 +37602,7 @@ function createRecentDmPersister(opts) {
|
|
|
37248
37602
|
const writeNow = (snap) => {
|
|
37249
37603
|
try {
|
|
37250
37604
|
mkdirSync4(dirname3(opts.filePath), { recursive: true });
|
|
37251
|
-
|
|
37605
|
+
writeFileSync6(opts.filePath, serializeRecentDms(snap), "utf-8");
|
|
37252
37606
|
lastWriteAt = Date.now();
|
|
37253
37607
|
} catch (err) {
|
|
37254
37608
|
opts.onError?.(`dm-restart-notice: failed to persist recent-DMs: ${err.message}`);
|
|
@@ -37293,7 +37647,7 @@ var CHANNEL_ADD_RESTART_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
|
37293
37647
|
function readChannelAddRestartMarker(filePath) {
|
|
37294
37648
|
let raw;
|
|
37295
37649
|
try {
|
|
37296
|
-
raw =
|
|
37650
|
+
raw = readFileSync10(filePath, "utf-8");
|
|
37297
37651
|
} catch {
|
|
37298
37652
|
return null;
|
|
37299
37653
|
}
|
|
@@ -37351,13 +37705,13 @@ async function runOrRetry(fn, opts) {
|
|
|
37351
37705
|
}
|
|
37352
37706
|
|
|
37353
37707
|
// src/turn-initiator-marker.ts
|
|
37354
|
-
import { writeFileSync as
|
|
37355
|
-
import { dirname as dirname4, join as
|
|
37708
|
+
import { writeFileSync as writeFileSync7, readFileSync as readFileSync11, mkdirSync as mkdirSync5, renameSync as renameSync2 } from "fs";
|
|
37709
|
+
import { dirname as dirname4, join as join12 } from "path";
|
|
37356
37710
|
var TURN_INITIATOR_MAX_AGE_MS = 5 * 60 * 1e3;
|
|
37357
37711
|
var TURN_INITIATOR_LEDGER_MAX_ENTRIES = 20;
|
|
37358
37712
|
var TURN_INITIATOR_LEDGER_FILENAME = ".turn-initiator-ledger.json";
|
|
37359
37713
|
function turnInitiatorLedgerPath(singleSlotFile) {
|
|
37360
|
-
return
|
|
37714
|
+
return join12(dirname4(singleSlotFile), TURN_INITIATOR_LEDGER_FILENAME);
|
|
37361
37715
|
}
|
|
37362
37716
|
function foldTurnInitiatorLedger(existing, marker, maxAgeMs = TURN_INITIATOR_MAX_AGE_MS, maxEntries = TURN_INITIATOR_LEDGER_MAX_ENTRIES) {
|
|
37363
37717
|
const now = marker.ts;
|
|
@@ -37382,13 +37736,13 @@ function updateTurnInitiatorLedger(singleSlotFile, marker) {
|
|
|
37382
37736
|
const ledgerFile = turnInitiatorLedgerPath(singleSlotFile);
|
|
37383
37737
|
let existing = null;
|
|
37384
37738
|
try {
|
|
37385
|
-
const parsed = JSON.parse(
|
|
37739
|
+
const parsed = JSON.parse(readFileSync11(ledgerFile, "utf8"));
|
|
37386
37740
|
if (parsed && parsed.v === 1 && Array.isArray(parsed.entries)) existing = parsed;
|
|
37387
37741
|
} catch {
|
|
37388
37742
|
}
|
|
37389
37743
|
const next = foldTurnInitiatorLedger(existing, marker);
|
|
37390
37744
|
const tmp = `${ledgerFile}.tmp`;
|
|
37391
|
-
|
|
37745
|
+
writeFileSync7(tmp, JSON.stringify(next), "utf8");
|
|
37392
37746
|
renameSync2(tmp, ledgerFile);
|
|
37393
37747
|
}
|
|
37394
37748
|
function writeTurnInitiatorMarker(input) {
|
|
@@ -37398,7 +37752,7 @@ function writeTurnInitiatorMarker(input) {
|
|
|
37398
37752
|
mkdirSync5(dirname4(file), { recursive: true });
|
|
37399
37753
|
const marker = { ...input, ts: Date.now() };
|
|
37400
37754
|
const tmp = `${file}.tmp`;
|
|
37401
|
-
|
|
37755
|
+
writeFileSync7(tmp, JSON.stringify(marker), "utf8");
|
|
37402
37756
|
renameSync2(tmp, file);
|
|
37403
37757
|
try {
|
|
37404
37758
|
updateTurnInitiatorLedger(file, marker);
|
|
@@ -37409,7 +37763,7 @@ function writeTurnInitiatorMarker(input) {
|
|
|
37409
37763
|
}
|
|
37410
37764
|
|
|
37411
37765
|
// src/slack-bot-photo.ts
|
|
37412
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as
|
|
37766
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "fs";
|
|
37413
37767
|
import { dirname as dirname5 } from "path";
|
|
37414
37768
|
async function applyBotPhoto(opts) {
|
|
37415
37769
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
@@ -37419,7 +37773,7 @@ async function applyBotPhoto(opts) {
|
|
|
37419
37773
|
const { token, avatarUrl, markerPath } = opts;
|
|
37420
37774
|
if (markerPath && existsSync7(markerPath)) {
|
|
37421
37775
|
try {
|
|
37422
|
-
if (
|
|
37776
|
+
if (readFileSync12(markerPath, "utf-8").trim() === avatarUrl) {
|
|
37423
37777
|
return { status: "skipped-unchanged" };
|
|
37424
37778
|
}
|
|
37425
37779
|
} catch {
|
|
@@ -37461,7 +37815,7 @@ async function applyBotPhoto(opts) {
|
|
|
37461
37815
|
if (markerPath) {
|
|
37462
37816
|
try {
|
|
37463
37817
|
mkdirSync6(dirname5(markerPath), { recursive: true, mode: 448 });
|
|
37464
|
-
|
|
37818
|
+
writeFileSync8(markerPath, avatarUrl, { mode: 384 });
|
|
37465
37819
|
} catch {
|
|
37466
37820
|
}
|
|
37467
37821
|
}
|
|
@@ -37544,8 +37898,8 @@ function conversationalLaneMeta(expectsReply = true) {
|
|
|
37544
37898
|
}
|
|
37545
37899
|
|
|
37546
37900
|
// src/inbound-lane-telemetry.ts
|
|
37547
|
-
import { readFileSync as
|
|
37548
|
-
import { join as
|
|
37901
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
|
|
37902
|
+
import { join as join13 } from "path";
|
|
37549
37903
|
var LANE_CLASSIFICATION_COUNTER_SUFFIX = "-lane-classifications.json";
|
|
37550
37904
|
var SUSPECTED_MISCLASSIFICATION_KEY = "suspected_misclassification";
|
|
37551
37905
|
var HUMAN_CHANNEL_SOURCES = /* @__PURE__ */ new Set([
|
|
@@ -37562,10 +37916,10 @@ function isSuspectedMisclassification(lane, source) {
|
|
|
37562
37916
|
}
|
|
37563
37917
|
function recordLaneClassification(agentDir, channel, classification) {
|
|
37564
37918
|
if (!agentDir) return;
|
|
37565
|
-
const path =
|
|
37919
|
+
const path = join13(agentDir, `${channel}${LANE_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
37566
37920
|
let counts = {};
|
|
37567
37921
|
try {
|
|
37568
|
-
const parsed = JSON.parse(
|
|
37922
|
+
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
37569
37923
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
37570
37924
|
} catch {
|
|
37571
37925
|
}
|
|
@@ -37575,14 +37929,14 @@ function recordLaneClassification(agentDir, channel, classification) {
|
|
|
37575
37929
|
counts[SUSPECTED_MISCLASSIFICATION_KEY] = (counts[SUSPECTED_MISCLASSIFICATION_KEY] ?? 0) + 1;
|
|
37576
37930
|
}
|
|
37577
37931
|
try {
|
|
37578
|
-
|
|
37932
|
+
writeFileSync9(path, JSON.stringify(counts), { mode: 384 });
|
|
37579
37933
|
} catch {
|
|
37580
37934
|
}
|
|
37581
37935
|
}
|
|
37582
37936
|
|
|
37583
37937
|
// src/slack-inbound-registry.ts
|
|
37584
|
-
import { readdirSync as
|
|
37585
|
-
import { join as
|
|
37938
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync14 } from "fs";
|
|
37939
|
+
import { join as join14 } from "path";
|
|
37586
37940
|
var DEFAULT_MAX_ENTRIES = 500;
|
|
37587
37941
|
var DEFAULT_CLEARED_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
37588
37942
|
function entryKey(channel, messageTs) {
|
|
@@ -37694,7 +38048,7 @@ function createInboundRegistry(opts = {}) {
|
|
|
37694
38048
|
function seedFromMarkerDir(dir) {
|
|
37695
38049
|
let names;
|
|
37696
38050
|
try {
|
|
37697
|
-
names =
|
|
38051
|
+
names = readdirSync4(dir);
|
|
37698
38052
|
} catch {
|
|
37699
38053
|
return;
|
|
37700
38054
|
}
|
|
@@ -37703,7 +38057,7 @@ function createInboundRegistry(opts = {}) {
|
|
|
37703
38057
|
if (name.includes(".retry-") || name.includes(".poison")) continue;
|
|
37704
38058
|
let marker;
|
|
37705
38059
|
try {
|
|
37706
|
-
marker = JSON.parse(
|
|
38060
|
+
marker = JSON.parse(readFileSync14(join14(dir, name), "utf-8"));
|
|
37707
38061
|
} catch {
|
|
37708
38062
|
continue;
|
|
37709
38063
|
}
|
|
@@ -37740,25 +38094,25 @@ function createInboundRegistry(opts = {}) {
|
|
|
37740
38094
|
}
|
|
37741
38095
|
|
|
37742
38096
|
// src/slack-inbound-id.ts
|
|
37743
|
-
import { createHash } from "crypto";
|
|
38097
|
+
import { createHash as createHash2 } from "crypto";
|
|
37744
38098
|
var INBOUND_ID_HEX_LEN = 12;
|
|
37745
38099
|
function slackInboundId(channel, threadTs, messageTs) {
|
|
37746
|
-
const digest =
|
|
38100
|
+
const digest = createHash2("sha256").update(`${channel}|${threadTs}|${messageTs}`).digest("hex").slice(0, INBOUND_ID_HEX_LEN);
|
|
37747
38101
|
return `ib_${digest}`;
|
|
37748
38102
|
}
|
|
37749
38103
|
|
|
37750
38104
|
// src/inbound-delivery-ledger.ts
|
|
37751
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as
|
|
37752
|
-
import { join as
|
|
38105
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as readdirSync5, readFileSync as readFileSync15, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
38106
|
+
import { join as join15 } from "path";
|
|
37753
38107
|
function safeInboundId(inboundId) {
|
|
37754
38108
|
return inboundId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
37755
38109
|
}
|
|
37756
38110
|
var defaultDeps = {
|
|
37757
38111
|
mkdir: (dir) => mkdirSync7(dir, { recursive: true }),
|
|
37758
|
-
writeFile: (path, data) =>
|
|
38112
|
+
writeFile: (path, data) => writeFileSync10(path, data, "utf8"),
|
|
37759
38113
|
rename: (from, to) => renameSync3(from, to),
|
|
37760
|
-
readdir: (dir) =>
|
|
37761
|
-
readFile: (path) =>
|
|
38114
|
+
readdir: (dir) => readdirSync5(dir),
|
|
38115
|
+
readFile: (path) => readFileSync15(path, "utf8"),
|
|
37762
38116
|
exists: (path) => existsSync8(path)
|
|
37763
38117
|
};
|
|
37764
38118
|
function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
|
|
@@ -37767,7 +38121,7 @@ function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
|
|
|
37767
38121
|
if (!safe || safe.includes("/") || safe.includes("\\") || safe.includes("..")) return;
|
|
37768
38122
|
try {
|
|
37769
38123
|
deps.mkdir(dir);
|
|
37770
|
-
const final =
|
|
38124
|
+
const final = join15(dir, `${safe}.json`);
|
|
37771
38125
|
const tmp = `${final}.tmp`;
|
|
37772
38126
|
deps.writeFile(tmp, JSON.stringify(record2));
|
|
37773
38127
|
deps.rename(tmp, final);
|
|
@@ -37923,8 +38277,8 @@ function describeChannelRedirect(input) {
|
|
|
37923
38277
|
}
|
|
37924
38278
|
|
|
37925
38279
|
// src/slack-reply-binding-telemetry.ts
|
|
37926
|
-
import { readFileSync as
|
|
37927
|
-
import { join as
|
|
38280
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
|
|
38281
|
+
import { join as join16 } from "path";
|
|
37928
38282
|
var REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX = "-reply-binding-classifications.json";
|
|
37929
38283
|
var UNKNOWN_INBOUND_ID_KEY = "unknown_inbound_id";
|
|
37930
38284
|
var CHANNEL_MISTARGET_CORRECTED_KEY = "channel_mistarget_corrected";
|
|
@@ -37939,10 +38293,10 @@ function slackReplyBindingMode() {
|
|
|
37939
38293
|
}
|
|
37940
38294
|
function recordReplyBindingClassification(agentDir, channel, input) {
|
|
37941
38295
|
if (!agentDir) return;
|
|
37942
|
-
const path =
|
|
38296
|
+
const path = join16(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
37943
38297
|
let counts = {};
|
|
37944
38298
|
try {
|
|
37945
|
-
const parsed = JSON.parse(
|
|
38299
|
+
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
37946
38300
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
37947
38301
|
} catch {
|
|
37948
38302
|
}
|
|
@@ -37951,32 +38305,32 @@ function recordReplyBindingClassification(agentDir, channel, input) {
|
|
|
37951
38305
|
counts[UNKNOWN_INBOUND_ID_KEY] = (counts[UNKNOWN_INBOUND_ID_KEY] ?? 0) + 1;
|
|
37952
38306
|
}
|
|
37953
38307
|
try {
|
|
37954
|
-
|
|
38308
|
+
writeFileSync11(path, JSON.stringify(counts), { mode: 384 });
|
|
37955
38309
|
} catch {
|
|
37956
38310
|
}
|
|
37957
38311
|
}
|
|
37958
38312
|
function recordScheduledChannelOverride(agentDir, channel, input) {
|
|
37959
38313
|
if (!agentDir) return;
|
|
37960
|
-
const path =
|
|
38314
|
+
const path = join16(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
37961
38315
|
let counts = {};
|
|
37962
38316
|
try {
|
|
37963
|
-
const parsed = JSON.parse(
|
|
38317
|
+
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
37964
38318
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
37965
38319
|
} catch {
|
|
37966
38320
|
}
|
|
37967
38321
|
const key2 = input.enforced ? SCHEDULED_CHANNEL_OVERRIDE_BLOCKED_KEY : SCHEDULED_CHANNEL_OVERRIDE_SHADOW_KEY;
|
|
37968
38322
|
counts[key2] = (counts[key2] ?? 0) + 1;
|
|
37969
38323
|
try {
|
|
37970
|
-
|
|
38324
|
+
writeFileSync11(path, JSON.stringify(counts), { mode: 384 });
|
|
37971
38325
|
} catch {
|
|
37972
38326
|
}
|
|
37973
38327
|
}
|
|
37974
38328
|
function recordChannelMistarget(agentDir, channel, input) {
|
|
37975
38329
|
if (!agentDir) return;
|
|
37976
|
-
const path =
|
|
38330
|
+
const path = join16(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
37977
38331
|
let counts = {};
|
|
37978
38332
|
try {
|
|
37979
|
-
const parsed = JSON.parse(
|
|
38333
|
+
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
37980
38334
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
37981
38335
|
} catch {
|
|
37982
38336
|
}
|
|
@@ -37985,14 +38339,14 @@ function recordChannelMistarget(agentDir, channel, input) {
|
|
|
37985
38339
|
counts[DM_CHANNEL_MISTARGET_KEY] = (counts[DM_CHANNEL_MISTARGET_KEY] ?? 0) + 1;
|
|
37986
38340
|
}
|
|
37987
38341
|
try {
|
|
37988
|
-
|
|
38342
|
+
writeFileSync11(path, JSON.stringify(counts), { mode: 384 });
|
|
37989
38343
|
} catch {
|
|
37990
38344
|
}
|
|
37991
38345
|
}
|
|
37992
38346
|
|
|
37993
38347
|
// src/slack-reply-target-telemetry.ts
|
|
37994
|
-
import { readFileSync as
|
|
37995
|
-
import { join as
|
|
38348
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync12 } from "fs";
|
|
38349
|
+
import { join as join17 } from "path";
|
|
37996
38350
|
var REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX = "-reply-target-classifications.json";
|
|
37997
38351
|
function pendingThreadsBucket(n) {
|
|
37998
38352
|
if (n <= 0) return "0";
|
|
@@ -38025,10 +38379,10 @@ function classifyReplyTarget(input) {
|
|
|
38025
38379
|
}
|
|
38026
38380
|
function recordReplyTargetClassification(agentDir, channel, classification) {
|
|
38027
38381
|
if (!agentDir) return;
|
|
38028
|
-
const path =
|
|
38382
|
+
const path = join17(agentDir, `${channel}${REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
38029
38383
|
let counts = {};
|
|
38030
38384
|
try {
|
|
38031
|
-
const parsed = JSON.parse(
|
|
38385
|
+
const parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
38032
38386
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
38033
38387
|
} catch {
|
|
38034
38388
|
}
|
|
@@ -38038,14 +38392,14 @@ function recordReplyTargetClassification(agentDir, channel, classification) {
|
|
|
38038
38392
|
);
|
|
38039
38393
|
counts[key2] = (counts[key2] ?? 0) + 1;
|
|
38040
38394
|
try {
|
|
38041
|
-
|
|
38395
|
+
writeFileSync12(path, JSON.stringify(counts), { mode: 384 });
|
|
38042
38396
|
} catch {
|
|
38043
38397
|
}
|
|
38044
38398
|
}
|
|
38045
38399
|
|
|
38046
38400
|
// src/scheduled-turn-marker.ts
|
|
38047
|
-
import { readFileSync as
|
|
38048
|
-
import { join as
|
|
38401
|
+
import { readFileSync as readFileSync18, unlinkSync as unlinkSync5 } from "fs";
|
|
38402
|
+
import { join as join18 } from "path";
|
|
38049
38403
|
var SCHEDULED_TURN_MARKER_FILENAME2 = ".current-scheduled-turn.json";
|
|
38050
38404
|
var SCHEDULED_TURN_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
38051
38405
|
function validateScheduledTurnMarker(raw, now, maxAgeMs = SCHEDULED_TURN_MAX_AGE_MS) {
|
|
@@ -38083,7 +38437,7 @@ function readScheduledTurnMarker(agentDir, now = Date.now()) {
|
|
|
38083
38437
|
if (!agentDir) return null;
|
|
38084
38438
|
try {
|
|
38085
38439
|
const raw = JSON.parse(
|
|
38086
|
-
|
|
38440
|
+
readFileSync18(join18(agentDir, SCHEDULED_TURN_MARKER_FILENAME2), "utf8")
|
|
38087
38441
|
);
|
|
38088
38442
|
return validateScheduledTurnMarker(raw, now);
|
|
38089
38443
|
} catch {
|
|
@@ -38093,7 +38447,7 @@ function readScheduledTurnMarker(agentDir, now = Date.now()) {
|
|
|
38093
38447
|
function clearScheduledTurnMarker(agentDir) {
|
|
38094
38448
|
if (!agentDir) return;
|
|
38095
38449
|
try {
|
|
38096
|
-
unlinkSync5(
|
|
38450
|
+
unlinkSync5(join18(agentDir, SCHEDULED_TURN_MARKER_FILENAME2));
|
|
38097
38451
|
} catch {
|
|
38098
38452
|
}
|
|
38099
38453
|
}
|
|
@@ -38891,14 +39245,14 @@ async function actuateHostRestart(opts) {
|
|
|
38891
39245
|
import {
|
|
38892
39246
|
existsSync as existsSync9,
|
|
38893
39247
|
mkdirSync as mkdirSync8,
|
|
38894
|
-
readFileSync as
|
|
39248
|
+
readFileSync as readFileSync19,
|
|
38895
39249
|
renameSync as renameSync4,
|
|
38896
|
-
statSync as
|
|
39250
|
+
statSync as statSync3,
|
|
38897
39251
|
unlinkSync as unlinkSync6,
|
|
38898
39252
|
utimesSync,
|
|
38899
|
-
writeFileSync as
|
|
39253
|
+
writeFileSync as writeFileSync13
|
|
38900
39254
|
} from "fs";
|
|
38901
|
-
import { join as
|
|
39255
|
+
import { join as join19 } from "path";
|
|
38902
39256
|
var STALE_LOCK_MS = 9e4;
|
|
38903
39257
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
38904
39258
|
function defaultIsPidAlive(pid) {
|
|
@@ -38921,7 +39275,7 @@ function acquireMcpSpawnLock(args) {
|
|
|
38921
39275
|
const nowMs = options.nowMs ?? (() => Date.now());
|
|
38922
39276
|
const lockMtimeMs = options.lockMtimeMs ?? defaultLockMtimeMs;
|
|
38923
39277
|
const staleMs = options.staleMs ?? STALE_LOCK_MS;
|
|
38924
|
-
const path =
|
|
39278
|
+
const path = join19(agentDir, basename2);
|
|
38925
39279
|
const existing = readLockHolder(path);
|
|
38926
39280
|
if (existing) {
|
|
38927
39281
|
if (existing.pid === selfPid) {
|
|
@@ -38938,7 +39292,7 @@ function acquireMcpSpawnLock(args) {
|
|
|
38938
39292
|
mkdirSync8(agentDir, { recursive: true, mode: 448 });
|
|
38939
39293
|
const tmpPath = `${path}.${selfPid}.tmp`;
|
|
38940
39294
|
const payload = { pid: selfPid, started_at: now() };
|
|
38941
|
-
|
|
39295
|
+
writeFileSync13(tmpPath, JSON.stringify(payload), { mode: 384 });
|
|
38942
39296
|
renameSync4(tmpPath, path);
|
|
38943
39297
|
return { kind: "acquired", path };
|
|
38944
39298
|
}
|
|
@@ -38980,7 +39334,7 @@ function startMcpSpawnLockHeartbeat(lockPath, opts = {}) {
|
|
|
38980
39334
|
}
|
|
38981
39335
|
function defaultLockMtimeMs(path) {
|
|
38982
39336
|
try {
|
|
38983
|
-
return
|
|
39337
|
+
return statSync3(path).mtimeMs;
|
|
38984
39338
|
} catch {
|
|
38985
39339
|
return null;
|
|
38986
39340
|
}
|
|
@@ -38988,7 +39342,7 @@ function defaultLockMtimeMs(path) {
|
|
|
38988
39342
|
function readLockHolder(path) {
|
|
38989
39343
|
if (!existsSync9(path)) return null;
|
|
38990
39344
|
try {
|
|
38991
|
-
const raw =
|
|
39345
|
+
const raw = readFileSync19(path, "utf8");
|
|
38992
39346
|
const parsed = JSON.parse(raw);
|
|
38993
39347
|
const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
|
|
38994
39348
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
@@ -39219,6 +39573,49 @@ async function maybeSendUsageLimitNotice(args) {
|
|
|
39219
39573
|
clearTimeout(timeoutId);
|
|
39220
39574
|
}
|
|
39221
39575
|
}
|
|
39576
|
+
function armSlackUsageLimitWatch(args) {
|
|
39577
|
+
void (async () => {
|
|
39578
|
+
try {
|
|
39579
|
+
const refusal = await watchForRateLimitRefusal({ sinceMs: args.sinceMs });
|
|
39580
|
+
const action = decideRefusalAction({ mode: args.mode, refusal });
|
|
39581
|
+
if (action === "none") return;
|
|
39582
|
+
if (action === "missing-reset") {
|
|
39583
|
+
process.stderr.write(
|
|
39584
|
+
`slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] mode=${args.mode} refusal detected for channel=${redactSlackId(args.channel)} but no reset time in it (${describeUnparsedRefusal(refusal?.text)}) - no notice
|
|
39585
|
+
`
|
|
39586
|
+
);
|
|
39587
|
+
return;
|
|
39588
|
+
}
|
|
39589
|
+
const resetsAt = refusal?.resetsAt;
|
|
39590
|
+
if (!resetsAt) return;
|
|
39591
|
+
if (action === "shadow-log") {
|
|
39592
|
+
process.stderr.write(
|
|
39593
|
+
`slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] mode=shadow WOULD notify channel=${redactSlackId(args.channel)} ts=${redactSlackId(args.messageTs)} resets=${resetsAt.toISOString()}
|
|
39594
|
+
`
|
|
39595
|
+
);
|
|
39596
|
+
return;
|
|
39597
|
+
}
|
|
39598
|
+
await maybeSendUsageLimitNotice({
|
|
39599
|
+
channel: args.channel,
|
|
39600
|
+
senderId: args.senderId,
|
|
39601
|
+
threadTs: args.threadTs,
|
|
39602
|
+
limitedUntil: resetsAt
|
|
39603
|
+
});
|
|
39604
|
+
if (args.channel && args.messageTs) {
|
|
39605
|
+
clearSlackPendingMarkerByMessageTs2(args.channel, args.messageTs);
|
|
39606
|
+
}
|
|
39607
|
+
process.stderr.write(
|
|
39608
|
+
`slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] reported refusal for channel=${redactSlackId(args.channel)} ts=${redactSlackId(args.messageTs)} resets=${resetsAt.toISOString()}
|
|
39609
|
+
`
|
|
39610
|
+
);
|
|
39611
|
+
} catch (err) {
|
|
39612
|
+
process.stderr.write(
|
|
39613
|
+
`slack-channel(${AGENT_CODE_NAME}): [usage-limit-reactive] watch failed for channel=${redactSlackId(args.channel)}: ${err.message}
|
|
39614
|
+
`
|
|
39615
|
+
);
|
|
39616
|
+
}
|
|
39617
|
+
})();
|
|
39618
|
+
}
|
|
39222
39619
|
var SLACK_ACCOUNT_MUTE_NOTICE_CACHE = /* @__PURE__ */ new Map();
|
|
39223
39620
|
async function maybeSendAccountMuteNotice(args) {
|
|
39224
39621
|
if (!BOT_TOKEN) return;
|
|
@@ -39394,18 +39791,18 @@ var SLACK_TEAM_PEER_USER_IDS = parseTeamPeerUserIdsEnv(
|
|
|
39394
39791
|
process.env.SLACK_TEAM_PEER_USER_IDS
|
|
39395
39792
|
);
|
|
39396
39793
|
var PEER_HINT_SEEN = /* @__PURE__ */ new Set();
|
|
39397
|
-
var SLACK_AGENT_DIR = AGENT_CODE_NAME ?
|
|
39398
|
-
var SLACK_MCP_CONFIG_PATH = SLACK_AGENT_DIR ?
|
|
39794
|
+
var SLACK_AGENT_DIR = AGENT_CODE_NAME ? join20(homedir7(), ".augmented", AGENT_CODE_NAME) : null;
|
|
39795
|
+
var SLACK_MCP_CONFIG_PATH = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "project", ".mcp.json") : null;
|
|
39399
39796
|
var liveAllowedUsersCache = null;
|
|
39400
39797
|
function readLiveAllowedUsers() {
|
|
39401
39798
|
if (!SLACK_MCP_CONFIG_PATH) return null;
|
|
39402
39799
|
try {
|
|
39403
|
-
const mtimeMs =
|
|
39800
|
+
const mtimeMs = statSync4(SLACK_MCP_CONFIG_PATH).mtimeMs;
|
|
39404
39801
|
if (liveAllowedUsersCache && liveAllowedUsersCache.mtimeMs === mtimeMs) {
|
|
39405
39802
|
return liveAllowedUsersCache.value;
|
|
39406
39803
|
}
|
|
39407
39804
|
const value = extractAllowedUsersFromMcpJson(
|
|
39408
|
-
|
|
39805
|
+
readFileSync20(SLACK_MCP_CONFIG_PATH, "utf-8")
|
|
39409
39806
|
);
|
|
39410
39807
|
if (value === null) return null;
|
|
39411
39808
|
liveAllowedUsersCache = { mtimeMs, value };
|
|
@@ -39421,12 +39818,12 @@ var livePingAllowedUsersCache = null;
|
|
|
39421
39818
|
function readLivePingAllowedUsers() {
|
|
39422
39819
|
if (!SLACK_MCP_CONFIG_PATH) return null;
|
|
39423
39820
|
try {
|
|
39424
|
-
const mtimeMs =
|
|
39821
|
+
const mtimeMs = statSync4(SLACK_MCP_CONFIG_PATH).mtimeMs;
|
|
39425
39822
|
if (livePingAllowedUsersCache && livePingAllowedUsersCache.mtimeMs === mtimeMs) {
|
|
39426
39823
|
return livePingAllowedUsersCache.value;
|
|
39427
39824
|
}
|
|
39428
39825
|
const value = extractPingAllowedUsersFromMcpJson(
|
|
39429
|
-
|
|
39826
|
+
readFileSync20(SLACK_MCP_CONFIG_PATH, "utf-8")
|
|
39430
39827
|
);
|
|
39431
39828
|
if (value === null) return null;
|
|
39432
39829
|
livePingAllowedUsersCache = { mtimeMs, value };
|
|
@@ -39438,20 +39835,20 @@ function readLivePingAllowedUsers() {
|
|
|
39438
39835
|
function getEffectivePingAllowedUsers() {
|
|
39439
39836
|
return readLivePingAllowedUsers() ?? PING_ALLOWED_USERS;
|
|
39440
39837
|
}
|
|
39441
|
-
var SLACK_PENDING_INBOUND_DIR = SLACK_AGENT_DIR ?
|
|
39442
|
-
var SLACK_RESTART_CONTEXT_DIR = SLACK_AGENT_DIR ?
|
|
39443
|
-
var SLACK_RECOVERY_OUTBOX_DIR = SLACK_AGENT_DIR ?
|
|
39444
|
-
var SLACK_RECOVERY_LEDGER_DIR = SLACK_AGENT_DIR ?
|
|
39445
|
-
var SLACK_DELIVERY_LEDGER_DIR = SLACK_AGENT_DIR ?
|
|
39838
|
+
var SLACK_PENDING_INBOUND_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-pending-inbound") : null;
|
|
39839
|
+
var SLACK_RESTART_CONTEXT_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-restart-context") : null;
|
|
39840
|
+
var SLACK_RECOVERY_OUTBOX_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-recovery-outbox") : null;
|
|
39841
|
+
var SLACK_RECOVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, ".agt-slack-recovery-ledger") : null;
|
|
39842
|
+
var SLACK_DELIVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, ".agt-inbound-delivery-ledger") : null;
|
|
39446
39843
|
var slackInboundRegistry = createInboundRegistry();
|
|
39447
|
-
var SLACK_RESTART_CONFIRM_FILE = SLACK_AGENT_DIR ?
|
|
39448
|
-
var SLACK_RECENT_DMS_FILE = SLACK_AGENT_DIR ?
|
|
39449
|
-
var SLACK_CHANNEL_ADD_RESTART_FILE = SLACK_AGENT_DIR ?
|
|
39844
|
+
var SLACK_RESTART_CONFIRM_FILE = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-restart-confirm.json") : null;
|
|
39845
|
+
var SLACK_RECENT_DMS_FILE = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-recent-dms.json") : null;
|
|
39846
|
+
var SLACK_CHANNEL_ADD_RESTART_FILE = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-channel-add-restart.json") : null;
|
|
39450
39847
|
var SLACK_MAX_RECOVERY_ATTEMPTS = 3;
|
|
39451
|
-
var SLACK_AVATAR_MARKER_PATH = SLACK_AGENT_DIR ?
|
|
39848
|
+
var SLACK_AVATAR_MARKER_PATH = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-avatar-applied") : null;
|
|
39452
39849
|
function redactSlackId(id) {
|
|
39453
39850
|
if (!id) return "<none>";
|
|
39454
|
-
return
|
|
39851
|
+
return createHash3("sha256").update(id).digest("hex").slice(0, 8);
|
|
39455
39852
|
}
|
|
39456
39853
|
function safeSlackMarkerName(channel, threadTs, messageTs) {
|
|
39457
39854
|
const safe = (s) => s.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
@@ -39459,7 +39856,7 @@ function safeSlackMarkerName(channel, threadTs, messageTs) {
|
|
|
39459
39856
|
}
|
|
39460
39857
|
function slackPendingInboundPath(channel, threadTs, messageTs) {
|
|
39461
39858
|
if (!SLACK_PENDING_INBOUND_DIR) return null;
|
|
39462
|
-
return
|
|
39859
|
+
return join20(SLACK_PENDING_INBOUND_DIR, safeSlackMarkerName(channel, threadTs, messageTs));
|
|
39463
39860
|
}
|
|
39464
39861
|
function writeSlackPendingInboundMarker(channel, threadTs, messageTs, undeliverable = false, discretionary = false, payload) {
|
|
39465
39862
|
const path = slackPendingInboundPath(channel, threadTs, messageTs);
|
|
@@ -39482,7 +39879,7 @@ function writeSlackPendingInboundMarker(channel, threadTs, messageTs, undelivera
|
|
|
39482
39879
|
};
|
|
39483
39880
|
try {
|
|
39484
39881
|
mkdirSync9(SLACK_PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
|
|
39485
|
-
|
|
39882
|
+
writeFileSync14(path, JSON.stringify(marker), { mode: 384 });
|
|
39486
39883
|
} catch (err) {
|
|
39487
39884
|
process.stderr.write(
|
|
39488
39885
|
`slack-channel(${AGENT_CODE_NAME}): pending-inbound marker write failed: ${err.message}
|
|
@@ -39510,7 +39907,7 @@ function rewriteSlackMarkerInPlace(path, marker) {
|
|
|
39510
39907
|
function markSlackMarkerSeenInPlace(fullPath) {
|
|
39511
39908
|
let marker;
|
|
39512
39909
|
try {
|
|
39513
|
-
marker = JSON.parse(
|
|
39910
|
+
marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
39514
39911
|
} catch {
|
|
39515
39912
|
return;
|
|
39516
39913
|
}
|
|
@@ -39524,7 +39921,7 @@ function attachSlackReplayPayload(channel, threadTs, messageTs, payload) {
|
|
|
39524
39921
|
if (!path) return;
|
|
39525
39922
|
let marker;
|
|
39526
39923
|
try {
|
|
39527
|
-
marker = JSON.parse(
|
|
39924
|
+
marker = JSON.parse(readFileSync20(path, "utf-8"));
|
|
39528
39925
|
} catch {
|
|
39529
39926
|
return;
|
|
39530
39927
|
}
|
|
@@ -39535,7 +39932,7 @@ function readSlackPendingInboundMarker(channel, threadTs, messageTs) {
|
|
|
39535
39932
|
const path = slackPendingInboundPath(channel, threadTs, messageTs);
|
|
39536
39933
|
if (!path || !existsSync10(path)) return null;
|
|
39537
39934
|
try {
|
|
39538
|
-
return JSON.parse(
|
|
39935
|
+
return JSON.parse(readFileSync20(path, "utf-8"));
|
|
39539
39936
|
} catch {
|
|
39540
39937
|
return null;
|
|
39541
39938
|
}
|
|
@@ -39651,7 +40048,7 @@ function scheduleBusyAck(channel, threadTs, messageTs, isThreadReply, arrivedWhi
|
|
|
39651
40048
|
let paneLogFreshAgeMs = null;
|
|
39652
40049
|
if (SLACK_AGENT_DIR) {
|
|
39653
40050
|
try {
|
|
39654
|
-
const paneMtimeMs =
|
|
40051
|
+
const paneMtimeMs = statSync4(join20(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
|
|
39655
40052
|
paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
|
|
39656
40053
|
} catch {
|
|
39657
40054
|
}
|
|
@@ -39684,7 +40081,7 @@ function __resetSlackBusyAckNoticeThrottle() {
|
|
|
39684
40081
|
function clearSlackMarkerFileWithHeal(fullPath) {
|
|
39685
40082
|
let marker = null;
|
|
39686
40083
|
try {
|
|
39687
|
-
marker = JSON.parse(
|
|
40084
|
+
marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
39688
40085
|
} catch {
|
|
39689
40086
|
}
|
|
39690
40087
|
if (marker && decideRecoveryHeal({
|
|
@@ -39702,7 +40099,7 @@ function clearSlackMarkerFileWithHeal(fullPath) {
|
|
|
39702
40099
|
function markSlackMarkerSeenWithHeal(fullPath) {
|
|
39703
40100
|
let marker = null;
|
|
39704
40101
|
try {
|
|
39705
|
-
marker = JSON.parse(
|
|
40102
|
+
marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
39706
40103
|
} catch {
|
|
39707
40104
|
return;
|
|
39708
40105
|
}
|
|
@@ -39771,10 +40168,10 @@ function slackNextRetryName(filename) {
|
|
|
39771
40168
|
async function processSlackRecoveryOutboxFile(filename) {
|
|
39772
40169
|
if (!SLACK_RECOVERY_OUTBOX_DIR) return;
|
|
39773
40170
|
if (filename.endsWith(".poison.json") || filename.endsWith(".tmp")) return;
|
|
39774
|
-
const fullPath =
|
|
40171
|
+
const fullPath = join20(SLACK_RECOVERY_OUTBOX_DIR, filename);
|
|
39775
40172
|
let payload;
|
|
39776
40173
|
try {
|
|
39777
|
-
payload = JSON.parse(
|
|
40174
|
+
payload = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
39778
40175
|
} catch (err) {
|
|
39779
40176
|
process.stderr.write(
|
|
39780
40177
|
`slack-channel(${AGENT_CODE_NAME}): recovery outbox parse failed (${filename}): ${err.message}
|
|
@@ -39878,7 +40275,7 @@ async function processSlackRecoveryOutboxFile(filename) {
|
|
|
39878
40275
|
const next = slackNextRetryName(filename);
|
|
39879
40276
|
if (next) {
|
|
39880
40277
|
try {
|
|
39881
|
-
renameSync5(fullPath,
|
|
40278
|
+
renameSync5(fullPath, join20(SLACK_RECOVERY_OUTBOX_DIR, next.next));
|
|
39882
40279
|
if (next.attempt >= SLACK_MAX_RECOVERY_ATTEMPTS) {
|
|
39883
40280
|
process.stderr.write(
|
|
39884
40281
|
`slack-channel(${AGENT_CODE_NAME}): ghost-reply recovery exhausted retries \u2014 moved to ${next.next}
|
|
@@ -39909,7 +40306,7 @@ function scanSlackRecoveryRetries() {
|
|
|
39909
40306
|
if (!SLACK_RECOVERY_OUTBOX_DIR) return;
|
|
39910
40307
|
let entries;
|
|
39911
40308
|
try {
|
|
39912
|
-
entries =
|
|
40309
|
+
entries = readdirSync6(SLACK_RECOVERY_OUTBOX_DIR);
|
|
39913
40310
|
} catch {
|
|
39914
40311
|
return;
|
|
39915
40312
|
}
|
|
@@ -39918,7 +40315,7 @@ function scanSlackRecoveryRetries() {
|
|
|
39918
40315
|
if (!f.includes(".retry-") || f.endsWith(".poison.json")) continue;
|
|
39919
40316
|
let mtimeMs;
|
|
39920
40317
|
try {
|
|
39921
|
-
mtimeMs =
|
|
40318
|
+
mtimeMs = statSync4(join20(SLACK_RECOVERY_OUTBOX_DIR, f)).mtimeMs;
|
|
39922
40319
|
} catch {
|
|
39923
40320
|
continue;
|
|
39924
40321
|
}
|
|
@@ -39939,7 +40336,7 @@ function startSlackRecoveryOutboxWatcher() {
|
|
|
39939
40336
|
return;
|
|
39940
40337
|
}
|
|
39941
40338
|
try {
|
|
39942
|
-
for (const f of
|
|
40339
|
+
for (const f of readdirSync6(SLACK_RECOVERY_OUTBOX_DIR)) {
|
|
39943
40340
|
if (isFirstAttemptSlackOutboxFile(f)) void processSlackRecoveryOutboxFile(f);
|
|
39944
40341
|
}
|
|
39945
40342
|
} catch {
|
|
@@ -39948,7 +40345,7 @@ function startSlackRecoveryOutboxWatcher() {
|
|
|
39948
40345
|
const watcher = watch(SLACK_RECOVERY_OUTBOX_DIR, (event, filename) => {
|
|
39949
40346
|
if (event !== "rename" || !filename) return;
|
|
39950
40347
|
if (!isFirstAttemptSlackOutboxFile(filename)) return;
|
|
39951
|
-
if (existsSync10(
|
|
40348
|
+
if (existsSync10(join20(SLACK_RECOVERY_OUTBOX_DIR, filename))) {
|
|
39952
40349
|
void processSlackRecoveryOutboxFile(filename);
|
|
39953
40350
|
}
|
|
39954
40351
|
});
|
|
@@ -39963,7 +40360,7 @@ function startSlackRecoveryOutboxWatcher() {
|
|
|
39963
40360
|
retryTimer.unref?.();
|
|
39964
40361
|
}
|
|
39965
40362
|
startSlackRecoveryOutboxWatcher();
|
|
39966
|
-
var SLACK_NOTICE_OUTBOX_DIR = SLACK_AGENT_DIR ?
|
|
40363
|
+
var SLACK_NOTICE_OUTBOX_DIR = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "slack-notice-outbox") : null;
|
|
39967
40364
|
var SLACK_NOTICE_MAX_AGE_MS = 9e4;
|
|
39968
40365
|
var SLACK_NOTICE_INFLIGHT = /* @__PURE__ */ new Set();
|
|
39969
40366
|
async function processSlackNoticeOutboxFile(filename) {
|
|
@@ -39971,11 +40368,11 @@ async function processSlackNoticeOutboxFile(filename) {
|
|
|
39971
40368
|
if (filename.startsWith(".") || filename.endsWith(".tmp") || !filename.endsWith(".json")) return;
|
|
39972
40369
|
if (SLACK_NOTICE_INFLIGHT.has(filename)) return;
|
|
39973
40370
|
SLACK_NOTICE_INFLIGHT.add(filename);
|
|
39974
|
-
const fullPath =
|
|
40371
|
+
const fullPath = join20(SLACK_NOTICE_OUTBOX_DIR, filename);
|
|
39975
40372
|
try {
|
|
39976
40373
|
let mtimeMs;
|
|
39977
40374
|
try {
|
|
39978
|
-
mtimeMs =
|
|
40375
|
+
mtimeMs = statSync4(fullPath).mtimeMs;
|
|
39979
40376
|
} catch {
|
|
39980
40377
|
return;
|
|
39981
40378
|
}
|
|
@@ -39988,7 +40385,7 @@ async function processSlackNoticeOutboxFile(filename) {
|
|
|
39988
40385
|
}
|
|
39989
40386
|
let payload;
|
|
39990
40387
|
try {
|
|
39991
|
-
const parsed = JSON.parse(
|
|
40388
|
+
const parsed = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
39992
40389
|
if (!parsed || typeof parsed !== "object") throw new Error("not an object");
|
|
39993
40390
|
payload = parsed;
|
|
39994
40391
|
} catch {
|
|
@@ -40071,13 +40468,13 @@ function startSlackNoticeOutboxWatcher() {
|
|
|
40071
40468
|
return;
|
|
40072
40469
|
}
|
|
40073
40470
|
try {
|
|
40074
|
-
for (const f of
|
|
40471
|
+
for (const f of readdirSync6(SLACK_NOTICE_OUTBOX_DIR)) void processSlackNoticeOutboxFile(f);
|
|
40075
40472
|
} catch {
|
|
40076
40473
|
}
|
|
40077
40474
|
try {
|
|
40078
40475
|
const watcher = watch(SLACK_NOTICE_OUTBOX_DIR, (event, filename) => {
|
|
40079
40476
|
if (event !== "rename" || !filename) return;
|
|
40080
|
-
if (existsSync10(
|
|
40477
|
+
if (existsSync10(join20(SLACK_NOTICE_OUTBOX_DIR, filename))) {
|
|
40081
40478
|
void processSlackNoticeOutboxFile(filename);
|
|
40082
40479
|
}
|
|
40083
40480
|
});
|
|
@@ -40100,7 +40497,7 @@ function sweepSlackStaleMarkers(thresholdMs) {
|
|
|
40100
40497
|
if (!existsSync10(SLACK_PENDING_INBOUND_DIR)) return;
|
|
40101
40498
|
let filenames;
|
|
40102
40499
|
try {
|
|
40103
|
-
filenames =
|
|
40500
|
+
filenames = readdirSync6(SLACK_PENDING_INBOUND_DIR);
|
|
40104
40501
|
} catch (err) {
|
|
40105
40502
|
process.stderr.write(
|
|
40106
40503
|
`slack-channel(${AGENT_CODE_NAME}): stale-marker readdir failed: ${err.message}
|
|
@@ -40114,10 +40511,10 @@ function sweepSlackStaleMarkers(thresholdMs) {
|
|
|
40114
40511
|
for (const filename of filenames) {
|
|
40115
40512
|
if (!filename.endsWith(".json")) continue;
|
|
40116
40513
|
if (filename.endsWith(".tmp")) continue;
|
|
40117
|
-
const fullPath =
|
|
40514
|
+
const fullPath = join20(SLACK_PENDING_INBOUND_DIR, filename);
|
|
40118
40515
|
let marker;
|
|
40119
40516
|
try {
|
|
40120
|
-
marker = JSON.parse(
|
|
40517
|
+
marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
40121
40518
|
} catch (err) {
|
|
40122
40519
|
process.stderr.write(
|
|
40123
40520
|
`slack-channel(${AGENT_CODE_NAME}): stale-marker parse failed for ${redactSlackId(filename)}: ${err.message}
|
|
@@ -40175,13 +40572,13 @@ var slackOrphanSweepTimer = setInterval(() => {
|
|
|
40175
40572
|
checkSlackWatchdogGiveUpNotice();
|
|
40176
40573
|
}, orphanSweepIntervalMs());
|
|
40177
40574
|
slackOrphanSweepTimer.unref?.();
|
|
40178
|
-
var SLACK_PROGRESS_HEARTBEAT_PATH = SLACK_AGENT_DIR ?
|
|
40575
|
+
var SLACK_PROGRESS_HEARTBEAT_PATH = SLACK_AGENT_DIR ? join20(SLACK_AGENT_DIR, "channel-progress-heartbeat.json") : null;
|
|
40179
40576
|
var slackTrackedProgress = null;
|
|
40180
40577
|
var slackProgressTickRunning = false;
|
|
40181
40578
|
function readSlackProgressHeartbeat() {
|
|
40182
40579
|
if (!SLACK_PROGRESS_HEARTBEAT_PATH || !existsSync10(SLACK_PROGRESS_HEARTBEAT_PATH)) return null;
|
|
40183
40580
|
try {
|
|
40184
|
-
return parseProgressHeartbeat(
|
|
40581
|
+
return parseProgressHeartbeat(readFileSync20(SLACK_PROGRESS_HEARTBEAT_PATH, "utf-8"));
|
|
40185
40582
|
} catch {
|
|
40186
40583
|
return null;
|
|
40187
40584
|
}
|
|
@@ -40190,7 +40587,7 @@ function seedSlackProgressHeartbeat() {
|
|
|
40190
40587
|
if (!SLACK_PROGRESS_HEARTBEAT_PATH) return;
|
|
40191
40588
|
const tmp = `${SLACK_PROGRESS_HEARTBEAT_PATH}.${process.pid}.tmp`;
|
|
40192
40589
|
try {
|
|
40193
|
-
|
|
40590
|
+
writeFileSync14(tmp, serializeProgressHeartbeat(SEED_PROGRESS_STEP, Date.now()), { mode: 384 });
|
|
40194
40591
|
renameSync5(tmp, SLACK_PROGRESS_HEARTBEAT_PATH);
|
|
40195
40592
|
} catch {
|
|
40196
40593
|
try {
|
|
@@ -40204,11 +40601,11 @@ function findSlackProgressTarget() {
|
|
|
40204
40601
|
let best = null;
|
|
40205
40602
|
let bestMs = Infinity;
|
|
40206
40603
|
try {
|
|
40207
|
-
for (const name of
|
|
40604
|
+
for (const name of readdirSync6(SLACK_PENDING_INBOUND_DIR)) {
|
|
40208
40605
|
if (!name.endsWith(".json")) continue;
|
|
40209
40606
|
let m;
|
|
40210
40607
|
try {
|
|
40211
|
-
m = JSON.parse(
|
|
40608
|
+
m = JSON.parse(readFileSync20(join20(SLACK_PENDING_INBOUND_DIR, name), "utf-8"));
|
|
40212
40609
|
} catch {
|
|
40213
40610
|
continue;
|
|
40214
40611
|
}
|
|
@@ -40355,11 +40752,11 @@ function listPendingSlackConversations() {
|
|
|
40355
40752
|
if (!SLACK_PENDING_INBOUND_DIR || !existsSync10(SLACK_PENDING_INBOUND_DIR)) return [];
|
|
40356
40753
|
const byKey = /* @__PURE__ */ new Map();
|
|
40357
40754
|
try {
|
|
40358
|
-
for (const name of
|
|
40755
|
+
for (const name of readdirSync6(SLACK_PENDING_INBOUND_DIR)) {
|
|
40359
40756
|
if (!name.endsWith(".json")) continue;
|
|
40360
40757
|
try {
|
|
40361
40758
|
const marker = JSON.parse(
|
|
40362
|
-
|
|
40759
|
+
readFileSync20(join20(SLACK_PENDING_INBOUND_DIR, name), "utf8")
|
|
40363
40760
|
);
|
|
40364
40761
|
if (typeof marker.channel !== "string" || !marker.channel) continue;
|
|
40365
40762
|
if (typeof marker.thread_ts !== "string" || !marker.thread_ts) continue;
|
|
@@ -40411,7 +40808,7 @@ function postSlackWatchdogGiveUpNotice(channel, threadTs, isThreadReply, reason)
|
|
|
40411
40808
|
}
|
|
40412
40809
|
function checkSlackWatchdogGiveUpNotice() {
|
|
40413
40810
|
if (!SLACK_AGENT_DIR) return;
|
|
40414
|
-
const signal = readGiveUpSignal(
|
|
40811
|
+
const signal = readGiveUpSignal(join20(SLACK_AGENT_DIR, GIVE_UP_SIGNAL_FILENAME));
|
|
40415
40812
|
const signalAtMs = signal?.atMs ?? null;
|
|
40416
40813
|
const act = decideGiveUpNotice({
|
|
40417
40814
|
signalAtMs,
|
|
@@ -40443,7 +40840,7 @@ function readRestartTopicForMarker(filename, channel, threadTs) {
|
|
|
40443
40840
|
if (!SLACK_RESTART_CONTEXT_DIR) return null;
|
|
40444
40841
|
let raw;
|
|
40445
40842
|
try {
|
|
40446
|
-
raw =
|
|
40843
|
+
raw = readFileSync20(join20(SLACK_RESTART_CONTEXT_DIR, filename), "utf-8");
|
|
40447
40844
|
} catch {
|
|
40448
40845
|
return null;
|
|
40449
40846
|
}
|
|
@@ -40452,7 +40849,7 @@ function readRestartTopicForMarker(filename, channel, threadTs) {
|
|
|
40452
40849
|
function removeRestartContextHint(filename) {
|
|
40453
40850
|
if (!SLACK_RESTART_CONTEXT_DIR) return;
|
|
40454
40851
|
try {
|
|
40455
|
-
unlinkSync7(
|
|
40852
|
+
unlinkSync7(join20(SLACK_RESTART_CONTEXT_DIR, filename));
|
|
40456
40853
|
} catch {
|
|
40457
40854
|
}
|
|
40458
40855
|
}
|
|
@@ -40460,14 +40857,14 @@ function clearAllRestartContextHints() {
|
|
|
40460
40857
|
if (!SLACK_RESTART_CONTEXT_DIR) return;
|
|
40461
40858
|
let names;
|
|
40462
40859
|
try {
|
|
40463
|
-
names =
|
|
40860
|
+
names = readdirSync6(SLACK_RESTART_CONTEXT_DIR);
|
|
40464
40861
|
} catch {
|
|
40465
40862
|
return;
|
|
40466
40863
|
}
|
|
40467
40864
|
for (const name of names) {
|
|
40468
40865
|
if (!name.endsWith(".json")) continue;
|
|
40469
40866
|
try {
|
|
40470
|
-
unlinkSync7(
|
|
40867
|
+
unlinkSync7(join20(SLACK_RESTART_CONTEXT_DIR, name));
|
|
40471
40868
|
} catch {
|
|
40472
40869
|
}
|
|
40473
40870
|
}
|
|
@@ -40484,7 +40881,7 @@ async function notifyStrandedInboundsOnFirstConnect() {
|
|
|
40484
40881
|
if (!SLACK_PENDING_INBOUND_DIR || !existsSync10(SLACK_PENDING_INBOUND_DIR)) return;
|
|
40485
40882
|
let filenames;
|
|
40486
40883
|
try {
|
|
40487
|
-
filenames =
|
|
40884
|
+
filenames = readdirSync6(SLACK_PENDING_INBOUND_DIR);
|
|
40488
40885
|
} catch {
|
|
40489
40886
|
hadFailure = true;
|
|
40490
40887
|
return;
|
|
@@ -40494,10 +40891,10 @@ async function notifyStrandedInboundsOnFirstConnect() {
|
|
|
40494
40891
|
let notified = 0;
|
|
40495
40892
|
for (const filename of filenames) {
|
|
40496
40893
|
if (!filename.endsWith(".json")) continue;
|
|
40497
|
-
const fullPath =
|
|
40894
|
+
const fullPath = join20(SLACK_PENDING_INBOUND_DIR, filename);
|
|
40498
40895
|
let marker;
|
|
40499
40896
|
try {
|
|
40500
|
-
marker = JSON.parse(
|
|
40897
|
+
marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
40501
40898
|
} catch {
|
|
40502
40899
|
continue;
|
|
40503
40900
|
}
|
|
@@ -40671,7 +41068,7 @@ function noteThreadActivityByMessageTs(channel, messageTs) {
|
|
|
40671
41068
|
markSeenAllSlackPendingMarkersForThread2(channel, messageTs);
|
|
40672
41069
|
markSeenSlackPendingMarkerByMessageTs2(channel, messageTs);
|
|
40673
41070
|
}
|
|
40674
|
-
var RESTART_FLAGS_DIR =
|
|
41071
|
+
var RESTART_FLAGS_DIR = join20(homedir7(), ".augmented", "restart-flags");
|
|
40675
41072
|
function actuateHostRestartSlack() {
|
|
40676
41073
|
return actuateHostRestart({
|
|
40677
41074
|
agtHost: AGT_HOST,
|
|
@@ -40692,10 +41089,10 @@ function buildAugmentedSlackMetadata() {
|
|
|
40692
41089
|
};
|
|
40693
41090
|
}
|
|
40694
41091
|
function hashChannelId(id) {
|
|
40695
|
-
return
|
|
41092
|
+
return createHash3("sha256").update(id).digest("hex").slice(0, 8);
|
|
40696
41093
|
}
|
|
40697
41094
|
function hashId(id) {
|
|
40698
|
-
return
|
|
41095
|
+
return createHash3("sha256").update(id).digest("hex").slice(0, 8);
|
|
40699
41096
|
}
|
|
40700
41097
|
async function postSlackMessage(body) {
|
|
40701
41098
|
const augmentedMeta = buildAugmentedSlackMetadata();
|
|
@@ -41276,7 +41673,7 @@ async function handleSlashCommandEnvelope(payload) {
|
|
|
41276
41673
|
if (!existsSync10(RESTART_FLAGS_DIR)) {
|
|
41277
41674
|
mkdirSync9(RESTART_FLAGS_DIR, { recursive: true });
|
|
41278
41675
|
}
|
|
41279
|
-
const flagPath =
|
|
41676
|
+
const flagPath = join20(RESTART_FLAGS_DIR, `${codeName}.flag`);
|
|
41280
41677
|
const flag = {
|
|
41281
41678
|
codeName,
|
|
41282
41679
|
source: "slack",
|
|
@@ -41284,7 +41681,7 @@ async function handleSlashCommandEnvelope(payload) {
|
|
|
41284
41681
|
reply: confirmReply
|
|
41285
41682
|
};
|
|
41286
41683
|
const tmpPath = `${flagPath}.${process.pid}.${randomUUID2()}.tmp`;
|
|
41287
|
-
|
|
41684
|
+
writeFileSync14(tmpPath, JSON.stringify(flag) + "\n", "utf8");
|
|
41288
41685
|
renameSync5(tmpPath, flagPath);
|
|
41289
41686
|
}
|
|
41290
41687
|
process.stderr.write(
|
|
@@ -41419,7 +41816,7 @@ async function handleRestartCommand(opts) {
|
|
|
41419
41816
|
if (!existsSync10(RESTART_FLAGS_DIR)) {
|
|
41420
41817
|
mkdirSync9(RESTART_FLAGS_DIR, { recursive: true });
|
|
41421
41818
|
}
|
|
41422
|
-
const flagPath =
|
|
41819
|
+
const flagPath = join20(RESTART_FLAGS_DIR, `${codeName}.flag`);
|
|
41423
41820
|
const flag = {
|
|
41424
41821
|
codeName,
|
|
41425
41822
|
source: "slack",
|
|
@@ -41427,7 +41824,7 @@ async function handleRestartCommand(opts) {
|
|
|
41427
41824
|
reply: { ...confirmReply, message_ts: opts.ts }
|
|
41428
41825
|
};
|
|
41429
41826
|
const tmpPath = `${flagPath}.${process.pid}.${randomUUID2()}.tmp`;
|
|
41430
|
-
|
|
41827
|
+
writeFileSync14(tmpPath, JSON.stringify(flag) + "\n", "utf8");
|
|
41431
41828
|
renameSync5(tmpPath, flagPath);
|
|
41432
41829
|
}
|
|
41433
41830
|
process.stderr.write(
|
|
@@ -41541,7 +41938,7 @@ var SLACK_HOT_THREAD_WINDOW_MS = parseHotThreadWindowMs(
|
|
|
41541
41938
|
);
|
|
41542
41939
|
function resolveThreadStorePath() {
|
|
41543
41940
|
if (!AGENT_CODE_NAME) return null;
|
|
41544
|
-
return
|
|
41941
|
+
return join20(homedir7(), ".augmented", AGENT_CODE_NAME, "slack-tracked-threads.json");
|
|
41545
41942
|
}
|
|
41546
41943
|
function parseTtlDays(raw) {
|
|
41547
41944
|
if (!raw) return void 0;
|
|
@@ -41580,9 +41977,9 @@ if (!BOT_TOKEN || !APP_TOKEN) {
|
|
|
41580
41977
|
var slackStderrLogStream = null;
|
|
41581
41978
|
if (AGENT_CODE_NAME) {
|
|
41582
41979
|
try {
|
|
41583
|
-
const logDir =
|
|
41980
|
+
const logDir = join20(homedir7(), ".augmented", AGENT_CODE_NAME);
|
|
41584
41981
|
mkdirSync9(logDir, { recursive: true });
|
|
41585
|
-
slackStderrLogStream = createWriteStream(
|
|
41982
|
+
slackStderrLogStream = createWriteStream(join20(logDir, "slack-channel-stderr.log"), {
|
|
41586
41983
|
flags: "a",
|
|
41587
41984
|
mode: 384
|
|
41588
41985
|
});
|
|
@@ -42118,6 +42515,11 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
42118
42515
|
windowMs: SLACK_HOT_THREAD_WINDOW_MS
|
|
42119
42516
|
});
|
|
42120
42517
|
hotGuard = applyHotThreadGuard({ baseThreadTs, forcedRoot, hotThread });
|
|
42518
|
+
recordHotThreadClassification(SLACK_AGENT_DIR, channel, {
|
|
42519
|
+
mode: hotThreadMode,
|
|
42520
|
+
outcome: hotGuard.guard,
|
|
42521
|
+
proactive: proactive === true
|
|
42522
|
+
});
|
|
42121
42523
|
if (hotGuard.guard === "redirected_to_hot_thread") {
|
|
42122
42524
|
process.stderr.write(
|
|
42123
42525
|
`slack-channel(${AGENT_CODE_NAME}): hot_thread_guard mode=${hotThreadMode} applied=${hotThreadMode === "enforce"} channel=${redactSlackId(channel)} hot_thread=${redactSlackId(hotGuard.threadTs)} proactive=${proactive === true} age_ms=${hotThread?.ageMs ?? ""}
|
|
@@ -42453,7 +42855,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
|
|
|
42453
42855
|
isError: true
|
|
42454
42856
|
};
|
|
42455
42857
|
}
|
|
42456
|
-
const allowedRoot = resolve2(
|
|
42858
|
+
const allowedRoot = resolve2(homedir7(), ".augmented", AGENT_CODE_NAME, "project") + "/";
|
|
42457
42859
|
const resolvedPath = resolve2(path);
|
|
42458
42860
|
if (!resolvedPath.startsWith(allowedRoot)) {
|
|
42459
42861
|
return {
|
|
@@ -42467,7 +42869,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
|
|
|
42467
42869
|
let bytes;
|
|
42468
42870
|
let size;
|
|
42469
42871
|
try {
|
|
42470
|
-
const stat2 =
|
|
42872
|
+
const stat2 = statSync4(resolvedPath);
|
|
42471
42873
|
if (!stat2.isFile()) {
|
|
42472
42874
|
return {
|
|
42473
42875
|
content: [{ type: "text", text: `Upload refused: ${resolvedPath} is not a regular file.` }],
|
|
@@ -42475,7 +42877,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
|
|
|
42475
42877
|
};
|
|
42476
42878
|
}
|
|
42477
42879
|
size = stat2.size;
|
|
42478
|
-
bytes =
|
|
42880
|
+
bytes = readFileSync20(resolvedPath);
|
|
42479
42881
|
} catch (err) {
|
|
42480
42882
|
return {
|
|
42481
42883
|
content: [{ type: "text", text: `Failed to read file: ${err.message}` }],
|
|
@@ -43130,7 +43532,7 @@ function isDownloadableFileId(fileId, channel) {
|
|
|
43130
43532
|
}
|
|
43131
43533
|
function redactAugmentedPaths2(msg) {
|
|
43132
43534
|
return msg.replaceAll(
|
|
43133
|
-
new RegExp(`${
|
|
43535
|
+
new RegExp(`${homedir7().replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&")}/\\.augmented/[^\\s'"\`]*`, "g"),
|
|
43134
43536
|
"<augmented-path>"
|
|
43135
43537
|
);
|
|
43136
43538
|
}
|
|
@@ -43189,7 +43591,7 @@ async function downloadSlackFile(fileId, codeName) {
|
|
|
43189
43591
|
throw new Error(`refusing to write ${savedPath} outside ${dir}`);
|
|
43190
43592
|
}
|
|
43191
43593
|
mkdirSync9(dir, { recursive: true });
|
|
43192
|
-
|
|
43594
|
+
writeFileSync14(savedPath, bytes, { mode: 384 });
|
|
43193
43595
|
try {
|
|
43194
43596
|
chmodSync(savedPath, 384);
|
|
43195
43597
|
} catch {
|
|
@@ -43250,7 +43652,7 @@ async function replayPendingSlackMarkers() {
|
|
|
43250
43652
|
if (!sessionAlive) return;
|
|
43251
43653
|
let filenames;
|
|
43252
43654
|
try {
|
|
43253
|
-
filenames =
|
|
43655
|
+
filenames = readdirSync6(SLACK_PENDING_INBOUND_DIR);
|
|
43254
43656
|
} catch {
|
|
43255
43657
|
return;
|
|
43256
43658
|
}
|
|
@@ -43258,7 +43660,7 @@ async function replayPendingSlackMarkers() {
|
|
|
43258
43660
|
let paneFreshAgeMs = null;
|
|
43259
43661
|
if (SLACK_AGENT_DIR) {
|
|
43260
43662
|
try {
|
|
43261
|
-
paneFreshAgeMs = Math.max(0, now -
|
|
43663
|
+
paneFreshAgeMs = Math.max(0, now - statSync4(join20(SLACK_AGENT_DIR, "pane.log")).mtimeMs);
|
|
43262
43664
|
} catch {
|
|
43263
43665
|
}
|
|
43264
43666
|
}
|
|
@@ -43266,10 +43668,10 @@ async function replayPendingSlackMarkers() {
|
|
|
43266
43668
|
const entries = [];
|
|
43267
43669
|
for (const name of filenames) {
|
|
43268
43670
|
if (!name.endsWith(".json") || name.endsWith(".tmp")) continue;
|
|
43269
|
-
const fullPath =
|
|
43671
|
+
const fullPath = join20(SLACK_PENDING_INBOUND_DIR, name);
|
|
43270
43672
|
let marker;
|
|
43271
43673
|
try {
|
|
43272
|
-
marker = JSON.parse(
|
|
43674
|
+
marker = JSON.parse(readFileSync20(fullPath, "utf-8"));
|
|
43273
43675
|
} catch {
|
|
43274
43676
|
continue;
|
|
43275
43677
|
}
|
|
@@ -43616,7 +44018,7 @@ async function connectSocketMode() {
|
|
|
43616
44018
|
const passedIdentity = access.kind !== "drop" || access.reason.startsWith("peer:");
|
|
43617
44019
|
if (passedIdentity) recordActivity("inbound");
|
|
43618
44020
|
if (access.kind === "drop") {
|
|
43619
|
-
const channelHash =
|
|
44021
|
+
const channelHash = createHash3("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
|
|
43620
44022
|
const subtypeSuffix = access.reason === "content:subtype" ? ` subtype=${evt.subtype ?? "none"}` : "";
|
|
43621
44023
|
process.stderr.write(
|
|
43622
44024
|
`slack-channel: inbound drop reason=${access.reason}${subtypeSuffix} channel=${channelHash} ts=${redactSlackId(evt.ts)}
|
|
@@ -43741,7 +44143,8 @@ async function connectSocketMode() {
|
|
|
43741
44143
|
});
|
|
43742
44144
|
return;
|
|
43743
44145
|
}
|
|
43744
|
-
const
|
|
44146
|
+
const reactiveMode = resolveUsageLimitReactiveMode();
|
|
44147
|
+
const usageLimitUntil = !isBot && shouldReadPredictiveMarker(reactiveMode) ? readUsageLimitUntil({ codeName: AGENT_CODE_NAME }) : null;
|
|
43745
44148
|
if (usageLimitUntil) {
|
|
43746
44149
|
process.stderr.write(
|
|
43747
44150
|
`slack-channel(${AGENT_CODE_NAME}): usage-limit active until ${usageLimitUntil.toISOString()} \u2014 notice, no dispatch (channel=${redactSlackId(evt.channel)})
|
|
@@ -43800,7 +44203,7 @@ async function connectSocketMode() {
|
|
|
43800
44203
|
if (evt.type === "message" && evt.channel && !isDirectMessage) {
|
|
43801
44204
|
if (isThreadReply) {
|
|
43802
44205
|
const logThreadDrop = (reason) => {
|
|
43803
|
-
const channelHash =
|
|
44206
|
+
const channelHash = createHash3("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
|
|
43804
44207
|
process.stderr.write(
|
|
43805
44208
|
`slack-channel(${AGENT_CODE_NAME}): thread-reply drop reason=${reason} auto_follow=${THREAD_AUTO_FOLLOW} channel=${channelHash} ts=${redactSlackId(evt.ts)}
|
|
43806
44209
|
`
|
|
@@ -43866,7 +44269,7 @@ async function connectSocketMode() {
|
|
|
43866
44269
|
let paneLogFreshAgeMs = null;
|
|
43867
44270
|
if (SLACK_AGENT_DIR) {
|
|
43868
44271
|
try {
|
|
43869
|
-
const paneMtimeMs =
|
|
44272
|
+
const paneMtimeMs = statSync4(join20(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
|
|
43870
44273
|
paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
|
|
43871
44274
|
} catch {
|
|
43872
44275
|
}
|
|
@@ -44032,10 +44435,26 @@ ${forwarded.text}` : forwarded.text;
|
|
|
44032
44435
|
});
|
|
44033
44436
|
clearScheduledTurnMarker(SLACK_AGENT_DIR);
|
|
44034
44437
|
}
|
|
44438
|
+
const dispatchedAtMs = Date.now();
|
|
44035
44439
|
await mcp.notification({
|
|
44036
44440
|
method: "notifications/claude/channel",
|
|
44037
44441
|
params: replayPayload
|
|
44038
44442
|
});
|
|
44443
|
+
const watchMode = armedWatchMode({
|
|
44444
|
+
mode: reactiveMode,
|
|
44445
|
+
isBot: isFromBot,
|
|
44446
|
+
replyOwed: shouldEngage
|
|
44447
|
+
});
|
|
44448
|
+
if (watchMode) {
|
|
44449
|
+
armSlackUsageLimitWatch({
|
|
44450
|
+
mode: watchMode,
|
|
44451
|
+
channel,
|
|
44452
|
+
senderId: evt.user,
|
|
44453
|
+
threadTs,
|
|
44454
|
+
messageTs: ts,
|
|
44455
|
+
sinceMs: dispatchedAtMs
|
|
44456
|
+
});
|
|
44457
|
+
}
|
|
44039
44458
|
if (shouldEngage) seedSlackProgressHeartbeat();
|
|
44040
44459
|
if (channel) {
|
|
44041
44460
|
conversationIngestClient?.ingest({
|