@integrity-labs/agt-cli 0.28.458 → 0.28.460
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-KAIH24HZ.js → chunk-BWH5XTDU.js} +25 -4
- package/dist/chunk-BWH5XTDU.js.map +1 -0
- package/dist/{chunk-QIQQ46NH.js → chunk-EBSFYBRI.js} +3 -3
- package/dist/{claude-pair-runtime-CVCPBJOZ.js → claude-pair-runtime-YNOY2ATX.js} +2 -2
- package/dist/lib/manager-worker.js +37 -11
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +1134 -788
- package/dist/mcp/origami.js +11 -1
- package/dist/mcp/slack-channel.js +539 -139
- package/dist/mcp/telegram-channel.js +482 -94
- package/dist/{persistent-session-EVLWDI3I.js → persistent-session-KGRCIIS5.js} +2 -2
- package/dist/{responsiveness-probe-EGP2F3WD.js → responsiveness-probe-4FVGB6NY.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-KAIH24HZ.js.map +0 -1
- /package/dist/{chunk-QIQQ46NH.js.map → chunk-EBSFYBRI.js.map} +0 -0
- /package/dist/{claude-pair-runtime-CVCPBJOZ.js.map → claude-pair-runtime-YNOY2ATX.js.map} +0 -0
- /package/dist/{persistent-session-EVLWDI3I.js.map → persistent-session-KGRCIIS5.js.map} +0 -0
- /package/dist/{responsiveness-probe-EGP2F3WD.js.map → responsiveness-probe-4FVGB6NY.js.map} +0 -0
|
@@ -18906,7 +18906,7 @@ var require_filters = __commonJS({
|
|
|
18906
18906
|
return r.copySafeness(str, res);
|
|
18907
18907
|
}
|
|
18908
18908
|
_exports.indent = indent;
|
|
18909
|
-
function
|
|
18909
|
+
function join22(arr, del, attr) {
|
|
18910
18910
|
del = del || "";
|
|
18911
18911
|
if (attr) {
|
|
18912
18912
|
arr = lib.map(arr, function(v) {
|
|
@@ -18915,7 +18915,7 @@ var require_filters = __commonJS({
|
|
|
18915
18915
|
}
|
|
18916
18916
|
return arr.join(del);
|
|
18917
18917
|
}
|
|
18918
|
-
_exports.join =
|
|
18918
|
+
_exports.join = join22;
|
|
18919
18919
|
function last(arr) {
|
|
18920
18920
|
return arr[arr.length - 1];
|
|
18921
18921
|
}
|
|
@@ -22516,11 +22516,11 @@ async function waitForResolution(cfg, callbackId, opts) {
|
|
|
22516
22516
|
}
|
|
22517
22517
|
} catch {
|
|
22518
22518
|
}
|
|
22519
|
-
await
|
|
22519
|
+
await sleep3(interval);
|
|
22520
22520
|
}
|
|
22521
22521
|
return { kind: "timeout" };
|
|
22522
22522
|
}
|
|
22523
|
-
function
|
|
22523
|
+
function sleep3(ms) {
|
|
22524
22524
|
return new Promise((r) => setTimeout(r, ms));
|
|
22525
22525
|
}
|
|
22526
22526
|
function generateOptionToken() {
|
|
@@ -34052,6 +34052,160 @@ function classifyTranscriptRateLimit(jsonl, startMs, endMs, now) {
|
|
|
34052
34052
|
return newest;
|
|
34053
34053
|
}
|
|
34054
34054
|
|
|
34055
|
+
// ../core/dist/claude-code-usage/turn-failure-classifier.js
|
|
34056
|
+
var UNKNOWN_TURN_FAILURE = Object.freeze({
|
|
34057
|
+
outcome: "unknown",
|
|
34058
|
+
atMs: null,
|
|
34059
|
+
failureClass: null,
|
|
34060
|
+
httpStatus: null,
|
|
34061
|
+
attempt: null,
|
|
34062
|
+
maxAttempts: null
|
|
34063
|
+
});
|
|
34064
|
+
var EXCLUDED_STATUSES = /* @__PURE__ */ new Set([429]);
|
|
34065
|
+
function classifyTransientStatus(status) {
|
|
34066
|
+
if (!Number.isFinite(status))
|
|
34067
|
+
return null;
|
|
34068
|
+
if (EXCLUDED_STATUSES.has(status))
|
|
34069
|
+
return null;
|
|
34070
|
+
if (status === 529)
|
|
34071
|
+
return "overloaded";
|
|
34072
|
+
if (status >= 500 && status <= 599)
|
|
34073
|
+
return "server_error";
|
|
34074
|
+
return null;
|
|
34075
|
+
}
|
|
34076
|
+
function numberOrNull(value) {
|
|
34077
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
34078
|
+
}
|
|
34079
|
+
function isErrorShaped(record2) {
|
|
34080
|
+
if (record2.isApiErrorMessage === true)
|
|
34081
|
+
return true;
|
|
34082
|
+
if (record2.type === "system" && record2.level === "error")
|
|
34083
|
+
return true;
|
|
34084
|
+
if (record2.type === "assistant" && typeof record2.error === "string" && record2.error)
|
|
34085
|
+
return true;
|
|
34086
|
+
return false;
|
|
34087
|
+
}
|
|
34088
|
+
function classifyRecord(record2, tsMs) {
|
|
34089
|
+
if (record2.isSidechain === true)
|
|
34090
|
+
return null;
|
|
34091
|
+
if (record2.type === "system" && record2.subtype === "api_error") {
|
|
34092
|
+
const error2 = record2.error;
|
|
34093
|
+
const status = typeof error2 === "object" && error2 !== null ? numberOrNull(error2.status) : null;
|
|
34094
|
+
if (status === null)
|
|
34095
|
+
return null;
|
|
34096
|
+
const failureClass = classifyTransientStatus(status);
|
|
34097
|
+
if (!failureClass)
|
|
34098
|
+
return null;
|
|
34099
|
+
return {
|
|
34100
|
+
outcome: "retrying",
|
|
34101
|
+
atMs: tsMs,
|
|
34102
|
+
failureClass,
|
|
34103
|
+
httpStatus: status,
|
|
34104
|
+
attempt: numberOrNull(record2.retryAttempt),
|
|
34105
|
+
maxAttempts: numberOrNull(record2.maxRetries)
|
|
34106
|
+
};
|
|
34107
|
+
}
|
|
34108
|
+
if (record2.type !== "assistant")
|
|
34109
|
+
return null;
|
|
34110
|
+
if (record2.isApiErrorMessage === true) {
|
|
34111
|
+
const status = numberOrNull(record2.apiErrorStatus);
|
|
34112
|
+
const failureClass = status === null ? null : classifyTransientStatus(status);
|
|
34113
|
+
if (!failureClass)
|
|
34114
|
+
return null;
|
|
34115
|
+
return {
|
|
34116
|
+
outcome: "failed",
|
|
34117
|
+
atMs: tsMs,
|
|
34118
|
+
failureClass,
|
|
34119
|
+
httpStatus: status,
|
|
34120
|
+
attempt: null,
|
|
34121
|
+
maxAttempts: null
|
|
34122
|
+
};
|
|
34123
|
+
}
|
|
34124
|
+
const message = record2.message;
|
|
34125
|
+
if (typeof message !== "object" || message === null)
|
|
34126
|
+
return null;
|
|
34127
|
+
const msg = message;
|
|
34128
|
+
if (msg.model === "<synthetic>")
|
|
34129
|
+
return null;
|
|
34130
|
+
const usage = msg.usage;
|
|
34131
|
+
if (typeof usage !== "object" || usage === null)
|
|
34132
|
+
return null;
|
|
34133
|
+
const u = usage;
|
|
34134
|
+
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);
|
|
34135
|
+
if (!Number.isFinite(spent) || spent <= 0)
|
|
34136
|
+
return null;
|
|
34137
|
+
return {
|
|
34138
|
+
outcome: "served",
|
|
34139
|
+
atMs: tsMs,
|
|
34140
|
+
failureClass: null,
|
|
34141
|
+
httpStatus: null,
|
|
34142
|
+
attempt: null,
|
|
34143
|
+
maxAttempts: null
|
|
34144
|
+
};
|
|
34145
|
+
}
|
|
34146
|
+
function pickNewerTurnFailure(current, next) {
|
|
34147
|
+
if (next.outcome === "unknown")
|
|
34148
|
+
return current;
|
|
34149
|
+
if (current.outcome === "unknown")
|
|
34150
|
+
return next;
|
|
34151
|
+
return (next.atMs ?? 0) >= (current.atMs ?? 0) ? next : current;
|
|
34152
|
+
}
|
|
34153
|
+
function isShapeRecognised(record2) {
|
|
34154
|
+
if (record2.type === "system" && record2.subtype === "api_error") {
|
|
34155
|
+
const error2 = record2.error;
|
|
34156
|
+
return typeof error2 === "object" && error2 !== null && numberOrNull(error2.status) !== null;
|
|
34157
|
+
}
|
|
34158
|
+
if (record2.type === "assistant" && record2.isApiErrorMessage === true) {
|
|
34159
|
+
return numberOrNull(record2.apiErrorStatus) !== null;
|
|
34160
|
+
}
|
|
34161
|
+
return false;
|
|
34162
|
+
}
|
|
34163
|
+
function analyzeTranscriptTurnFailure(jsonl, startMs, endMs, opts = {}) {
|
|
34164
|
+
const maxKeys = opts.maxKeys ?? 40;
|
|
34165
|
+
let newest = UNKNOWN_TURN_FAILURE;
|
|
34166
|
+
let coarse = 0;
|
|
34167
|
+
let fine = 0;
|
|
34168
|
+
const keys = /* @__PURE__ */ new Set();
|
|
34169
|
+
for (const line of jsonl.split("\n")) {
|
|
34170
|
+
const trimmed = line.trim();
|
|
34171
|
+
if (!trimmed)
|
|
34172
|
+
continue;
|
|
34173
|
+
let obj;
|
|
34174
|
+
try {
|
|
34175
|
+
obj = JSON.parse(trimmed);
|
|
34176
|
+
} catch {
|
|
34177
|
+
continue;
|
|
34178
|
+
}
|
|
34179
|
+
if (typeof obj !== "object" || obj === null)
|
|
34180
|
+
continue;
|
|
34181
|
+
const record2 = obj;
|
|
34182
|
+
const ts = record2.timestamp;
|
|
34183
|
+
if (typeof ts !== "string" || !ts)
|
|
34184
|
+
continue;
|
|
34185
|
+
const tsMs = new Date(ts).getTime();
|
|
34186
|
+
if (!Number.isFinite(tsMs) || tsMs < startMs || tsMs > endMs)
|
|
34187
|
+
continue;
|
|
34188
|
+
const classified = classifyRecord(record2, tsMs);
|
|
34189
|
+
if (classified)
|
|
34190
|
+
newest = pickNewerTurnFailure(newest, classified);
|
|
34191
|
+
if (!isErrorShaped(record2) || record2.isSidechain === true)
|
|
34192
|
+
continue;
|
|
34193
|
+
coarse++;
|
|
34194
|
+
if (isShapeRecognised(record2)) {
|
|
34195
|
+
fine++;
|
|
34196
|
+
continue;
|
|
34197
|
+
}
|
|
34198
|
+
if (keys.size < maxKeys) {
|
|
34199
|
+
for (const key2 of Object.keys(record2)) {
|
|
34200
|
+
if (keys.size >= maxKeys)
|
|
34201
|
+
break;
|
|
34202
|
+
keys.add(key2);
|
|
34203
|
+
}
|
|
34204
|
+
}
|
|
34205
|
+
}
|
|
34206
|
+
return { result: newest, coarse, fine, unrecognisedKeys: [...keys].sort() };
|
|
34207
|
+
}
|
|
34208
|
+
|
|
34055
34209
|
// ../core/dist/claude-code-usage/transcript-location.js
|
|
34056
34210
|
function encodeClaudeProjectPath(projectDir) {
|
|
34057
34211
|
return "-" + projectDir.replace(/^\//, "").replace(/[/.]/g, "-");
|
|
@@ -34908,7 +35062,7 @@ var FLAG_REGISTRY = [
|
|
|
34908
35062
|
},
|
|
34909
35063
|
{
|
|
34910
35064
|
key: "wedge-transient-notice",
|
|
34911
|
-
description:
|
|
35065
|
+
description: `Tell the person waiting when their turn dies on a transient LLM-API failure (529 overloaded / 5xx). TWO consumers now share this gate. (1) ENG-7360: a wedge-respawn preceded by such an error writes the ENG-6058 give-up signal tagged reason=transient_overload so the channel sweeps post a "please resend" notice. (2) ENG-8269: the channel MCPs watch the dispatched turn in Claude Code's own transcript and notify the conversation that was actually waiting \u2014 Slack, Telegram AND direct chat \u2014 plus a "still working on this" notice after ~3min on Slack/Telegram only (direct chat already shows a client-side one at 90s). NOTE: (2) fires on a MUCH larger population than (1) \u2014 any dispatched turn that dies, not only one that also wedged the session \u2014 and (1) has never actually been able to fire, because its pane.log detector cannot match the banner Claude Code renders today. So flipping this on is in practice enabling (2) for the first time. Boolean gate; ships dark \u2014 channel-visible copy soaks per host before going wide. Materialized into the channel-MCP spawn env: a Docker-isolated agent never mounts the host flags-cache, so a central flip reaches it only that way.`,
|
|
34912
35066
|
flagType: "boolean",
|
|
34913
35067
|
defaultValue: false,
|
|
34914
35068
|
envVar: "AGT_WEDGE_TRANSIENT_NOTICE_ENABLED"
|
|
@@ -35731,6 +35885,12 @@ function giveUpNoticeText(reason = null) {
|
|
|
35731
35885
|
}
|
|
35732
35886
|
return "\u26A0\uFE0F I couldn't read your last message \u2014 please resend it.";
|
|
35733
35887
|
}
|
|
35888
|
+
function turnFailedNoticeText() {
|
|
35889
|
+
return "\u26A0\uFE0F Something went wrong on my side and I couldn\u2019t finish that. Sorry \u2014 send it again when you get a chance and I\u2019ll pick it straight up.";
|
|
35890
|
+
}
|
|
35891
|
+
function turnRetryingNoticeText() {
|
|
35892
|
+
return "\u23F3 Still working on this \u2014 things are running slower than usual on my side. I\u2019ll reply as soon as I have it.";
|
|
35893
|
+
}
|
|
35734
35894
|
function oldestPendingMarkerAgeMs(dir, now = Date.now(), opts) {
|
|
35735
35895
|
if (!dir) return null;
|
|
35736
35896
|
let names;
|
|
@@ -36706,6 +36866,149 @@ async function watchForRateLimitRefusal(opts) {
|
|
|
36706
36866
|
}
|
|
36707
36867
|
}
|
|
36708
36868
|
|
|
36869
|
+
// src/turn-failure-watch.ts
|
|
36870
|
+
import { readFileSync as readFileSync7, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
|
|
36871
|
+
import { join as join8 } from "path";
|
|
36872
|
+
function turnFailureNoticeEnabled(env2) {
|
|
36873
|
+
return resolveHostBooleanFlag({
|
|
36874
|
+
key: "wedge-transient-notice",
|
|
36875
|
+
envVar: "AGT_WEDGE_TRANSIENT_NOTICE_ENABLED",
|
|
36876
|
+
defaultValue: false,
|
|
36877
|
+
...env2 ? { env: env2 } : {}
|
|
36878
|
+
});
|
|
36879
|
+
}
|
|
36880
|
+
var DEFAULT_FAILURE_WATCH_MS = 5 * 6e4;
|
|
36881
|
+
var FAST_POLL_MS = 500;
|
|
36882
|
+
var SLOW_POLL_MS = 3e3;
|
|
36883
|
+
var FAST_PHASE_MS = 1e4;
|
|
36884
|
+
var RETRYING_NOTICE_AFTER_MS = 3 * 6e4;
|
|
36885
|
+
var sleep2 = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
36886
|
+
function classifyTurnFailureSince(opts) {
|
|
36887
|
+
const dir = opts.transcriptDir ?? agentTranscriptDir({ cwd: opts.cwd, home: opts.home });
|
|
36888
|
+
let entries;
|
|
36889
|
+
try {
|
|
36890
|
+
entries = readdirSync3(dir);
|
|
36891
|
+
} catch {
|
|
36892
|
+
return { result: UNKNOWN_TURN_FAILURE, coarse: 0, fine: 0, unrecognisedKeys: [] };
|
|
36893
|
+
}
|
|
36894
|
+
let newest = UNKNOWN_TURN_FAILURE;
|
|
36895
|
+
let coarse = 0;
|
|
36896
|
+
let fine = 0;
|
|
36897
|
+
const unrecognised = /* @__PURE__ */ new Set();
|
|
36898
|
+
for (const name of entries) {
|
|
36899
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
36900
|
+
const path = join8(dir, name);
|
|
36901
|
+
let fingerprint;
|
|
36902
|
+
try {
|
|
36903
|
+
const st = statSync2(path);
|
|
36904
|
+
if (!st.isFile() || st.mtimeMs < opts.sinceMs) continue;
|
|
36905
|
+
fingerprint = `${st.mtimeMs}:${st.size}`;
|
|
36906
|
+
} catch {
|
|
36907
|
+
continue;
|
|
36908
|
+
}
|
|
36909
|
+
const cached2 = opts.cache?.get(path);
|
|
36910
|
+
let scan;
|
|
36911
|
+
if (cached2 && cached2.fingerprint === fingerprint) {
|
|
36912
|
+
scan = cached2.scan;
|
|
36913
|
+
} else {
|
|
36914
|
+
let content;
|
|
36915
|
+
try {
|
|
36916
|
+
content = readFileSync7(path, "utf-8");
|
|
36917
|
+
} catch {
|
|
36918
|
+
continue;
|
|
36919
|
+
}
|
|
36920
|
+
const analysis = analyzeTranscriptTurnFailure(content, opts.sinceMs, opts.nowMs);
|
|
36921
|
+
scan = {
|
|
36922
|
+
result: analysis.result,
|
|
36923
|
+
coarse: analysis.coarse,
|
|
36924
|
+
fine: analysis.fine,
|
|
36925
|
+
unrecognisedKeys: analysis.unrecognisedKeys
|
|
36926
|
+
};
|
|
36927
|
+
opts.cache?.set(path, { fingerprint, scan });
|
|
36928
|
+
}
|
|
36929
|
+
newest = pickNewerTurnFailure(newest, scan.result);
|
|
36930
|
+
coarse += scan.coarse;
|
|
36931
|
+
fine += scan.fine;
|
|
36932
|
+
for (const key2 of scan.unrecognisedKeys) unrecognised.add(key2);
|
|
36933
|
+
}
|
|
36934
|
+
return { result: newest, coarse, fine, unrecognisedKeys: [...unrecognised].sort() };
|
|
36935
|
+
}
|
|
36936
|
+
function emitDriftTelemetryIfBlind(args) {
|
|
36937
|
+
if (args.coarse <= 0 || args.fine > 0) return;
|
|
36938
|
+
try {
|
|
36939
|
+
process.stderr.write(
|
|
36940
|
+
`agt.transcript.api_error.unclassified ${JSON.stringify({
|
|
36941
|
+
channel: args.channel,
|
|
36942
|
+
agent_code: process.env.AGT_AGENT_CODE_NAME ?? "unknown",
|
|
36943
|
+
coarse: args.coarse,
|
|
36944
|
+
keys: args.unrecognisedKeys.slice(0, 20)
|
|
36945
|
+
})}
|
|
36946
|
+
`
|
|
36947
|
+
);
|
|
36948
|
+
} catch {
|
|
36949
|
+
}
|
|
36950
|
+
}
|
|
36951
|
+
async function watchForTurnFailure(opts) {
|
|
36952
|
+
const now = opts.now ?? (() => Date.now());
|
|
36953
|
+
const wait = opts.wait ?? sleep2;
|
|
36954
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_FAILURE_WATCH_MS;
|
|
36955
|
+
const fastPollMs = opts.fastPollMs ?? FAST_POLL_MS;
|
|
36956
|
+
const slowPollMs = opts.slowPollMs ?? SLOW_POLL_MS;
|
|
36957
|
+
const fastPhaseMs = opts.fastPhaseMs ?? FAST_PHASE_MS;
|
|
36958
|
+
const retryingAfterMs = opts.retryingNoticeAfterMs ?? RETRYING_NOTICE_AFTER_MS;
|
|
36959
|
+
const startedAt = now();
|
|
36960
|
+
const deadline = startedAt + timeoutMs;
|
|
36961
|
+
let longRetryFired = false;
|
|
36962
|
+
let driftEmitted = false;
|
|
36963
|
+
const cache = /* @__PURE__ */ new Map();
|
|
36964
|
+
for (; ; ) {
|
|
36965
|
+
let scan;
|
|
36966
|
+
try {
|
|
36967
|
+
scan = classifyTurnFailureSince({
|
|
36968
|
+
sinceMs: opts.sinceMs,
|
|
36969
|
+
// No upper bound, deliberately. Two reasons, and the second is a
|
|
36970
|
+
// correctness requirement of the cache above:
|
|
36971
|
+
// 1. For a post-dispatch watch the question is "has anything since the
|
|
36972
|
+
// dispatch killed this turn?" — a future-dated entry is still an
|
|
36973
|
+
// answer, and rejecting it on clock skew would drop the notice.
|
|
36974
|
+
// 2. A window that widens each poll makes a cached scan unsound: an
|
|
36975
|
+
// entry stamped a hair ahead of our clock would be parsed as
|
|
36976
|
+
// out-of-window, cached as "not seen", and — because a DEAD turn
|
|
36977
|
+
// produces no further appends to invalidate the entry — never looked
|
|
36978
|
+
// at again. That is exactly the silence this feature exists to end.
|
|
36979
|
+
nowMs: Number.POSITIVE_INFINITY,
|
|
36980
|
+
transcriptDir: opts.transcriptDir,
|
|
36981
|
+
cwd: opts.cwd,
|
|
36982
|
+
home: opts.home,
|
|
36983
|
+
cache
|
|
36984
|
+
});
|
|
36985
|
+
} catch {
|
|
36986
|
+
return null;
|
|
36987
|
+
}
|
|
36988
|
+
if (!driftEmitted && scan.coarse > 0 && scan.fine === 0) {
|
|
36989
|
+
driftEmitted = true;
|
|
36990
|
+
emitDriftTelemetryIfBlind({
|
|
36991
|
+
channel: opts.channel ?? "unknown",
|
|
36992
|
+
coarse: scan.coarse,
|
|
36993
|
+
fine: scan.fine,
|
|
36994
|
+
unrecognisedKeys: scan.unrecognisedKeys
|
|
36995
|
+
});
|
|
36996
|
+
}
|
|
36997
|
+
const { result } = scan;
|
|
36998
|
+
if (result.outcome === "failed") return result;
|
|
36999
|
+
if (result.outcome === "served") return null;
|
|
37000
|
+
if (result.outcome === "retrying" && !longRetryFired && opts.onLongRetry && now() - startedAt >= retryingAfterMs) {
|
|
37001
|
+
longRetryFired = true;
|
|
37002
|
+
try {
|
|
37003
|
+
await opts.onLongRetry(result);
|
|
37004
|
+
} catch {
|
|
37005
|
+
}
|
|
37006
|
+
}
|
|
37007
|
+
if (now() >= deadline) return null;
|
|
37008
|
+
await wait(now() - startedAt < fastPhaseMs ? fastPollMs : slowPollMs);
|
|
37009
|
+
}
|
|
37010
|
+
}
|
|
37011
|
+
|
|
36709
37012
|
// src/usage-limit-reactive-decision.ts
|
|
36710
37013
|
import { createHash } from "crypto";
|
|
36711
37014
|
function shouldReadPredictiveMarker(mode) {
|
|
@@ -36732,7 +37035,7 @@ function describeUnparsedRefusal(text) {
|
|
|
36732
37035
|
import { execFile as execFile2 } from "child_process";
|
|
36733
37036
|
import { existsSync as existsSync3, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
36734
37037
|
import { homedir as homedir6 } from "os";
|
|
36735
|
-
import { join as
|
|
37038
|
+
import { join as join9 } from "path";
|
|
36736
37039
|
var DEFAULT_CLAUDE_EVAL_MODEL = "claude-haiku-4-5-20251001";
|
|
36737
37040
|
var DEFAULT_ANTHROPIC_MESSAGES_URL = "https://api.anthropic.com/v1/messages";
|
|
36738
37041
|
var ANTHROPIC_API_VERSION = "2023-06-01";
|
|
@@ -36831,12 +37134,12 @@ async function runAnthropicMessages(prompt, opts) {
|
|
|
36831
37134
|
var emptyMcpConfigPath = null;
|
|
36832
37135
|
function ensureEmptyMcpConfig() {
|
|
36833
37136
|
if (emptyMcpConfigPath && existsSync3(emptyMcpConfigPath)) return emptyMcpConfigPath;
|
|
36834
|
-
const dir =
|
|
37137
|
+
const dir = join9(homedir6(), ".augmented");
|
|
36835
37138
|
try {
|
|
36836
37139
|
mkdirSync(dir, { recursive: true });
|
|
36837
37140
|
} catch {
|
|
36838
37141
|
}
|
|
36839
|
-
const p2 =
|
|
37142
|
+
const p2 = join9(dir, ".reply-intent-empty-mcp.json");
|
|
36840
37143
|
writeFileSync2(p2, JSON.stringify({ mcpServers: {} }));
|
|
36841
37144
|
emptyMcpConfigPath = p2;
|
|
36842
37145
|
return p2;
|
|
@@ -36983,8 +37286,8 @@ function emitTransientApiErrorTelemetry(channel, match, original) {
|
|
|
36983
37286
|
}
|
|
36984
37287
|
|
|
36985
37288
|
// src/slack-pending-inbound-cleanup.ts
|
|
36986
|
-
import { existsSync as existsSync4, readdirSync as
|
|
36987
|
-
import { join as
|
|
37289
|
+
import { existsSync as existsSync4, readdirSync as readdirSync4, statSync as statSync3, unlinkSync } from "fs";
|
|
37290
|
+
import { join as join10 } from "path";
|
|
36988
37291
|
function sanitizeMarkerSegment(value) {
|
|
36989
37292
|
return value.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
36990
37293
|
}
|
|
@@ -36998,9 +37301,9 @@ function applyToMatchingMarkers(dir, prefix, suffix, op) {
|
|
|
36998
37301
|
if (!dir) return 0;
|
|
36999
37302
|
let applied = 0;
|
|
37000
37303
|
try {
|
|
37001
|
-
for (const f of
|
|
37304
|
+
for (const f of readdirSync4(dir)) {
|
|
37002
37305
|
if (!f.startsWith(prefix) || !f.endsWith(suffix)) continue;
|
|
37003
|
-
op(
|
|
37306
|
+
op(join10(dir, f));
|
|
37004
37307
|
applied += 1;
|
|
37005
37308
|
}
|
|
37006
37309
|
} catch {
|
|
@@ -37029,11 +37332,11 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
|
|
|
37029
37332
|
if (!dir) return null;
|
|
37030
37333
|
const channelPrefix = `${sanitizeMarkerSegment(channel)}__`;
|
|
37031
37334
|
try {
|
|
37032
|
-
const entries =
|
|
37033
|
-
const full =
|
|
37335
|
+
const entries = readdirSync4(dir).filter((f) => f.startsWith(channelPrefix) && f.endsWith(".json")).map((f) => {
|
|
37336
|
+
const full = join10(dir, f);
|
|
37034
37337
|
let mtime = 0;
|
|
37035
37338
|
try {
|
|
37036
|
-
mtime =
|
|
37339
|
+
mtime = statSync3(full).mtimeMs;
|
|
37037
37340
|
} catch {
|
|
37038
37341
|
}
|
|
37039
37342
|
return { name: f, full, mtime };
|
|
@@ -37049,12 +37352,12 @@ function clearOldestSlackPendingMarkerInChannel(dir, channel, clear = defaultCle
|
|
|
37049
37352
|
|
|
37050
37353
|
// src/recovery-ledger.ts
|
|
37051
37354
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
37052
|
-
import { join as
|
|
37355
|
+
import { join as join11 } from "path";
|
|
37053
37356
|
function recoveryLedgerEntryExists(ledgerDir, markerName, exists = (p2) => existsSync5(p2)) {
|
|
37054
37357
|
if (!ledgerDir || !markerName) return false;
|
|
37055
37358
|
if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return false;
|
|
37056
37359
|
try {
|
|
37057
|
-
return exists(
|
|
37360
|
+
return exists(join11(ledgerDir, markerName));
|
|
37058
37361
|
} catch {
|
|
37059
37362
|
return false;
|
|
37060
37363
|
}
|
|
@@ -37065,7 +37368,7 @@ function removeRecoveryLedgerEntry(ledgerDir, markerName, unlink = (p2) => {
|
|
|
37065
37368
|
if (!ledgerDir || !markerName) return;
|
|
37066
37369
|
if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
|
|
37067
37370
|
try {
|
|
37068
|
-
unlink(
|
|
37371
|
+
unlink(join11(ledgerDir, markerName));
|
|
37069
37372
|
} catch {
|
|
37070
37373
|
}
|
|
37071
37374
|
}
|
|
@@ -37302,18 +37605,18 @@ function applyHotThreadGuard(input) {
|
|
|
37302
37605
|
}
|
|
37303
37606
|
|
|
37304
37607
|
// src/slack-hot-thread-telemetry.ts
|
|
37305
|
-
import { readFileSync as
|
|
37306
|
-
import { join as
|
|
37608
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "fs";
|
|
37609
|
+
import { join as join12 } from "path";
|
|
37307
37610
|
var HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX = "-hot-thread-classifications.json";
|
|
37308
37611
|
function hotThreadKey(mode, outcome, proactive) {
|
|
37309
37612
|
return `${mode}|${outcome}|${proactive ? "true" : "false"}`;
|
|
37310
37613
|
}
|
|
37311
37614
|
function recordHotThreadClassification(agentDir, channel, classification) {
|
|
37312
37615
|
if (!agentDir || !channel) return;
|
|
37313
|
-
const path =
|
|
37616
|
+
const path = join12(agentDir, `${channel}${HOT_THREAD_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
37314
37617
|
let counts = {};
|
|
37315
37618
|
try {
|
|
37316
|
-
const parsed = JSON.parse(
|
|
37619
|
+
const parsed = JSON.parse(readFileSync8(path, "utf-8"));
|
|
37317
37620
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
37318
37621
|
for (const [k, v] of Object.entries(parsed)) {
|
|
37319
37622
|
if (typeof v === "number" && Number.isInteger(v) && v >= 0) counts[k] = v;
|
|
@@ -37330,7 +37633,7 @@ function recordHotThreadClassification(agentDir, channel, classification) {
|
|
|
37330
37633
|
}
|
|
37331
37634
|
|
|
37332
37635
|
// src/restart-confirm.ts
|
|
37333
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as
|
|
37636
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync9, renameSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
37334
37637
|
import { dirname } from "path";
|
|
37335
37638
|
import { randomUUID } from "crypto";
|
|
37336
37639
|
var RESTART_CONFIRM_MAX_AGE_MS = 10 * 60 * 1e3;
|
|
@@ -37356,7 +37659,7 @@ function writeRestartConfirmMarker(filePath, marker) {
|
|
|
37356
37659
|
function readRestartConfirmMarker(filePath) {
|
|
37357
37660
|
try {
|
|
37358
37661
|
if (!existsSync6(filePath)) return null;
|
|
37359
|
-
const parsed = JSON.parse(
|
|
37662
|
+
const parsed = JSON.parse(readFileSync9(filePath, "utf8"));
|
|
37360
37663
|
if (!parsed || typeof parsed !== "object") return null;
|
|
37361
37664
|
return parsed;
|
|
37362
37665
|
} catch {
|
|
@@ -37501,21 +37804,21 @@ import {
|
|
|
37501
37804
|
ftruncateSync,
|
|
37502
37805
|
mkdirSync as mkdirSync9,
|
|
37503
37806
|
openSync,
|
|
37504
|
-
readFileSync as
|
|
37505
|
-
readdirSync as
|
|
37807
|
+
readFileSync as readFileSync21,
|
|
37808
|
+
readdirSync as readdirSync7,
|
|
37506
37809
|
renameSync as renameSync5,
|
|
37507
|
-
statSync as
|
|
37810
|
+
statSync as statSync5,
|
|
37508
37811
|
unlinkSync as unlinkSync7,
|
|
37509
37812
|
watch,
|
|
37510
37813
|
writeFileSync as writeFileSync14,
|
|
37511
37814
|
writeSync
|
|
37512
37815
|
} from "fs";
|
|
37513
|
-
import { basename, join as
|
|
37816
|
+
import { basename, join as join21, resolve as resolve2 } from "path";
|
|
37514
37817
|
import { homedir as homedir7 } from "os";
|
|
37515
37818
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
|
|
37516
37819
|
|
|
37517
37820
|
// src/slack-thread-store.ts
|
|
37518
|
-
import { mkdirSync as mkdirSync3, readFileSync as
|
|
37821
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
|
|
37519
37822
|
import { dirname as dirname2 } from "path";
|
|
37520
37823
|
function isParticipatingThread(entry) {
|
|
37521
37824
|
if (!entry) return false;
|
|
@@ -37530,7 +37833,7 @@ function loadThreadStore(filePath, opts = {}) {
|
|
|
37530
37833
|
const ttlMs = ttlDays * 24 * 60 * 60 * 1e3;
|
|
37531
37834
|
let raw;
|
|
37532
37835
|
try {
|
|
37533
|
-
raw =
|
|
37836
|
+
raw = readFileSync10(filePath, "utf-8");
|
|
37534
37837
|
} catch {
|
|
37535
37838
|
return { threads: /* @__PURE__ */ new Map(), pruned: 0 };
|
|
37536
37839
|
}
|
|
@@ -37631,7 +37934,7 @@ function isThreadEntry(value) {
|
|
|
37631
37934
|
}
|
|
37632
37935
|
|
|
37633
37936
|
// src/dm-restart-notice.ts
|
|
37634
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
37937
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
37635
37938
|
import { dirname as dirname3 } from "path";
|
|
37636
37939
|
var RECENT_DM_VERSION = 1;
|
|
37637
37940
|
var DEFAULT_RECENT_DM_TTL_MS = 30 * 60 * 1e3;
|
|
@@ -37655,7 +37958,7 @@ function loadRecentDms(filePath, opts = {}) {
|
|
|
37655
37958
|
const ttlMs = opts.ttlMs ?? DEFAULT_RECENT_DM_TTL_MS;
|
|
37656
37959
|
let raw;
|
|
37657
37960
|
try {
|
|
37658
|
-
raw =
|
|
37961
|
+
raw = readFileSync11(filePath, "utf-8");
|
|
37659
37962
|
} catch (err) {
|
|
37660
37963
|
const code = err.code;
|
|
37661
37964
|
if (code !== "ENOENT") {
|
|
@@ -37740,7 +38043,7 @@ var CHANNEL_ADD_RESTART_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
|
37740
38043
|
function readChannelAddRestartMarker(filePath) {
|
|
37741
38044
|
let raw;
|
|
37742
38045
|
try {
|
|
37743
|
-
raw =
|
|
38046
|
+
raw = readFileSync11(filePath, "utf-8");
|
|
37744
38047
|
} catch {
|
|
37745
38048
|
return null;
|
|
37746
38049
|
}
|
|
@@ -37798,13 +38101,13 @@ async function runOrRetry(fn, opts) {
|
|
|
37798
38101
|
}
|
|
37799
38102
|
|
|
37800
38103
|
// src/turn-initiator-marker.ts
|
|
37801
|
-
import { writeFileSync as writeFileSync7, readFileSync as
|
|
37802
|
-
import { dirname as dirname4, join as
|
|
38104
|
+
import { writeFileSync as writeFileSync7, readFileSync as readFileSync12, mkdirSync as mkdirSync5, renameSync as renameSync2 } from "fs";
|
|
38105
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
37803
38106
|
var TURN_INITIATOR_MAX_AGE_MS = 5 * 60 * 1e3;
|
|
37804
38107
|
var TURN_INITIATOR_LEDGER_MAX_ENTRIES = 20;
|
|
37805
38108
|
var TURN_INITIATOR_LEDGER_FILENAME = ".turn-initiator-ledger.json";
|
|
37806
38109
|
function turnInitiatorLedgerPath(singleSlotFile) {
|
|
37807
|
-
return
|
|
38110
|
+
return join13(dirname4(singleSlotFile), TURN_INITIATOR_LEDGER_FILENAME);
|
|
37808
38111
|
}
|
|
37809
38112
|
function foldTurnInitiatorLedger(existing, marker, maxAgeMs = TURN_INITIATOR_MAX_AGE_MS, maxEntries = TURN_INITIATOR_LEDGER_MAX_ENTRIES) {
|
|
37810
38113
|
const now = marker.ts;
|
|
@@ -37829,7 +38132,7 @@ function updateTurnInitiatorLedger(singleSlotFile, marker) {
|
|
|
37829
38132
|
const ledgerFile = turnInitiatorLedgerPath(singleSlotFile);
|
|
37830
38133
|
let existing = null;
|
|
37831
38134
|
try {
|
|
37832
|
-
const parsed = JSON.parse(
|
|
38135
|
+
const parsed = JSON.parse(readFileSync12(ledgerFile, "utf8"));
|
|
37833
38136
|
if (parsed && parsed.v === 1 && Array.isArray(parsed.entries)) existing = parsed;
|
|
37834
38137
|
} catch {
|
|
37835
38138
|
}
|
|
@@ -37856,7 +38159,7 @@ function writeTurnInitiatorMarker(input) {
|
|
|
37856
38159
|
}
|
|
37857
38160
|
|
|
37858
38161
|
// src/slack-bot-photo.ts
|
|
37859
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as
|
|
38162
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
|
|
37860
38163
|
import { dirname as dirname5 } from "path";
|
|
37861
38164
|
async function applyBotPhoto(opts) {
|
|
37862
38165
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
@@ -37866,7 +38169,7 @@ async function applyBotPhoto(opts) {
|
|
|
37866
38169
|
const { token, avatarUrl, markerPath } = opts;
|
|
37867
38170
|
if (markerPath && existsSync7(markerPath)) {
|
|
37868
38171
|
try {
|
|
37869
|
-
if (
|
|
38172
|
+
if (readFileSync13(markerPath, "utf-8").trim() === avatarUrl) {
|
|
37870
38173
|
return { status: "skipped-unchanged" };
|
|
37871
38174
|
}
|
|
37872
38175
|
} catch {
|
|
@@ -37991,8 +38294,8 @@ function conversationalLaneMeta(expectsReply = true) {
|
|
|
37991
38294
|
}
|
|
37992
38295
|
|
|
37993
38296
|
// src/inbound-lane-telemetry.ts
|
|
37994
|
-
import { readFileSync as
|
|
37995
|
-
import { join as
|
|
38297
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "fs";
|
|
38298
|
+
import { join as join14 } from "path";
|
|
37996
38299
|
var LANE_CLASSIFICATION_COUNTER_SUFFIX = "-lane-classifications.json";
|
|
37997
38300
|
var SUSPECTED_MISCLASSIFICATION_KEY = "suspected_misclassification";
|
|
37998
38301
|
var HUMAN_CHANNEL_SOURCES = /* @__PURE__ */ new Set([
|
|
@@ -38009,10 +38312,10 @@ function isSuspectedMisclassification(lane, source) {
|
|
|
38009
38312
|
}
|
|
38010
38313
|
function recordLaneClassification(agentDir, channel, classification) {
|
|
38011
38314
|
if (!agentDir) return;
|
|
38012
|
-
const path =
|
|
38315
|
+
const path = join14(agentDir, `${channel}${LANE_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
38013
38316
|
let counts = {};
|
|
38014
38317
|
try {
|
|
38015
|
-
const parsed = JSON.parse(
|
|
38318
|
+
const parsed = JSON.parse(readFileSync14(path, "utf-8"));
|
|
38016
38319
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
38017
38320
|
} catch {
|
|
38018
38321
|
}
|
|
@@ -38028,8 +38331,8 @@ function recordLaneClassification(agentDir, channel, classification) {
|
|
|
38028
38331
|
}
|
|
38029
38332
|
|
|
38030
38333
|
// src/slack-inbound-registry.ts
|
|
38031
|
-
import { readdirSync as
|
|
38032
|
-
import { join as
|
|
38334
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync15 } from "fs";
|
|
38335
|
+
import { join as join15 } from "path";
|
|
38033
38336
|
var DEFAULT_MAX_ENTRIES = 500;
|
|
38034
38337
|
var DEFAULT_CLEARED_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
38035
38338
|
function entryKey(channel, messageTs) {
|
|
@@ -38141,7 +38444,7 @@ function createInboundRegistry(opts = {}) {
|
|
|
38141
38444
|
function seedFromMarkerDir(dir) {
|
|
38142
38445
|
let names;
|
|
38143
38446
|
try {
|
|
38144
|
-
names =
|
|
38447
|
+
names = readdirSync5(dir);
|
|
38145
38448
|
} catch {
|
|
38146
38449
|
return;
|
|
38147
38450
|
}
|
|
@@ -38150,7 +38453,7 @@ function createInboundRegistry(opts = {}) {
|
|
|
38150
38453
|
if (name.includes(".retry-") || name.includes(".poison")) continue;
|
|
38151
38454
|
let marker;
|
|
38152
38455
|
try {
|
|
38153
|
-
marker = JSON.parse(
|
|
38456
|
+
marker = JSON.parse(readFileSync15(join15(dir, name), "utf-8"));
|
|
38154
38457
|
} catch {
|
|
38155
38458
|
continue;
|
|
38156
38459
|
}
|
|
@@ -38195,8 +38498,8 @@ function slackInboundId(channel, threadTs, messageTs) {
|
|
|
38195
38498
|
}
|
|
38196
38499
|
|
|
38197
38500
|
// src/inbound-delivery-ledger.ts
|
|
38198
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as
|
|
38199
|
-
import { join as
|
|
38501
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as readdirSync6, readFileSync as readFileSync16, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
38502
|
+
import { join as join16 } from "path";
|
|
38200
38503
|
function safeInboundId(inboundId) {
|
|
38201
38504
|
return inboundId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
38202
38505
|
}
|
|
@@ -38204,8 +38507,8 @@ var defaultDeps = {
|
|
|
38204
38507
|
mkdir: (dir) => mkdirSync7(dir, { recursive: true }),
|
|
38205
38508
|
writeFile: (path, data) => writeFileSync10(path, data, "utf8"),
|
|
38206
38509
|
rename: (from, to) => renameSync3(from, to),
|
|
38207
|
-
readdir: (dir) =>
|
|
38208
|
-
readFile: (path) =>
|
|
38510
|
+
readdir: (dir) => readdirSync6(dir),
|
|
38511
|
+
readFile: (path) => readFileSync16(path, "utf8"),
|
|
38209
38512
|
exists: (path) => existsSync8(path)
|
|
38210
38513
|
};
|
|
38211
38514
|
function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
|
|
@@ -38214,7 +38517,7 @@ function writeInboundDeliveryLedgerEntry(dir, record2, deps = defaultDeps) {
|
|
|
38214
38517
|
if (!safe || safe.includes("/") || safe.includes("\\") || safe.includes("..")) return;
|
|
38215
38518
|
try {
|
|
38216
38519
|
deps.mkdir(dir);
|
|
38217
|
-
const final =
|
|
38520
|
+
const final = join16(dir, `${safe}.json`);
|
|
38218
38521
|
const tmp = `${final}.tmp`;
|
|
38219
38522
|
deps.writeFile(tmp, JSON.stringify(record2));
|
|
38220
38523
|
deps.rename(tmp, final);
|
|
@@ -38370,8 +38673,8 @@ function describeChannelRedirect(input) {
|
|
|
38370
38673
|
}
|
|
38371
38674
|
|
|
38372
38675
|
// src/slack-reply-binding-telemetry.ts
|
|
38373
|
-
import { readFileSync as
|
|
38374
|
-
import { join as
|
|
38676
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync11 } from "fs";
|
|
38677
|
+
import { join as join17 } from "path";
|
|
38375
38678
|
var REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX = "-reply-binding-classifications.json";
|
|
38376
38679
|
var UNKNOWN_INBOUND_ID_KEY = "unknown_inbound_id";
|
|
38377
38680
|
var CHANNEL_MISTARGET_CORRECTED_KEY = "channel_mistarget_corrected";
|
|
@@ -38386,10 +38689,10 @@ function slackReplyBindingMode() {
|
|
|
38386
38689
|
}
|
|
38387
38690
|
function recordReplyBindingClassification(agentDir, channel, input) {
|
|
38388
38691
|
if (!agentDir) return;
|
|
38389
|
-
const path =
|
|
38692
|
+
const path = join17(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
38390
38693
|
let counts = {};
|
|
38391
38694
|
try {
|
|
38392
|
-
const parsed = JSON.parse(
|
|
38695
|
+
const parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
38393
38696
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
38394
38697
|
} catch {
|
|
38395
38698
|
}
|
|
@@ -38404,10 +38707,10 @@ function recordReplyBindingClassification(agentDir, channel, input) {
|
|
|
38404
38707
|
}
|
|
38405
38708
|
function recordScheduledChannelOverride(agentDir, channel, input) {
|
|
38406
38709
|
if (!agentDir) return;
|
|
38407
|
-
const path =
|
|
38710
|
+
const path = join17(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
38408
38711
|
let counts = {};
|
|
38409
38712
|
try {
|
|
38410
|
-
const parsed = JSON.parse(
|
|
38713
|
+
const parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
38411
38714
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
38412
38715
|
} catch {
|
|
38413
38716
|
}
|
|
@@ -38420,10 +38723,10 @@ function recordScheduledChannelOverride(agentDir, channel, input) {
|
|
|
38420
38723
|
}
|
|
38421
38724
|
function recordChannelMistarget(agentDir, channel, input) {
|
|
38422
38725
|
if (!agentDir) return;
|
|
38423
|
-
const path =
|
|
38726
|
+
const path = join17(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
38424
38727
|
let counts = {};
|
|
38425
38728
|
try {
|
|
38426
|
-
const parsed = JSON.parse(
|
|
38729
|
+
const parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
38427
38730
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
38428
38731
|
} catch {
|
|
38429
38732
|
}
|
|
@@ -38438,8 +38741,8 @@ function recordChannelMistarget(agentDir, channel, input) {
|
|
|
38438
38741
|
}
|
|
38439
38742
|
|
|
38440
38743
|
// src/slack-reply-target-telemetry.ts
|
|
38441
|
-
import { readFileSync as
|
|
38442
|
-
import { join as
|
|
38744
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "fs";
|
|
38745
|
+
import { join as join18 } from "path";
|
|
38443
38746
|
var REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX = "-reply-target-classifications.json";
|
|
38444
38747
|
function pendingThreadsBucket(n) {
|
|
38445
38748
|
if (n <= 0) return "0";
|
|
@@ -38472,10 +38775,10 @@ function classifyReplyTarget(input) {
|
|
|
38472
38775
|
}
|
|
38473
38776
|
function recordReplyTargetClassification(agentDir, channel, classification) {
|
|
38474
38777
|
if (!agentDir) return;
|
|
38475
|
-
const path =
|
|
38778
|
+
const path = join18(agentDir, `${channel}${REPLY_TARGET_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
38476
38779
|
let counts = {};
|
|
38477
38780
|
try {
|
|
38478
|
-
const parsed = JSON.parse(
|
|
38781
|
+
const parsed = JSON.parse(readFileSync18(path, "utf-8"));
|
|
38479
38782
|
if (parsed && typeof parsed === "object") counts = parsed;
|
|
38480
38783
|
} catch {
|
|
38481
38784
|
}
|
|
@@ -38491,8 +38794,8 @@ function recordReplyTargetClassification(agentDir, channel, classification) {
|
|
|
38491
38794
|
}
|
|
38492
38795
|
|
|
38493
38796
|
// src/scheduled-turn-marker.ts
|
|
38494
|
-
import { readFileSync as
|
|
38495
|
-
import { join as
|
|
38797
|
+
import { readFileSync as readFileSync19, unlinkSync as unlinkSync5 } from "fs";
|
|
38798
|
+
import { join as join19 } from "path";
|
|
38496
38799
|
var SCHEDULED_TURN_MARKER_FILENAME2 = ".current-scheduled-turn.json";
|
|
38497
38800
|
var SCHEDULED_TURN_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
38498
38801
|
function validateScheduledTurnMarker(raw, now, maxAgeMs = SCHEDULED_TURN_MAX_AGE_MS) {
|
|
@@ -38530,7 +38833,7 @@ function readScheduledTurnMarker(agentDir, now = Date.now()) {
|
|
|
38530
38833
|
if (!agentDir) return null;
|
|
38531
38834
|
try {
|
|
38532
38835
|
const raw = JSON.parse(
|
|
38533
|
-
|
|
38836
|
+
readFileSync19(join19(agentDir, SCHEDULED_TURN_MARKER_FILENAME2), "utf8")
|
|
38534
38837
|
);
|
|
38535
38838
|
return validateScheduledTurnMarker(raw, now);
|
|
38536
38839
|
} catch {
|
|
@@ -38540,7 +38843,7 @@ function readScheduledTurnMarker(agentDir, now = Date.now()) {
|
|
|
38540
38843
|
function clearScheduledTurnMarker(agentDir) {
|
|
38541
38844
|
if (!agentDir) return;
|
|
38542
38845
|
try {
|
|
38543
|
-
unlinkSync5(
|
|
38846
|
+
unlinkSync5(join19(agentDir, SCHEDULED_TURN_MARKER_FILENAME2));
|
|
38544
38847
|
} catch {
|
|
38545
38848
|
}
|
|
38546
38849
|
}
|
|
@@ -39338,14 +39641,14 @@ async function actuateHostRestart(opts) {
|
|
|
39338
39641
|
import {
|
|
39339
39642
|
existsSync as existsSync9,
|
|
39340
39643
|
mkdirSync as mkdirSync8,
|
|
39341
|
-
readFileSync as
|
|
39644
|
+
readFileSync as readFileSync20,
|
|
39342
39645
|
renameSync as renameSync4,
|
|
39343
|
-
statSync as
|
|
39646
|
+
statSync as statSync4,
|
|
39344
39647
|
unlinkSync as unlinkSync6,
|
|
39345
39648
|
utimesSync,
|
|
39346
39649
|
writeFileSync as writeFileSync13
|
|
39347
39650
|
} from "fs";
|
|
39348
|
-
import { join as
|
|
39651
|
+
import { join as join20 } from "path";
|
|
39349
39652
|
var STALE_LOCK_MS = 9e4;
|
|
39350
39653
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
39351
39654
|
function defaultIsPidAlive(pid) {
|
|
@@ -39368,7 +39671,7 @@ function acquireMcpSpawnLock(args) {
|
|
|
39368
39671
|
const nowMs = options.nowMs ?? (() => Date.now());
|
|
39369
39672
|
const lockMtimeMs = options.lockMtimeMs ?? defaultLockMtimeMs;
|
|
39370
39673
|
const staleMs = options.staleMs ?? STALE_LOCK_MS;
|
|
39371
|
-
const path =
|
|
39674
|
+
const path = join20(agentDir, basename2);
|
|
39372
39675
|
const existing = readLockHolder(path);
|
|
39373
39676
|
if (existing) {
|
|
39374
39677
|
if (existing.pid === selfPid) {
|
|
@@ -39427,7 +39730,7 @@ function startMcpSpawnLockHeartbeat(lockPath, opts = {}) {
|
|
|
39427
39730
|
}
|
|
39428
39731
|
function defaultLockMtimeMs(path) {
|
|
39429
39732
|
try {
|
|
39430
|
-
return
|
|
39733
|
+
return statSync4(path).mtimeMs;
|
|
39431
39734
|
} catch {
|
|
39432
39735
|
return null;
|
|
39433
39736
|
}
|
|
@@ -39435,7 +39738,7 @@ function defaultLockMtimeMs(path) {
|
|
|
39435
39738
|
function readLockHolder(path) {
|
|
39436
39739
|
if (!existsSync9(path)) return null;
|
|
39437
39740
|
try {
|
|
39438
|
-
const raw =
|
|
39741
|
+
const raw = readFileSync20(path, "utf8");
|
|
39439
39742
|
const parsed = JSON.parse(raw);
|
|
39440
39743
|
const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
|
|
39441
39744
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
@@ -39884,18 +40187,18 @@ var SLACK_TEAM_PEER_USER_IDS = parseTeamPeerUserIdsEnv(
|
|
|
39884
40187
|
process.env.SLACK_TEAM_PEER_USER_IDS
|
|
39885
40188
|
);
|
|
39886
40189
|
var PEER_HINT_SEEN = /* @__PURE__ */ new Set();
|
|
39887
|
-
var SLACK_AGENT_DIR = AGENT_CODE_NAME ?
|
|
39888
|
-
var SLACK_MCP_CONFIG_PATH = SLACK_AGENT_DIR ?
|
|
40190
|
+
var SLACK_AGENT_DIR = AGENT_CODE_NAME ? join21(homedir7(), ".augmented", AGENT_CODE_NAME) : null;
|
|
40191
|
+
var SLACK_MCP_CONFIG_PATH = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "project", ".mcp.json") : null;
|
|
39889
40192
|
var liveAllowedUsersCache = null;
|
|
39890
40193
|
function readLiveAllowedUsers() {
|
|
39891
40194
|
if (!SLACK_MCP_CONFIG_PATH) return null;
|
|
39892
40195
|
try {
|
|
39893
|
-
const mtimeMs =
|
|
40196
|
+
const mtimeMs = statSync5(SLACK_MCP_CONFIG_PATH).mtimeMs;
|
|
39894
40197
|
if (liveAllowedUsersCache && liveAllowedUsersCache.mtimeMs === mtimeMs) {
|
|
39895
40198
|
return liveAllowedUsersCache.value;
|
|
39896
40199
|
}
|
|
39897
40200
|
const value = extractAllowedUsersFromMcpJson(
|
|
39898
|
-
|
|
40201
|
+
readFileSync21(SLACK_MCP_CONFIG_PATH, "utf-8")
|
|
39899
40202
|
);
|
|
39900
40203
|
if (value === null) return null;
|
|
39901
40204
|
liveAllowedUsersCache = { mtimeMs, value };
|
|
@@ -39911,12 +40214,12 @@ var livePingAllowedUsersCache = null;
|
|
|
39911
40214
|
function readLivePingAllowedUsers() {
|
|
39912
40215
|
if (!SLACK_MCP_CONFIG_PATH) return null;
|
|
39913
40216
|
try {
|
|
39914
|
-
const mtimeMs =
|
|
40217
|
+
const mtimeMs = statSync5(SLACK_MCP_CONFIG_PATH).mtimeMs;
|
|
39915
40218
|
if (livePingAllowedUsersCache && livePingAllowedUsersCache.mtimeMs === mtimeMs) {
|
|
39916
40219
|
return livePingAllowedUsersCache.value;
|
|
39917
40220
|
}
|
|
39918
40221
|
const value = extractPingAllowedUsersFromMcpJson(
|
|
39919
|
-
|
|
40222
|
+
readFileSync21(SLACK_MCP_CONFIG_PATH, "utf-8")
|
|
39920
40223
|
);
|
|
39921
40224
|
if (value === null) return null;
|
|
39922
40225
|
livePingAllowedUsersCache = { mtimeMs, value };
|
|
@@ -39928,17 +40231,17 @@ function readLivePingAllowedUsers() {
|
|
|
39928
40231
|
function getEffectivePingAllowedUsers() {
|
|
39929
40232
|
return readLivePingAllowedUsers() ?? PING_ALLOWED_USERS;
|
|
39930
40233
|
}
|
|
39931
|
-
var SLACK_PENDING_INBOUND_DIR = SLACK_AGENT_DIR ?
|
|
39932
|
-
var SLACK_RESTART_CONTEXT_DIR = SLACK_AGENT_DIR ?
|
|
39933
|
-
var SLACK_RECOVERY_OUTBOX_DIR = SLACK_AGENT_DIR ?
|
|
39934
|
-
var SLACK_RECOVERY_LEDGER_DIR = SLACK_AGENT_DIR ?
|
|
39935
|
-
var SLACK_DELIVERY_LEDGER_DIR = SLACK_AGENT_DIR ?
|
|
40234
|
+
var SLACK_PENDING_INBOUND_DIR = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-pending-inbound") : null;
|
|
40235
|
+
var SLACK_RESTART_CONTEXT_DIR = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-restart-context") : null;
|
|
40236
|
+
var SLACK_RECOVERY_OUTBOX_DIR = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-recovery-outbox") : null;
|
|
40237
|
+
var SLACK_RECOVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, ".agt-slack-recovery-ledger") : null;
|
|
40238
|
+
var SLACK_DELIVERY_LEDGER_DIR = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, ".agt-inbound-delivery-ledger") : null;
|
|
39936
40239
|
var slackInboundRegistry = createInboundRegistry();
|
|
39937
|
-
var SLACK_RESTART_CONFIRM_FILE = SLACK_AGENT_DIR ?
|
|
39938
|
-
var SLACK_RECENT_DMS_FILE = SLACK_AGENT_DIR ?
|
|
39939
|
-
var SLACK_CHANNEL_ADD_RESTART_FILE = SLACK_AGENT_DIR ?
|
|
40240
|
+
var SLACK_RESTART_CONFIRM_FILE = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-restart-confirm.json") : null;
|
|
40241
|
+
var SLACK_RECENT_DMS_FILE = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-recent-dms.json") : null;
|
|
40242
|
+
var SLACK_CHANNEL_ADD_RESTART_FILE = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-channel-add-restart.json") : null;
|
|
39940
40243
|
var SLACK_MAX_RECOVERY_ATTEMPTS = 3;
|
|
39941
|
-
var SLACK_AVATAR_MARKER_PATH = SLACK_AGENT_DIR ?
|
|
40244
|
+
var SLACK_AVATAR_MARKER_PATH = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-avatar-applied") : null;
|
|
39942
40245
|
function redactSlackId(id) {
|
|
39943
40246
|
if (!id) return "<none>";
|
|
39944
40247
|
return createHash3("sha256").update(id).digest("hex").slice(0, 8);
|
|
@@ -39949,7 +40252,7 @@ function safeSlackMarkerName(channel, threadTs, messageTs) {
|
|
|
39949
40252
|
}
|
|
39950
40253
|
function slackPendingInboundPath(channel, threadTs, messageTs) {
|
|
39951
40254
|
if (!SLACK_PENDING_INBOUND_DIR) return null;
|
|
39952
|
-
return
|
|
40255
|
+
return join21(SLACK_PENDING_INBOUND_DIR, safeSlackMarkerName(channel, threadTs, messageTs));
|
|
39953
40256
|
}
|
|
39954
40257
|
function writeSlackPendingInboundMarker(channel, threadTs, messageTs, undeliverable = false, discretionary = false, payload) {
|
|
39955
40258
|
const path = slackPendingInboundPath(channel, threadTs, messageTs);
|
|
@@ -40000,7 +40303,7 @@ function rewriteSlackMarkerInPlace(path, marker) {
|
|
|
40000
40303
|
function markSlackMarkerSeenInPlace(fullPath) {
|
|
40001
40304
|
let marker;
|
|
40002
40305
|
try {
|
|
40003
|
-
marker = JSON.parse(
|
|
40306
|
+
marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40004
40307
|
} catch {
|
|
40005
40308
|
return;
|
|
40006
40309
|
}
|
|
@@ -40014,7 +40317,7 @@ function attachSlackReplayPayload(channel, threadTs, messageTs, payload) {
|
|
|
40014
40317
|
if (!path) return;
|
|
40015
40318
|
let marker;
|
|
40016
40319
|
try {
|
|
40017
|
-
marker = JSON.parse(
|
|
40320
|
+
marker = JSON.parse(readFileSync21(path, "utf-8"));
|
|
40018
40321
|
} catch {
|
|
40019
40322
|
return;
|
|
40020
40323
|
}
|
|
@@ -40025,7 +40328,7 @@ function readSlackPendingInboundMarker(channel, threadTs, messageTs) {
|
|
|
40025
40328
|
const path = slackPendingInboundPath(channel, threadTs, messageTs);
|
|
40026
40329
|
if (!path || !existsSync10(path)) return null;
|
|
40027
40330
|
try {
|
|
40028
|
-
return JSON.parse(
|
|
40331
|
+
return JSON.parse(readFileSync21(path, "utf-8"));
|
|
40029
40332
|
} catch {
|
|
40030
40333
|
return null;
|
|
40031
40334
|
}
|
|
@@ -40141,7 +40444,7 @@ function scheduleBusyAck(channel, threadTs, messageTs, isThreadReply, arrivedWhi
|
|
|
40141
40444
|
let paneLogFreshAgeMs = null;
|
|
40142
40445
|
if (SLACK_AGENT_DIR) {
|
|
40143
40446
|
try {
|
|
40144
|
-
const paneMtimeMs =
|
|
40447
|
+
const paneMtimeMs = statSync5(join21(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
|
|
40145
40448
|
paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
|
|
40146
40449
|
} catch {
|
|
40147
40450
|
}
|
|
@@ -40174,7 +40477,7 @@ function __resetSlackBusyAckNoticeThrottle() {
|
|
|
40174
40477
|
function clearSlackMarkerFileWithHeal(fullPath) {
|
|
40175
40478
|
let marker = null;
|
|
40176
40479
|
try {
|
|
40177
|
-
marker = JSON.parse(
|
|
40480
|
+
marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40178
40481
|
} catch {
|
|
40179
40482
|
}
|
|
40180
40483
|
if (marker && decideRecoveryHeal({
|
|
@@ -40192,7 +40495,7 @@ function clearSlackMarkerFileWithHeal(fullPath) {
|
|
|
40192
40495
|
function markSlackMarkerSeenWithHeal(fullPath) {
|
|
40193
40496
|
let marker = null;
|
|
40194
40497
|
try {
|
|
40195
|
-
marker = JSON.parse(
|
|
40498
|
+
marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40196
40499
|
} catch {
|
|
40197
40500
|
return;
|
|
40198
40501
|
}
|
|
@@ -40261,10 +40564,10 @@ function slackNextRetryName(filename) {
|
|
|
40261
40564
|
async function processSlackRecoveryOutboxFile(filename) {
|
|
40262
40565
|
if (!SLACK_RECOVERY_OUTBOX_DIR) return;
|
|
40263
40566
|
if (filename.endsWith(".poison.json") || filename.endsWith(".tmp")) return;
|
|
40264
|
-
const fullPath =
|
|
40567
|
+
const fullPath = join21(SLACK_RECOVERY_OUTBOX_DIR, filename);
|
|
40265
40568
|
let payload;
|
|
40266
40569
|
try {
|
|
40267
|
-
payload = JSON.parse(
|
|
40570
|
+
payload = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40268
40571
|
} catch (err) {
|
|
40269
40572
|
process.stderr.write(
|
|
40270
40573
|
`slack-channel(${AGENT_CODE_NAME}): recovery outbox parse failed (${filename}): ${err.message}
|
|
@@ -40368,7 +40671,7 @@ async function processSlackRecoveryOutboxFile(filename) {
|
|
|
40368
40671
|
const next = slackNextRetryName(filename);
|
|
40369
40672
|
if (next) {
|
|
40370
40673
|
try {
|
|
40371
|
-
renameSync5(fullPath,
|
|
40674
|
+
renameSync5(fullPath, join21(SLACK_RECOVERY_OUTBOX_DIR, next.next));
|
|
40372
40675
|
if (next.attempt >= SLACK_MAX_RECOVERY_ATTEMPTS) {
|
|
40373
40676
|
process.stderr.write(
|
|
40374
40677
|
`slack-channel(${AGENT_CODE_NAME}): ghost-reply recovery exhausted retries \u2014 moved to ${next.next}
|
|
@@ -40399,7 +40702,7 @@ function scanSlackRecoveryRetries() {
|
|
|
40399
40702
|
if (!SLACK_RECOVERY_OUTBOX_DIR) return;
|
|
40400
40703
|
let entries;
|
|
40401
40704
|
try {
|
|
40402
|
-
entries =
|
|
40705
|
+
entries = readdirSync7(SLACK_RECOVERY_OUTBOX_DIR);
|
|
40403
40706
|
} catch {
|
|
40404
40707
|
return;
|
|
40405
40708
|
}
|
|
@@ -40408,7 +40711,7 @@ function scanSlackRecoveryRetries() {
|
|
|
40408
40711
|
if (!f.includes(".retry-") || f.endsWith(".poison.json")) continue;
|
|
40409
40712
|
let mtimeMs;
|
|
40410
40713
|
try {
|
|
40411
|
-
mtimeMs =
|
|
40714
|
+
mtimeMs = statSync5(join21(SLACK_RECOVERY_OUTBOX_DIR, f)).mtimeMs;
|
|
40412
40715
|
} catch {
|
|
40413
40716
|
continue;
|
|
40414
40717
|
}
|
|
@@ -40429,7 +40732,7 @@ function startSlackRecoveryOutboxWatcher() {
|
|
|
40429
40732
|
return;
|
|
40430
40733
|
}
|
|
40431
40734
|
try {
|
|
40432
|
-
for (const f of
|
|
40735
|
+
for (const f of readdirSync7(SLACK_RECOVERY_OUTBOX_DIR)) {
|
|
40433
40736
|
if (isFirstAttemptSlackOutboxFile(f)) void processSlackRecoveryOutboxFile(f);
|
|
40434
40737
|
}
|
|
40435
40738
|
} catch {
|
|
@@ -40438,7 +40741,7 @@ function startSlackRecoveryOutboxWatcher() {
|
|
|
40438
40741
|
const watcher = watch(SLACK_RECOVERY_OUTBOX_DIR, (event, filename) => {
|
|
40439
40742
|
if (event !== "rename" || !filename) return;
|
|
40440
40743
|
if (!isFirstAttemptSlackOutboxFile(filename)) return;
|
|
40441
|
-
if (existsSync10(
|
|
40744
|
+
if (existsSync10(join21(SLACK_RECOVERY_OUTBOX_DIR, filename))) {
|
|
40442
40745
|
void processSlackRecoveryOutboxFile(filename);
|
|
40443
40746
|
}
|
|
40444
40747
|
});
|
|
@@ -40453,7 +40756,7 @@ function startSlackRecoveryOutboxWatcher() {
|
|
|
40453
40756
|
retryTimer.unref?.();
|
|
40454
40757
|
}
|
|
40455
40758
|
startSlackRecoveryOutboxWatcher();
|
|
40456
|
-
var SLACK_NOTICE_OUTBOX_DIR = SLACK_AGENT_DIR ?
|
|
40759
|
+
var SLACK_NOTICE_OUTBOX_DIR = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "slack-notice-outbox") : null;
|
|
40457
40760
|
var SLACK_NOTICE_MAX_AGE_MS = 9e4;
|
|
40458
40761
|
var SLACK_NOTICE_INFLIGHT = /* @__PURE__ */ new Set();
|
|
40459
40762
|
async function processSlackNoticeOutboxFile(filename) {
|
|
@@ -40461,11 +40764,11 @@ async function processSlackNoticeOutboxFile(filename) {
|
|
|
40461
40764
|
if (filename.startsWith(".") || filename.endsWith(".tmp") || !filename.endsWith(".json")) return;
|
|
40462
40765
|
if (SLACK_NOTICE_INFLIGHT.has(filename)) return;
|
|
40463
40766
|
SLACK_NOTICE_INFLIGHT.add(filename);
|
|
40464
|
-
const fullPath =
|
|
40767
|
+
const fullPath = join21(SLACK_NOTICE_OUTBOX_DIR, filename);
|
|
40465
40768
|
try {
|
|
40466
40769
|
let mtimeMs;
|
|
40467
40770
|
try {
|
|
40468
|
-
mtimeMs =
|
|
40771
|
+
mtimeMs = statSync5(fullPath).mtimeMs;
|
|
40469
40772
|
} catch {
|
|
40470
40773
|
return;
|
|
40471
40774
|
}
|
|
@@ -40478,7 +40781,7 @@ async function processSlackNoticeOutboxFile(filename) {
|
|
|
40478
40781
|
}
|
|
40479
40782
|
let payload;
|
|
40480
40783
|
try {
|
|
40481
|
-
const parsed = JSON.parse(
|
|
40784
|
+
const parsed = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40482
40785
|
if (!parsed || typeof parsed !== "object") throw new Error("not an object");
|
|
40483
40786
|
payload = parsed;
|
|
40484
40787
|
} catch {
|
|
@@ -40561,13 +40864,13 @@ function startSlackNoticeOutboxWatcher() {
|
|
|
40561
40864
|
return;
|
|
40562
40865
|
}
|
|
40563
40866
|
try {
|
|
40564
|
-
for (const f of
|
|
40867
|
+
for (const f of readdirSync7(SLACK_NOTICE_OUTBOX_DIR)) void processSlackNoticeOutboxFile(f);
|
|
40565
40868
|
} catch {
|
|
40566
40869
|
}
|
|
40567
40870
|
try {
|
|
40568
40871
|
const watcher = watch(SLACK_NOTICE_OUTBOX_DIR, (event, filename) => {
|
|
40569
40872
|
if (event !== "rename" || !filename) return;
|
|
40570
|
-
if (existsSync10(
|
|
40873
|
+
if (existsSync10(join21(SLACK_NOTICE_OUTBOX_DIR, filename))) {
|
|
40571
40874
|
void processSlackNoticeOutboxFile(filename);
|
|
40572
40875
|
}
|
|
40573
40876
|
});
|
|
@@ -40590,7 +40893,7 @@ function sweepSlackStaleMarkers(thresholdMs) {
|
|
|
40590
40893
|
if (!existsSync10(SLACK_PENDING_INBOUND_DIR)) return;
|
|
40591
40894
|
let filenames;
|
|
40592
40895
|
try {
|
|
40593
|
-
filenames =
|
|
40896
|
+
filenames = readdirSync7(SLACK_PENDING_INBOUND_DIR);
|
|
40594
40897
|
} catch (err) {
|
|
40595
40898
|
process.stderr.write(
|
|
40596
40899
|
`slack-channel(${AGENT_CODE_NAME}): stale-marker readdir failed: ${err.message}
|
|
@@ -40604,10 +40907,10 @@ function sweepSlackStaleMarkers(thresholdMs) {
|
|
|
40604
40907
|
for (const filename of filenames) {
|
|
40605
40908
|
if (!filename.endsWith(".json")) continue;
|
|
40606
40909
|
if (filename.endsWith(".tmp")) continue;
|
|
40607
|
-
const fullPath =
|
|
40910
|
+
const fullPath = join21(SLACK_PENDING_INBOUND_DIR, filename);
|
|
40608
40911
|
let marker;
|
|
40609
40912
|
try {
|
|
40610
|
-
marker = JSON.parse(
|
|
40913
|
+
marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40611
40914
|
} catch (err) {
|
|
40612
40915
|
process.stderr.write(
|
|
40613
40916
|
`slack-channel(${AGENT_CODE_NAME}): stale-marker parse failed for ${redactSlackId(filename)}: ${err.message}
|
|
@@ -40665,13 +40968,13 @@ var slackOrphanSweepTimer = setInterval(() => {
|
|
|
40665
40968
|
checkSlackWatchdogGiveUpNotice();
|
|
40666
40969
|
}, orphanSweepIntervalMs());
|
|
40667
40970
|
slackOrphanSweepTimer.unref?.();
|
|
40668
|
-
var SLACK_PROGRESS_HEARTBEAT_PATH = SLACK_AGENT_DIR ?
|
|
40971
|
+
var SLACK_PROGRESS_HEARTBEAT_PATH = SLACK_AGENT_DIR ? join21(SLACK_AGENT_DIR, "channel-progress-heartbeat.json") : null;
|
|
40669
40972
|
var slackTrackedProgress = null;
|
|
40670
40973
|
var slackProgressTickRunning = false;
|
|
40671
40974
|
function readSlackProgressHeartbeat() {
|
|
40672
40975
|
if (!SLACK_PROGRESS_HEARTBEAT_PATH || !existsSync10(SLACK_PROGRESS_HEARTBEAT_PATH)) return null;
|
|
40673
40976
|
try {
|
|
40674
|
-
return parseProgressHeartbeat(
|
|
40977
|
+
return parseProgressHeartbeat(readFileSync21(SLACK_PROGRESS_HEARTBEAT_PATH, "utf-8"));
|
|
40675
40978
|
} catch {
|
|
40676
40979
|
return null;
|
|
40677
40980
|
}
|
|
@@ -40694,11 +40997,11 @@ function findSlackProgressTarget() {
|
|
|
40694
40997
|
let best = null;
|
|
40695
40998
|
let bestMs = Infinity;
|
|
40696
40999
|
try {
|
|
40697
|
-
for (const name of
|
|
41000
|
+
for (const name of readdirSync7(SLACK_PENDING_INBOUND_DIR)) {
|
|
40698
41001
|
if (!name.endsWith(".json")) continue;
|
|
40699
41002
|
let m;
|
|
40700
41003
|
try {
|
|
40701
|
-
m = JSON.parse(
|
|
41004
|
+
m = JSON.parse(readFileSync21(join21(SLACK_PENDING_INBOUND_DIR, name), "utf-8"));
|
|
40702
41005
|
} catch {
|
|
40703
41006
|
continue;
|
|
40704
41007
|
}
|
|
@@ -40845,11 +41148,11 @@ function listPendingSlackConversations() {
|
|
|
40845
41148
|
if (!SLACK_PENDING_INBOUND_DIR || !existsSync10(SLACK_PENDING_INBOUND_DIR)) return [];
|
|
40846
41149
|
const byKey = /* @__PURE__ */ new Map();
|
|
40847
41150
|
try {
|
|
40848
|
-
for (const name of
|
|
41151
|
+
for (const name of readdirSync7(SLACK_PENDING_INBOUND_DIR)) {
|
|
40849
41152
|
if (!name.endsWith(".json")) continue;
|
|
40850
41153
|
try {
|
|
40851
41154
|
const marker = JSON.parse(
|
|
40852
|
-
|
|
41155
|
+
readFileSync21(join21(SLACK_PENDING_INBOUND_DIR, name), "utf8")
|
|
40853
41156
|
);
|
|
40854
41157
|
if (typeof marker.channel !== "string" || !marker.channel) continue;
|
|
40855
41158
|
if (typeof marker.thread_ts !== "string" || !marker.thread_ts) continue;
|
|
@@ -40868,6 +41171,95 @@ function listPendingSlackConversations() {
|
|
|
40868
41171
|
}
|
|
40869
41172
|
return [...byKey.values()];
|
|
40870
41173
|
}
|
|
41174
|
+
var lastSlackTurnFailedNoticeAt = /* @__PURE__ */ new Map();
|
|
41175
|
+
var lastSlackTurnRetryingNoticeAt = /* @__PURE__ */ new Map();
|
|
41176
|
+
async function postSlackTurnNotice(args) {
|
|
41177
|
+
if (!BOT_TOKEN || !args.channel) return { ok: false, error: "no_bot_token_or_channel" };
|
|
41178
|
+
try {
|
|
41179
|
+
const res = await fetch("https://slack.com/api/chat.postMessage", {
|
|
41180
|
+
method: "POST",
|
|
41181
|
+
headers: {
|
|
41182
|
+
"Content-Type": "application/json",
|
|
41183
|
+
Authorization: `Bearer ${BOT_TOKEN}`
|
|
41184
|
+
},
|
|
41185
|
+
body: JSON.stringify({
|
|
41186
|
+
channel: args.channel,
|
|
41187
|
+
text: args.text,
|
|
41188
|
+
// Anchor to the originating message, matching the give-up notice: the
|
|
41189
|
+
// user must see this against the message it concerns.
|
|
41190
|
+
...args.threadTs ? { thread_ts: args.threadTs } : {}
|
|
41191
|
+
}),
|
|
41192
|
+
signal: AbortSignal.timeout(1e4)
|
|
41193
|
+
});
|
|
41194
|
+
const body = await res.json().catch(() => ({}));
|
|
41195
|
+
if (body.ok === true) return { ok: true };
|
|
41196
|
+
return { ok: false, error: body.error ?? `http_${res.status}` };
|
|
41197
|
+
} catch (err) {
|
|
41198
|
+
return { ok: false, error: err.name || "fetch_failed" };
|
|
41199
|
+
}
|
|
41200
|
+
}
|
|
41201
|
+
function armSlackTurnFailureWatch(args) {
|
|
41202
|
+
const channel = args.channel;
|
|
41203
|
+
if (!channel) return;
|
|
41204
|
+
const conversationKey = args.threadTs ? `${channel}:${args.threadTs}` : channel;
|
|
41205
|
+
void (async () => {
|
|
41206
|
+
try {
|
|
41207
|
+
const failure = await watchForTurnFailure({
|
|
41208
|
+
sinceMs: args.sinceMs,
|
|
41209
|
+
channel: "slack",
|
|
41210
|
+
onLongRetry: async () => {
|
|
41211
|
+
const now2 = Date.now();
|
|
41212
|
+
if (!shouldPostUndeliverableNotice(lastSlackTurnRetryingNoticeAt.get(conversationKey), now2)) {
|
|
41213
|
+
return;
|
|
41214
|
+
}
|
|
41215
|
+
lastSlackTurnRetryingNoticeAt.set(conversationKey, now2);
|
|
41216
|
+
const posted2 = await postSlackTurnNotice({
|
|
41217
|
+
channel,
|
|
41218
|
+
threadTs: args.threadTs,
|
|
41219
|
+
text: turnRetryingNoticeText()
|
|
41220
|
+
});
|
|
41221
|
+
if (!posted2.ok) lastSlackTurnRetryingNoticeAt.delete(conversationKey);
|
|
41222
|
+
process.stderr.write(
|
|
41223
|
+
`slack-channel(${AGENT_CODE_NAME}): [turn-failure] retrying notice ${posted2.ok ? "posted" : `FAILED (${posted2.error})`} channel=${redactSlackId(channel)}
|
|
41224
|
+
`
|
|
41225
|
+
);
|
|
41226
|
+
}
|
|
41227
|
+
});
|
|
41228
|
+
if (!failure) return;
|
|
41229
|
+
const now = Date.now();
|
|
41230
|
+
if (!shouldPostUndeliverableNotice(lastSlackTurnFailedNoticeAt.get(conversationKey), now)) {
|
|
41231
|
+
process.stderr.write(
|
|
41232
|
+
`slack-channel(${AGENT_CODE_NAME}): [turn-failure] suppressed (throttled) channel=${redactSlackId(channel)} class=${failure.failureClass}
|
|
41233
|
+
`
|
|
41234
|
+
);
|
|
41235
|
+
return;
|
|
41236
|
+
}
|
|
41237
|
+
lastSlackTurnFailedNoticeAt.set(conversationKey, now);
|
|
41238
|
+
const posted = await postSlackTurnNotice({
|
|
41239
|
+
channel,
|
|
41240
|
+
threadTs: args.threadTs,
|
|
41241
|
+
text: turnFailedNoticeText()
|
|
41242
|
+
});
|
|
41243
|
+
if (!posted.ok) {
|
|
41244
|
+
lastSlackTurnFailedNoticeAt.delete(conversationKey);
|
|
41245
|
+
process.stderr.write(
|
|
41246
|
+
`slack-channel(${AGENT_CODE_NAME}): [turn-failure] NOTICE POST FAILED (${posted.error}) channel=${redactSlackId(channel)} - the user is still waiting on a dead turn
|
|
41247
|
+
`
|
|
41248
|
+
);
|
|
41249
|
+
return;
|
|
41250
|
+
}
|
|
41251
|
+
process.stderr.write(
|
|
41252
|
+
`slack-channel(${AGENT_CODE_NAME}): [turn-failure] notified channel=${redactSlackId(channel)} ts=${redactSlackId(args.messageTs)} class=${failure.failureClass} status=${failure.httpStatus}
|
|
41253
|
+
`
|
|
41254
|
+
);
|
|
41255
|
+
} catch (err) {
|
|
41256
|
+
process.stderr.write(
|
|
41257
|
+
`slack-channel(${AGENT_CODE_NAME}): [turn-failure] watch error: ${err.message}
|
|
41258
|
+
`
|
|
41259
|
+
);
|
|
41260
|
+
}
|
|
41261
|
+
})();
|
|
41262
|
+
}
|
|
40871
41263
|
function postSlackWatchdogGiveUpNotice(channel, threadTs, isThreadReply, reason) {
|
|
40872
41264
|
if (!BOT_TOKEN || !channel) return;
|
|
40873
41265
|
const now = Date.now();
|
|
@@ -40901,7 +41293,7 @@ function postSlackWatchdogGiveUpNotice(channel, threadTs, isThreadReply, reason)
|
|
|
40901
41293
|
}
|
|
40902
41294
|
function checkSlackWatchdogGiveUpNotice() {
|
|
40903
41295
|
if (!SLACK_AGENT_DIR) return;
|
|
40904
|
-
const signal = readGiveUpSignal(
|
|
41296
|
+
const signal = readGiveUpSignal(join21(SLACK_AGENT_DIR, GIVE_UP_SIGNAL_FILENAME));
|
|
40905
41297
|
const signalAtMs = signal?.atMs ?? null;
|
|
40906
41298
|
const act = decideGiveUpNotice({
|
|
40907
41299
|
signalAtMs,
|
|
@@ -40933,7 +41325,7 @@ function readRestartTopicForMarker(filename, channel, threadTs) {
|
|
|
40933
41325
|
if (!SLACK_RESTART_CONTEXT_DIR) return null;
|
|
40934
41326
|
let raw;
|
|
40935
41327
|
try {
|
|
40936
|
-
raw =
|
|
41328
|
+
raw = readFileSync21(join21(SLACK_RESTART_CONTEXT_DIR, filename), "utf-8");
|
|
40937
41329
|
} catch {
|
|
40938
41330
|
return null;
|
|
40939
41331
|
}
|
|
@@ -40942,7 +41334,7 @@ function readRestartTopicForMarker(filename, channel, threadTs) {
|
|
|
40942
41334
|
function removeRestartContextHint(filename) {
|
|
40943
41335
|
if (!SLACK_RESTART_CONTEXT_DIR) return;
|
|
40944
41336
|
try {
|
|
40945
|
-
unlinkSync7(
|
|
41337
|
+
unlinkSync7(join21(SLACK_RESTART_CONTEXT_DIR, filename));
|
|
40946
41338
|
} catch {
|
|
40947
41339
|
}
|
|
40948
41340
|
}
|
|
@@ -40950,14 +41342,14 @@ function clearAllRestartContextHints() {
|
|
|
40950
41342
|
if (!SLACK_RESTART_CONTEXT_DIR) return;
|
|
40951
41343
|
let names;
|
|
40952
41344
|
try {
|
|
40953
|
-
names =
|
|
41345
|
+
names = readdirSync7(SLACK_RESTART_CONTEXT_DIR);
|
|
40954
41346
|
} catch {
|
|
40955
41347
|
return;
|
|
40956
41348
|
}
|
|
40957
41349
|
for (const name of names) {
|
|
40958
41350
|
if (!name.endsWith(".json")) continue;
|
|
40959
41351
|
try {
|
|
40960
|
-
unlinkSync7(
|
|
41352
|
+
unlinkSync7(join21(SLACK_RESTART_CONTEXT_DIR, name));
|
|
40961
41353
|
} catch {
|
|
40962
41354
|
}
|
|
40963
41355
|
}
|
|
@@ -40974,7 +41366,7 @@ async function notifyStrandedInboundsOnFirstConnect() {
|
|
|
40974
41366
|
if (!SLACK_PENDING_INBOUND_DIR || !existsSync10(SLACK_PENDING_INBOUND_DIR)) return;
|
|
40975
41367
|
let filenames;
|
|
40976
41368
|
try {
|
|
40977
|
-
filenames =
|
|
41369
|
+
filenames = readdirSync7(SLACK_PENDING_INBOUND_DIR);
|
|
40978
41370
|
} catch {
|
|
40979
41371
|
hadFailure = true;
|
|
40980
41372
|
return;
|
|
@@ -40984,10 +41376,10 @@ async function notifyStrandedInboundsOnFirstConnect() {
|
|
|
40984
41376
|
let notified = 0;
|
|
40985
41377
|
for (const filename of filenames) {
|
|
40986
41378
|
if (!filename.endsWith(".json")) continue;
|
|
40987
|
-
const fullPath =
|
|
41379
|
+
const fullPath = join21(SLACK_PENDING_INBOUND_DIR, filename);
|
|
40988
41380
|
let marker;
|
|
40989
41381
|
try {
|
|
40990
|
-
marker = JSON.parse(
|
|
41382
|
+
marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
40991
41383
|
} catch {
|
|
40992
41384
|
continue;
|
|
40993
41385
|
}
|
|
@@ -41161,7 +41553,7 @@ function noteThreadActivityByMessageTs(channel, messageTs) {
|
|
|
41161
41553
|
markSeenAllSlackPendingMarkersForThread2(channel, messageTs);
|
|
41162
41554
|
markSeenSlackPendingMarkerByMessageTs2(channel, messageTs);
|
|
41163
41555
|
}
|
|
41164
|
-
var RESTART_FLAGS_DIR =
|
|
41556
|
+
var RESTART_FLAGS_DIR = join21(homedir7(), ".augmented", "restart-flags");
|
|
41165
41557
|
function actuateHostRestartSlack() {
|
|
41166
41558
|
return actuateHostRestart({
|
|
41167
41559
|
agtHost: AGT_HOST,
|
|
@@ -41766,7 +42158,7 @@ async function handleSlashCommandEnvelope(payload) {
|
|
|
41766
42158
|
if (!existsSync10(RESTART_FLAGS_DIR)) {
|
|
41767
42159
|
mkdirSync9(RESTART_FLAGS_DIR, { recursive: true });
|
|
41768
42160
|
}
|
|
41769
|
-
const flagPath =
|
|
42161
|
+
const flagPath = join21(RESTART_FLAGS_DIR, `${codeName}.flag`);
|
|
41770
42162
|
const flag = {
|
|
41771
42163
|
codeName,
|
|
41772
42164
|
source: "slack",
|
|
@@ -41909,7 +42301,7 @@ async function handleRestartCommand(opts) {
|
|
|
41909
42301
|
if (!existsSync10(RESTART_FLAGS_DIR)) {
|
|
41910
42302
|
mkdirSync9(RESTART_FLAGS_DIR, { recursive: true });
|
|
41911
42303
|
}
|
|
41912
|
-
const flagPath =
|
|
42304
|
+
const flagPath = join21(RESTART_FLAGS_DIR, `${codeName}.flag`);
|
|
41913
42305
|
const flag = {
|
|
41914
42306
|
codeName,
|
|
41915
42307
|
source: "slack",
|
|
@@ -42031,7 +42423,7 @@ var SLACK_HOT_THREAD_WINDOW_MS = parseHotThreadWindowMs(
|
|
|
42031
42423
|
);
|
|
42032
42424
|
function resolveThreadStorePath() {
|
|
42033
42425
|
if (!AGENT_CODE_NAME) return null;
|
|
42034
|
-
return
|
|
42426
|
+
return join21(homedir7(), ".augmented", AGENT_CODE_NAME, "slack-tracked-threads.json");
|
|
42035
42427
|
}
|
|
42036
42428
|
function parseTtlDays(raw) {
|
|
42037
42429
|
if (!raw) return void 0;
|
|
@@ -42070,9 +42462,9 @@ if (!BOT_TOKEN || !APP_TOKEN) {
|
|
|
42070
42462
|
var slackStderrLogStream = null;
|
|
42071
42463
|
if (AGENT_CODE_NAME) {
|
|
42072
42464
|
try {
|
|
42073
|
-
const logDir =
|
|
42465
|
+
const logDir = join21(homedir7(), ".augmented", AGENT_CODE_NAME);
|
|
42074
42466
|
mkdirSync9(logDir, { recursive: true });
|
|
42075
|
-
slackStderrLogStream = createWriteStream(
|
|
42467
|
+
slackStderrLogStream = createWriteStream(join21(logDir, "slack-channel-stderr.log"), {
|
|
42076
42468
|
flags: "a",
|
|
42077
42469
|
mode: 384
|
|
42078
42470
|
});
|
|
@@ -42962,7 +43354,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
|
|
|
42962
43354
|
let bytes;
|
|
42963
43355
|
let size;
|
|
42964
43356
|
try {
|
|
42965
|
-
const stat2 =
|
|
43357
|
+
const stat2 = statSync5(resolvedPath);
|
|
42966
43358
|
if (!stat2.isFile()) {
|
|
42967
43359
|
return {
|
|
42968
43360
|
content: [{ type: "text", text: `Upload refused: ${resolvedPath} is not a regular file.` }],
|
|
@@ -42970,7 +43362,7 @@ ${result.formatted}` : "No messages in range, or the bot is not a member of this
|
|
|
42970
43362
|
};
|
|
42971
43363
|
}
|
|
42972
43364
|
size = stat2.size;
|
|
42973
|
-
bytes =
|
|
43365
|
+
bytes = readFileSync21(resolvedPath);
|
|
42974
43366
|
} catch (err) {
|
|
42975
43367
|
return {
|
|
42976
43368
|
content: [{ type: "text", text: `Failed to read file: ${err.message}` }],
|
|
@@ -43745,7 +44137,7 @@ async function replayPendingSlackMarkers() {
|
|
|
43745
44137
|
if (!sessionAlive) return;
|
|
43746
44138
|
let filenames;
|
|
43747
44139
|
try {
|
|
43748
|
-
filenames =
|
|
44140
|
+
filenames = readdirSync7(SLACK_PENDING_INBOUND_DIR);
|
|
43749
44141
|
} catch {
|
|
43750
44142
|
return;
|
|
43751
44143
|
}
|
|
@@ -43753,7 +44145,7 @@ async function replayPendingSlackMarkers() {
|
|
|
43753
44145
|
let paneFreshAgeMs = null;
|
|
43754
44146
|
if (SLACK_AGENT_DIR) {
|
|
43755
44147
|
try {
|
|
43756
|
-
paneFreshAgeMs = Math.max(0, now -
|
|
44148
|
+
paneFreshAgeMs = Math.max(0, now - statSync5(join21(SLACK_AGENT_DIR, "pane.log")).mtimeMs);
|
|
43757
44149
|
} catch {
|
|
43758
44150
|
}
|
|
43759
44151
|
}
|
|
@@ -43761,10 +44153,10 @@ async function replayPendingSlackMarkers() {
|
|
|
43761
44153
|
const entries = [];
|
|
43762
44154
|
for (const name of filenames) {
|
|
43763
44155
|
if (!name.endsWith(".json") || name.endsWith(".tmp")) continue;
|
|
43764
|
-
const fullPath =
|
|
44156
|
+
const fullPath = join21(SLACK_PENDING_INBOUND_DIR, name);
|
|
43765
44157
|
let marker;
|
|
43766
44158
|
try {
|
|
43767
|
-
marker = JSON.parse(
|
|
44159
|
+
marker = JSON.parse(readFileSync21(fullPath, "utf-8"));
|
|
43768
44160
|
} catch {
|
|
43769
44161
|
continue;
|
|
43770
44162
|
}
|
|
@@ -44362,7 +44754,7 @@ async function connectSocketMode() {
|
|
|
44362
44754
|
let paneLogFreshAgeMs = null;
|
|
44363
44755
|
if (SLACK_AGENT_DIR) {
|
|
44364
44756
|
try {
|
|
44365
|
-
const paneMtimeMs =
|
|
44757
|
+
const paneMtimeMs = statSync5(join21(SLACK_AGENT_DIR, "pane.log")).mtimeMs;
|
|
44366
44758
|
paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
|
|
44367
44759
|
} catch {
|
|
44368
44760
|
}
|
|
@@ -44548,6 +44940,14 @@ ${forwarded.text}` : forwarded.text;
|
|
|
44548
44940
|
sinceMs: dispatchedAtMs
|
|
44549
44941
|
});
|
|
44550
44942
|
}
|
|
44943
|
+
if (shouldEngage && !isFromBot && turnFailureNoticeEnabled()) {
|
|
44944
|
+
armSlackTurnFailureWatch({
|
|
44945
|
+
channel,
|
|
44946
|
+
threadTs,
|
|
44947
|
+
messageTs: ts,
|
|
44948
|
+
sinceMs: dispatchedAtMs
|
|
44949
|
+
});
|
|
44950
|
+
}
|
|
44551
44951
|
if (shouldEngage) seedSlackProgressHeartbeat();
|
|
44552
44952
|
if (channel) {
|
|
44553
44953
|
conversationIngestClient?.ingest({
|