@integrity-labs/agt-cli 0.19.18 → 0.19.20
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-WTFROCJ3.js → chunk-IWFXAB4O.js} +427 -21
- package/dist/chunk-IWFXAB4O.js.map +1 -0
- package/dist/lib/manager-worker.js +111 -5
- package/dist/lib/manager-worker.js.map +1 -1
- package/mcp/slack-channel.js +282 -0
- package/mcp/telegram-channel.js +600 -14
- package/package.json +1 -1
- package/dist/chunk-WTFROCJ3.js.map +0 -1
package/mcp/slack-channel.js
CHANGED
|
@@ -14734,6 +14734,202 @@ function buildChannelInfoResult(args) {
|
|
|
14734
14734
|
return { ok: true, channel, bot_user_handle: botUserHandle };
|
|
14735
14735
|
}
|
|
14736
14736
|
|
|
14737
|
+
// src/slack-peer-classifier.ts
|
|
14738
|
+
var CODE_NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
14739
|
+
function classifyPeerMessage(msg, cfg, self) {
|
|
14740
|
+
if (!msg.bot_id) return { kind: "human" };
|
|
14741
|
+
if (self.bot_user_id !== null && msg.user === self.bot_user_id) {
|
|
14742
|
+
return { kind: "self" };
|
|
14743
|
+
}
|
|
14744
|
+
if (cfg.peer_disabled_mode === "all") {
|
|
14745
|
+
return { kind: "drop", reason: "peer_disabled_all" };
|
|
14746
|
+
}
|
|
14747
|
+
if (cfg.peer_agent_mode === "off") {
|
|
14748
|
+
return { kind: "drop", reason: "mode_off" };
|
|
14749
|
+
}
|
|
14750
|
+
if (cfg.peer_group_ids.length === 0) {
|
|
14751
|
+
if (msg.channel_type !== "im") {
|
|
14752
|
+
return { kind: "drop", reason: "chat_not_allowed" };
|
|
14753
|
+
}
|
|
14754
|
+
} else if (!cfg.peer_group_ids.includes(msg.channel)) {
|
|
14755
|
+
return { kind: "drop", reason: "chat_not_allowed" };
|
|
14756
|
+
}
|
|
14757
|
+
const peer = cfg.peers.find((p) => p.bot_user_id === msg.user);
|
|
14758
|
+
if (!peer) {
|
|
14759
|
+
return { kind: "drop", reason: "unknown_peer" };
|
|
14760
|
+
}
|
|
14761
|
+
if (peer.gate_path === null) {
|
|
14762
|
+
return { kind: "drop", reason: "cross_team_grant_missing" };
|
|
14763
|
+
}
|
|
14764
|
+
if (cfg.peer_disabled_mode === "cross_team_only" && peer.gate_path !== void 0 && peer.gate_path !== "same_team") {
|
|
14765
|
+
return { kind: "drop", reason: "peer_disabled_cross_team" };
|
|
14766
|
+
}
|
|
14767
|
+
if (self.bot_user_id === null) {
|
|
14768
|
+
return { kind: "drop", reason: "self_resolution_pending" };
|
|
14769
|
+
}
|
|
14770
|
+
const addressing = classifyAddressing(msg, self.bot_user_id);
|
|
14771
|
+
if (!addressing.addressed) {
|
|
14772
|
+
return { kind: "drop", reason: "not_addressed" };
|
|
14773
|
+
}
|
|
14774
|
+
if (addressing.viaReplyOnly) {
|
|
14775
|
+
const inAllowedGroup = cfg.peer_group_ids.length > 0 && cfg.peer_group_ids.includes(msg.channel);
|
|
14776
|
+
const respondMode = cfg.peer_agent_mode === "respond";
|
|
14777
|
+
if (!(inAllowedGroup && respondMode)) {
|
|
14778
|
+
return { kind: "drop", reason: "not_addressed" };
|
|
14779
|
+
}
|
|
14780
|
+
}
|
|
14781
|
+
return { kind: "peer-ingress", peer };
|
|
14782
|
+
}
|
|
14783
|
+
function classifyAddressing(msg, ourBotUserId) {
|
|
14784
|
+
const text = msg.text ?? "";
|
|
14785
|
+
const mentionToken = `<@${ourBotUserId}>`;
|
|
14786
|
+
const viaMention = text.includes(mentionToken);
|
|
14787
|
+
const viaReply = !!msg.thread_ts && msg.thread_ts !== void 0 && msg.parent_user_id === ourBotUserId;
|
|
14788
|
+
if (viaMention) {
|
|
14789
|
+
return { addressed: true, viaReplyOnly: false };
|
|
14790
|
+
}
|
|
14791
|
+
if (viaReply) {
|
|
14792
|
+
return { addressed: true, viaReplyOnly: true };
|
|
14793
|
+
}
|
|
14794
|
+
return { addressed: false, viaReplyOnly: false };
|
|
14795
|
+
}
|
|
14796
|
+
function parsePeersEnv(raw, gateRaw) {
|
|
14797
|
+
if (!raw || raw.trim().length === 0) return [];
|
|
14798
|
+
let parsed;
|
|
14799
|
+
try {
|
|
14800
|
+
parsed = JSON.parse(raw);
|
|
14801
|
+
} catch {
|
|
14802
|
+
return [];
|
|
14803
|
+
}
|
|
14804
|
+
if (!Array.isArray(parsed)) return [];
|
|
14805
|
+
const gateMap = /* @__PURE__ */ new Map();
|
|
14806
|
+
let gateConfigInvalid = false;
|
|
14807
|
+
if (gateRaw && gateRaw.trim().length > 0) {
|
|
14808
|
+
try {
|
|
14809
|
+
const gateParsed = JSON.parse(gateRaw);
|
|
14810
|
+
if (!gateParsed || typeof gateParsed !== "object" || Array.isArray(gateParsed)) {
|
|
14811
|
+
gateConfigInvalid = true;
|
|
14812
|
+
} else {
|
|
14813
|
+
for (const [k, v] of Object.entries(gateParsed)) {
|
|
14814
|
+
if (v === null) {
|
|
14815
|
+
gateMap.set(k, null);
|
|
14816
|
+
} else if (typeof v === "string") {
|
|
14817
|
+
const isGrantPath = v.startsWith("grant:") && v.slice("grant:".length).trim().length > 0;
|
|
14818
|
+
if (v === "same_team" || v === "intra_org_unrestricted" || isGrantPath) {
|
|
14819
|
+
gateMap.set(k, v);
|
|
14820
|
+
} else {
|
|
14821
|
+
gateConfigInvalid = true;
|
|
14822
|
+
break;
|
|
14823
|
+
}
|
|
14824
|
+
} else {
|
|
14825
|
+
gateConfigInvalid = true;
|
|
14826
|
+
break;
|
|
14827
|
+
}
|
|
14828
|
+
}
|
|
14829
|
+
}
|
|
14830
|
+
} catch {
|
|
14831
|
+
gateConfigInvalid = true;
|
|
14832
|
+
}
|
|
14833
|
+
if (gateConfigInvalid) {
|
|
14834
|
+
console.error(
|
|
14835
|
+
"[slack-peer-classifier] SLACK_PEERS_GATE is present but malformed; failing closed (every peer drops as cross_team_grant_missing)"
|
|
14836
|
+
);
|
|
14837
|
+
}
|
|
14838
|
+
}
|
|
14839
|
+
const out = [];
|
|
14840
|
+
for (const entry of parsed) {
|
|
14841
|
+
if (entry && typeof entry === "object" && typeof entry.code_name === "string" && CODE_NAME_RE.test(entry.code_name) && typeof entry.agent_id === "string" && typeof entry.bot_user_id === "string" && entry.bot_user_id.length > 0) {
|
|
14842
|
+
const e = entry;
|
|
14843
|
+
const peer = {
|
|
14844
|
+
code_name: e.code_name,
|
|
14845
|
+
bot_user_id: e.bot_user_id,
|
|
14846
|
+
agent_id: e.agent_id
|
|
14847
|
+
};
|
|
14848
|
+
if (gateConfigInvalid) {
|
|
14849
|
+
peer.gate_path = null;
|
|
14850
|
+
} else if (gateMap.has(e.bot_user_id)) {
|
|
14851
|
+
peer.gate_path = gateMap.get(e.bot_user_id) ?? null;
|
|
14852
|
+
}
|
|
14853
|
+
out.push(peer);
|
|
14854
|
+
}
|
|
14855
|
+
}
|
|
14856
|
+
return out;
|
|
14857
|
+
}
|
|
14858
|
+
function parsePeerGroupIdsEnv(raw) {
|
|
14859
|
+
if (!raw) return [];
|
|
14860
|
+
return raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
14861
|
+
}
|
|
14862
|
+
function parsePeerAgentModeEnv(raw) {
|
|
14863
|
+
if (raw === "listen" || raw === "respond") return raw;
|
|
14864
|
+
return "off";
|
|
14865
|
+
}
|
|
14866
|
+
|
|
14867
|
+
// src/cross-team-peer-audit-client.ts
|
|
14868
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
14869
|
+
function createCrossTeamPeerAuditClient(args) {
|
|
14870
|
+
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
14871
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
14872
|
+
const log = args.log ?? (() => {
|
|
14873
|
+
});
|
|
14874
|
+
const base = args.agtHost.replace(/\/+$/, "");
|
|
14875
|
+
const agentId = args.agentId;
|
|
14876
|
+
const apiKey = args.agtApiKey;
|
|
14877
|
+
let cachedToken = null;
|
|
14878
|
+
let cachedTokenExpiresAt = 0;
|
|
14879
|
+
async function getToken() {
|
|
14880
|
+
if (cachedToken && Date.now() < cachedTokenExpiresAt) return cachedToken;
|
|
14881
|
+
const resp = await fetchImpl(`${base}/host/exchange`, {
|
|
14882
|
+
method: "POST",
|
|
14883
|
+
headers: { "Content-Type": "application/json" },
|
|
14884
|
+
body: JSON.stringify({ host_key: apiKey }),
|
|
14885
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
14886
|
+
});
|
|
14887
|
+
if (!resp.ok) {
|
|
14888
|
+
const body = await resp.text().catch(() => "");
|
|
14889
|
+
throw new Error(`/host/exchange failed (${resp.status}): ${body.slice(0, 200)}`);
|
|
14890
|
+
}
|
|
14891
|
+
const data = await resp.json();
|
|
14892
|
+
cachedToken = data.token;
|
|
14893
|
+
cachedTokenExpiresAt = data.expires_at ? new Date(data.expires_at).getTime() - 12e4 : Date.now() + 55 * 6e4;
|
|
14894
|
+
return cachedToken;
|
|
14895
|
+
}
|
|
14896
|
+
async function postOnce(event) {
|
|
14897
|
+
const token = await getToken();
|
|
14898
|
+
return fetchImpl(`${base}/host/cross-team-peer-event`, {
|
|
14899
|
+
method: "POST",
|
|
14900
|
+
headers: {
|
|
14901
|
+
Authorization: `Bearer ${token}`,
|
|
14902
|
+
"Content-Type": "application/json"
|
|
14903
|
+
},
|
|
14904
|
+
body: JSON.stringify({ agent_id: agentId, ...event }),
|
|
14905
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
14906
|
+
});
|
|
14907
|
+
}
|
|
14908
|
+
async function emitAsync(event) {
|
|
14909
|
+
try {
|
|
14910
|
+
let resp = await postOnce(event);
|
|
14911
|
+
if (resp.status === 401) {
|
|
14912
|
+
cachedToken = null;
|
|
14913
|
+
cachedTokenExpiresAt = 0;
|
|
14914
|
+
resp = await postOnce(event);
|
|
14915
|
+
}
|
|
14916
|
+
if (!resp.ok) {
|
|
14917
|
+
const body = await resp.text().catch(() => "");
|
|
14918
|
+
log(
|
|
14919
|
+
`cross-team-peer-audit: POST failed (${resp.status}) event=${event.event_type}: ${body.slice(0, 200)}`
|
|
14920
|
+
);
|
|
14921
|
+
}
|
|
14922
|
+
} catch (err) {
|
|
14923
|
+
log(`cross-team-peer-audit: emit threw event=${event.event_type}: ${err.message}`);
|
|
14924
|
+
}
|
|
14925
|
+
}
|
|
14926
|
+
return {
|
|
14927
|
+
emit(event) {
|
|
14928
|
+
void emitAsync(event);
|
|
14929
|
+
}
|
|
14930
|
+
};
|
|
14931
|
+
}
|
|
14932
|
+
|
|
14737
14933
|
// src/slack-channel.ts
|
|
14738
14934
|
var BOT_TOKEN = process.env.SLACK_BOT_TOKEN;
|
|
14739
14935
|
var APP_TOKEN = process.env.SLACK_APP_TOKEN;
|
|
@@ -14749,6 +14945,35 @@ var ALLOWED_USERS = new Set(
|
|
|
14749
14945
|
);
|
|
14750
14946
|
var THREAD_AUTO_FOLLOW = process.env.SLACK_THREAD_AUTO_FOLLOW ?? "off";
|
|
14751
14947
|
var CHANNEL_RESPONSE_MODE = parseResponseMode(process.env.SLACK_CHANNEL_RESPONSE_MODE);
|
|
14948
|
+
var SLACK_PEER_DISABLED_MODE = (() => {
|
|
14949
|
+
const raw = (process.env.PEER_DISABLED ?? "").trim().toLowerCase();
|
|
14950
|
+
if (raw === "" || raw === "off") return "off";
|
|
14951
|
+
if (raw === "cross_team_only" || raw === "all") return raw;
|
|
14952
|
+
process.stderr.write(
|
|
14953
|
+
`slack-channel: invalid PEER_DISABLED=${JSON.stringify(process.env.PEER_DISABLED)} \u2014 defaulting to 'all' (fail-closed)
|
|
14954
|
+
`
|
|
14955
|
+
);
|
|
14956
|
+
return "all";
|
|
14957
|
+
})();
|
|
14958
|
+
if (SLACK_PEER_DISABLED_MODE !== "off") {
|
|
14959
|
+
process.stderr.write(
|
|
14960
|
+
`slack-channel: PEER_DISABLED=${SLACK_PEER_DISABLED_MODE} \u2014 ${SLACK_PEER_DISABLED_MODE === "all" ? "every peer surface short-circuited" : "cross-team peers dropped, same-team peers admitted"}
|
|
14961
|
+
`
|
|
14962
|
+
);
|
|
14963
|
+
}
|
|
14964
|
+
var crossTeamPeerAuditClient = createCrossTeamPeerAuditClient({
|
|
14965
|
+
agtHost: AGT_HOST,
|
|
14966
|
+
agtApiKey: AGT_API_KEY,
|
|
14967
|
+
agentId: AGT_AGENT_ID,
|
|
14968
|
+
log: (line) => process.stderr.write(`slack-channel: ${line}
|
|
14969
|
+
`)
|
|
14970
|
+
});
|
|
14971
|
+
var SLACK_PEER_CLASSIFIER_CONFIG = {
|
|
14972
|
+
peer_agent_mode: parsePeerAgentModeEnv(process.env.SLACK_PEER_AGENT_MODE),
|
|
14973
|
+
peer_group_ids: parsePeerGroupIdsEnv(process.env.SLACK_PEER_GROUP_IDS),
|
|
14974
|
+
peers: parsePeersEnv(process.env.SLACK_PEERS, process.env.SLACK_PEERS_GATE),
|
|
14975
|
+
peer_disabled_mode: SLACK_PEER_DISABLED_MODE
|
|
14976
|
+
};
|
|
14752
14977
|
var RESPONSE_TIMEOUT_MS = 3e5;
|
|
14753
14978
|
var pendingMessages = /* @__PURE__ */ new Map();
|
|
14754
14979
|
var SLACK_AGENT_DIR = AGENT_CODE_NAME ? join2(homedir2(), ".augmented", AGENT_CODE_NAME) : null;
|
|
@@ -16715,6 +16940,63 @@ async function connectSocketMode() {
|
|
|
16715
16940
|
return;
|
|
16716
16941
|
}
|
|
16717
16942
|
if (ALLOWED_USERS.size > 0 && evt.user && !ALLOWED_USERS.has(evt.user)) return;
|
|
16943
|
+
if (evt.bot_id) {
|
|
16944
|
+
const peerMsg = {
|
|
16945
|
+
text: evt.text,
|
|
16946
|
+
channel: evt.channel ?? "",
|
|
16947
|
+
channel_type: evt.channel_type,
|
|
16948
|
+
user: evt.user,
|
|
16949
|
+
bot_id: evt.bot_id,
|
|
16950
|
+
thread_ts: evt.thread_ts,
|
|
16951
|
+
parent_user_id: evt.parent_user_id
|
|
16952
|
+
};
|
|
16953
|
+
const decision = classifyPeerMessage(
|
|
16954
|
+
peerMsg,
|
|
16955
|
+
SLACK_PEER_CLASSIFIER_CONFIG,
|
|
16956
|
+
{ bot_user_id: botUserId }
|
|
16957
|
+
);
|
|
16958
|
+
if (decision.kind === "self") return;
|
|
16959
|
+
if (decision.kind === "drop") {
|
|
16960
|
+
const channelHash = createHash("sha256").update(evt.channel ?? "").digest("hex").slice(0, 8);
|
|
16961
|
+
process.stderr.write(
|
|
16962
|
+
`slack-channel: peer drop reason=${decision.reason} channel=${channelHash}
|
|
16963
|
+
`
|
|
16964
|
+
);
|
|
16965
|
+
if (decision.reason === "cross_team_grant_missing") {
|
|
16966
|
+
crossTeamPeerAuditClient?.emit({
|
|
16967
|
+
event_type: "slack.peer.drop.cross_team_grant_missing",
|
|
16968
|
+
peer_agent_id: null,
|
|
16969
|
+
gate_path: null,
|
|
16970
|
+
grant_id: null,
|
|
16971
|
+
chat_id: evt.channel ?? null,
|
|
16972
|
+
message_id: evt.ts ?? null
|
|
16973
|
+
});
|
|
16974
|
+
}
|
|
16975
|
+
return;
|
|
16976
|
+
}
|
|
16977
|
+
if (decision.kind === "peer-ingress") {
|
|
16978
|
+
const peerGate = decision.peer.gate_path;
|
|
16979
|
+
if (peerGate === "intra_org_unrestricted") {
|
|
16980
|
+
crossTeamPeerAuditClient?.emit({
|
|
16981
|
+
event_type: "slack.peer.ingress.cross_team",
|
|
16982
|
+
peer_agent_id: decision.peer.agent_id || null,
|
|
16983
|
+
gate_path: peerGate,
|
|
16984
|
+
grant_id: null,
|
|
16985
|
+
chat_id: evt.channel ?? null,
|
|
16986
|
+
message_id: evt.ts ?? null
|
|
16987
|
+
});
|
|
16988
|
+
} else if (typeof peerGate === "string" && peerGate.startsWith("grant:")) {
|
|
16989
|
+
crossTeamPeerAuditClient?.emit({
|
|
16990
|
+
event_type: "slack.peer.ingress.cross_team",
|
|
16991
|
+
peer_agent_id: decision.peer.agent_id || null,
|
|
16992
|
+
gate_path: peerGate,
|
|
16993
|
+
grant_id: peerGate.slice("grant:".length),
|
|
16994
|
+
chat_id: evt.channel ?? null,
|
|
16995
|
+
message_id: evt.ts ?? null
|
|
16996
|
+
});
|
|
16997
|
+
}
|
|
16998
|
+
}
|
|
16999
|
+
}
|
|
16718
17000
|
if (evt.type === "app_mention") {
|
|
16719
17001
|
rememberThread(evt.channel, trackTs, "mentioned");
|
|
16720
17002
|
}
|