@integrity-labs/agt-cli 0.28.267 → 0.28.268
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
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
success,
|
|
39
39
|
table,
|
|
40
40
|
warn
|
|
41
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-PA3PWATY.js";
|
|
42
42
|
import {
|
|
43
43
|
CHANNEL_REGISTRY,
|
|
44
44
|
DEFAULT_FRAMEWORK,
|
|
@@ -4826,7 +4826,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4826
4826
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4827
4827
|
import chalk18 from "chalk";
|
|
4828
4828
|
import ora16 from "ora";
|
|
4829
|
-
var cliVersion = true ? "0.28.
|
|
4829
|
+
var cliVersion = true ? "0.28.268" : "dev";
|
|
4830
4830
|
async function fetchLatestVersion() {
|
|
4831
4831
|
const host2 = getHost();
|
|
4832
4832
|
if (!host2) return null;
|
|
@@ -5840,7 +5840,7 @@ function handleError(err) {
|
|
|
5840
5840
|
}
|
|
5841
5841
|
|
|
5842
5842
|
// src/bin/agt.ts
|
|
5843
|
-
var cliVersion2 = true ? "0.28.
|
|
5843
|
+
var cliVersion2 = true ? "0.28.268" : "dev";
|
|
5844
5844
|
var program = new Command();
|
|
5845
5845
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
5846
5846
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -5876,7 +5876,7 @@ function requireHost() {
|
|
|
5876
5876
|
}
|
|
5877
5877
|
|
|
5878
5878
|
// src/lib/api-client.ts
|
|
5879
|
-
var agtCliVersion = true ? "0.28.
|
|
5879
|
+
var agtCliVersion = true ? "0.28.268" : "dev";
|
|
5880
5880
|
var lastConfigHash = null;
|
|
5881
5881
|
function setConfigHash(hash) {
|
|
5882
5882
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -8153,4 +8153,4 @@ export {
|
|
|
8153
8153
|
managerInstallSystemUnitCommand,
|
|
8154
8154
|
managerUninstallSystemUnitCommand
|
|
8155
8155
|
};
|
|
8156
|
-
//# sourceMappingURL=chunk-
|
|
8156
|
+
//# sourceMappingURL=chunk-PA3PWATY.js.map
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
requireHost,
|
|
39
39
|
safeWriteJsonAtomic,
|
|
40
40
|
setConfigHash
|
|
41
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-PA3PWATY.js";
|
|
42
42
|
import {
|
|
43
43
|
getProjectDir as getProjectDir2,
|
|
44
44
|
getReadyTasks,
|
|
@@ -6700,7 +6700,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
6700
6700
|
var lastVersionCheckAt = 0;
|
|
6701
6701
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6702
6702
|
var lastResponsivenessProbeAt = 0;
|
|
6703
|
-
var agtCliVersion = true ? "0.28.
|
|
6703
|
+
var agtCliVersion = true ? "0.28.268" : "dev";
|
|
6704
6704
|
function resolveBrewPath(execFileSync2) {
|
|
6705
6705
|
try {
|
|
6706
6706
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -16869,7 +16869,7 @@ import { join as join9 } from "path";
|
|
|
16869
16869
|
var DEFAULT_MAX_ENTRIES = 500;
|
|
16870
16870
|
var DEFAULT_CLEARED_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
16871
16871
|
function entryKey(channel, messageTs) {
|
|
16872
|
-
return `${channel}
|
|
16872
|
+
return `${channel} ${messageTs}`;
|
|
16873
16873
|
}
|
|
16874
16874
|
function createInboundRegistry(opts = {}) {
|
|
16875
16875
|
const maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
@@ -16946,6 +16946,27 @@ function createInboundRegistry(opts = {}) {
|
|
|
16946
16946
|
}
|
|
16947
16947
|
return best;
|
|
16948
16948
|
}
|
|
16949
|
+
function byCoordsAnyChannel(threadOrMessageTs) {
|
|
16950
|
+
let best = null;
|
|
16951
|
+
let bestExact = false;
|
|
16952
|
+
for (const e of entries.values()) {
|
|
16953
|
+
const exact = e.messageTs === threadOrMessageTs;
|
|
16954
|
+
const thread = e.threadTs === threadOrMessageTs;
|
|
16955
|
+
if (!exact && !thread) continue;
|
|
16956
|
+
if (best === null) {
|
|
16957
|
+
best = e;
|
|
16958
|
+
bestExact = exact;
|
|
16959
|
+
continue;
|
|
16960
|
+
}
|
|
16961
|
+
if (exact && !bestExact) {
|
|
16962
|
+
best = e;
|
|
16963
|
+
bestExact = true;
|
|
16964
|
+
} else if (exact === bestExact && e.receivedAt >= best.receivedAt) {
|
|
16965
|
+
best = e;
|
|
16966
|
+
}
|
|
16967
|
+
}
|
|
16968
|
+
return best;
|
|
16969
|
+
}
|
|
16949
16970
|
function livePending() {
|
|
16950
16971
|
const out = [];
|
|
16951
16972
|
for (const e of entries.values()) {
|
|
@@ -16994,6 +17015,7 @@ function createInboundRegistry(opts = {}) {
|
|
|
16994
17015
|
markClearedOldestInChannel,
|
|
16995
17016
|
byInboundId,
|
|
16996
17017
|
byCoords,
|
|
17018
|
+
byCoordsAnyChannel,
|
|
16997
17019
|
livePending,
|
|
16998
17020
|
seedFromMarkerDir,
|
|
16999
17021
|
size: () => entries.size
|
|
@@ -17059,6 +17081,33 @@ function resolveReplyBinding(input) {
|
|
|
17059
17081
|
}
|
|
17060
17082
|
return classifyByCoords(mode, args, registry2, now, false, knownThread);
|
|
17061
17083
|
}
|
|
17084
|
+
function isDmChannel(channel) {
|
|
17085
|
+
return !!channel && channel.startsWith("D");
|
|
17086
|
+
}
|
|
17087
|
+
function guardReplyChannel(input) {
|
|
17088
|
+
const { args, registry: registry2 } = input;
|
|
17089
|
+
const noop = {
|
|
17090
|
+
channel: args.channel,
|
|
17091
|
+
threadTs: args.thread_ts,
|
|
17092
|
+
messageTs: args.message_ts,
|
|
17093
|
+
corrected: false,
|
|
17094
|
+
dm: false
|
|
17095
|
+
};
|
|
17096
|
+
if (args.inbound_id) return noop;
|
|
17097
|
+
if (args.proactive === true) return noop;
|
|
17098
|
+
if (!args.channel) return noop;
|
|
17099
|
+
const matched = (args.message_ts ? registry2.byCoordsAnyChannel(args.message_ts) : null) ?? (args.thread_ts ? registry2.byCoordsAnyChannel(args.thread_ts) : null);
|
|
17100
|
+
if (!matched) return noop;
|
|
17101
|
+
if (matched.channel === args.channel) return noop;
|
|
17102
|
+
return {
|
|
17103
|
+
channel: matched.channel,
|
|
17104
|
+
threadTs: matched.threadTs,
|
|
17105
|
+
messageTs: matched.messageTs,
|
|
17106
|
+
corrected: true,
|
|
17107
|
+
dm: isDmChannel(matched.channel),
|
|
17108
|
+
requestedChannel: args.channel
|
|
17109
|
+
};
|
|
17110
|
+
}
|
|
17062
17111
|
function classifyByCoords(mode, args, registry2, now, unknownInboundId, knownThread) {
|
|
17063
17112
|
const modelChannel = args.channel;
|
|
17064
17113
|
const modelThread = args.thread_ts;
|
|
@@ -17121,6 +17170,8 @@ import { readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from
|
|
|
17121
17170
|
import { join as join10 } from "path";
|
|
17122
17171
|
var REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX = "-reply-binding-classifications.json";
|
|
17123
17172
|
var UNKNOWN_INBOUND_ID_KEY = "unknown_inbound_id";
|
|
17173
|
+
var CHANNEL_MISTARGET_CORRECTED_KEY = "channel_mistarget_corrected";
|
|
17174
|
+
var DM_CHANNEL_MISTARGET_KEY = "dm_channel_mistarget";
|
|
17124
17175
|
var VALID_MODES = /* @__PURE__ */ new Set(["shadow", "warn", "enforce"]);
|
|
17125
17176
|
function slackReplyBindingMode() {
|
|
17126
17177
|
const raw = process.env["AGT_SLACK_REPLY_BINDING"];
|
|
@@ -17145,6 +17196,24 @@ function recordReplyBindingClassification(agentDir, channel, input) {
|
|
|
17145
17196
|
} catch {
|
|
17146
17197
|
}
|
|
17147
17198
|
}
|
|
17199
|
+
function recordChannelMistarget(agentDir, channel, input) {
|
|
17200
|
+
if (!agentDir) return;
|
|
17201
|
+
const path = join10(agentDir, `${channel}${REPLY_BINDING_CLASSIFICATION_COUNTER_SUFFIX}`);
|
|
17202
|
+
let counts = {};
|
|
17203
|
+
try {
|
|
17204
|
+
const parsed = JSON.parse(readFileSync11(path, "utf-8"));
|
|
17205
|
+
if (parsed && typeof parsed === "object") counts = parsed;
|
|
17206
|
+
} catch {
|
|
17207
|
+
}
|
|
17208
|
+
counts[CHANNEL_MISTARGET_CORRECTED_KEY] = (counts[CHANNEL_MISTARGET_CORRECTED_KEY] ?? 0) + 1;
|
|
17209
|
+
if (input.dm) {
|
|
17210
|
+
counts[DM_CHANNEL_MISTARGET_KEY] = (counts[DM_CHANNEL_MISTARGET_KEY] ?? 0) + 1;
|
|
17211
|
+
}
|
|
17212
|
+
try {
|
|
17213
|
+
writeFileSync9(path, JSON.stringify(counts), { mode: 384 });
|
|
17214
|
+
} catch {
|
|
17215
|
+
}
|
|
17216
|
+
}
|
|
17148
17217
|
|
|
17149
17218
|
// src/slack-reply-target-telemetry.ts
|
|
17150
17219
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
@@ -20297,7 +20366,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
20297
20366
|
properties: {
|
|
20298
20367
|
channel: {
|
|
20299
20368
|
type: "string",
|
|
20300
|
-
description:
|
|
20369
|
+
description: 'Slack channel ID. Copy it from the channel attribute of the SAME <channel> tag you are answering - never reuse a channel from a different message. A DM channel starts with "D": a DM answer MUST go to that "D\u2026" id, not a shared "C\u2026"/"G\u2026" channel. Prefer passing inbound_id, which resolves the exact destination for you.'
|
|
20301
20370
|
},
|
|
20302
20371
|
text: { type: "string", description: "The message to send" },
|
|
20303
20372
|
thread_ts: {
|
|
@@ -20324,7 +20393,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
20324
20393
|
// WS2 (cross-thread reply routing): the preferred way to target a reply.
|
|
20325
20394
|
inbound_id: {
|
|
20326
20395
|
type: "string",
|
|
20327
|
-
description: `The inbound_id attribute of the <channel> tag you are answering (e.g. "ib_a1b2c3d4e5f6"). PREFERRED over channel/thread_ts/message_ts
|
|
20396
|
+
description: `The inbound_id attribute of the <channel> tag you are answering (e.g. "ib_a1b2c3d4e5f6"). ALWAYS include it when replying to a message - it is STRONGLY PREFERRED over channel/thread_ts/message_ts because the server resolves the exact destination (channel AND thread) from it, so your reply can never land in another user's channel or thread. Copy it verbatim from the tag of the message you are replying to. Omit it only for a proactive (self-initiated) send.`
|
|
20328
20397
|
},
|
|
20329
20398
|
proactive: {
|
|
20330
20399
|
type: "boolean",
|
|
@@ -20580,7 +20649,20 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20580
20649
|
classification: binding.classification,
|
|
20581
20650
|
unknownInboundId: binding.unknownInboundId
|
|
20582
20651
|
});
|
|
20583
|
-
|
|
20652
|
+
const channelGuard = guardReplyChannel({
|
|
20653
|
+
args: { inbound_id, channel, thread_ts, message_ts, proactive },
|
|
20654
|
+
registry: slackInboundRegistry
|
|
20655
|
+
});
|
|
20656
|
+
if (channelGuard.corrected) {
|
|
20657
|
+
recordChannelMistarget(SLACK_AGENT_DIR, "slack", { dm: channelGuard.dm });
|
|
20658
|
+
process.stderr.write(
|
|
20659
|
+
`slack-channel(${AGENT_CODE_NAME}): reply_channel_mistarget_corrected dm=${channelGuard.dm} requested=${redactSlackId(channelGuard.requestedChannel)} registry=${redactSlackId(channelGuard.channel)}
|
|
20660
|
+
`
|
|
20661
|
+
);
|
|
20662
|
+
}
|
|
20663
|
+
const effectiveChannel = channelGuard.corrected && channelGuard.channel ? channelGuard.channel : channel;
|
|
20664
|
+
const effectiveMessageTs = channelGuard.corrected ? channelGuard.messageTs : message_ts;
|
|
20665
|
+
if (bindingMode === "enforce" && binding.reject && !channelGuard.corrected) {
|
|
20584
20666
|
process.stderr.write(
|
|
20585
20667
|
`slack-channel(${AGENT_CODE_NAME}): reply_binding_rejected class=${binding.classification} channel=${redactSlackId(channel)}
|
|
20586
20668
|
`
|
|
@@ -20604,28 +20686,28 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20604
20686
|
};
|
|
20605
20687
|
}
|
|
20606
20688
|
const bindingFeedback = bindingMode === "warn" ? binding.agentFeedback : void 0;
|
|
20607
|
-
const effectiveThreadTs = enforceBound ? binding.threadTs : resolveReplyThreadTs({
|
|
20689
|
+
const effectiveThreadTs = enforceBound ? binding.threadTs : channelGuard.corrected ? channelGuard.threadTs : resolveReplyThreadTs({
|
|
20608
20690
|
channel,
|
|
20609
20691
|
threadTs: thread_ts,
|
|
20610
20692
|
messageTs: message_ts
|
|
20611
20693
|
});
|
|
20612
|
-
if (
|
|
20694
|
+
if (effectiveChannel) {
|
|
20613
20695
|
recordReplyTargetClassification(
|
|
20614
20696
|
SLACK_AGENT_DIR,
|
|
20615
20697
|
"slack",
|
|
20616
20698
|
classifyReplyTarget({
|
|
20617
|
-
channel,
|
|
20699
|
+
channel: effectiveChannel,
|
|
20618
20700
|
threadTs: effectiveThreadTs,
|
|
20619
|
-
messageTs:
|
|
20701
|
+
messageTs: effectiveMessageTs,
|
|
20620
20702
|
registry: slackInboundRegistry
|
|
20621
20703
|
})
|
|
20622
20704
|
);
|
|
20623
20705
|
}
|
|
20624
20706
|
const throttleCfg = configFromEnv();
|
|
20625
|
-
const throttleKey = effectiveThreadTs ??
|
|
20707
|
+
const throttleKey = effectiveThreadTs ?? effectiveChannel;
|
|
20626
20708
|
const throttleNow = Date.now();
|
|
20627
20709
|
const throttleDecision = decideReplyThrottle({
|
|
20628
|
-
recentReplyTimestamps: getRecentReplies(
|
|
20710
|
+
recentReplyTimestamps: getRecentReplies(effectiveChannel, throttleKey, throttleNow, throttleCfg),
|
|
20629
20711
|
now: throttleNow,
|
|
20630
20712
|
config: throttleCfg
|
|
20631
20713
|
});
|
|
@@ -20634,14 +20716,14 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20634
20716
|
`slack-channel(${AGENT_CODE_NAME}): reply_throttled channel=${redactSlackId(channel)} thread=${redactSlackId(throttleKey)} count=${throttleDecision.recentCount} window_ms=${throttleCfg.windowMs} threshold=${throttleCfg.threshold}
|
|
20635
20717
|
`
|
|
20636
20718
|
);
|
|
20637
|
-
if (
|
|
20719
|
+
if (effectiveChannel && effectiveThreadTs) {
|
|
20638
20720
|
fetch("https://slack.com/api/reactions.add", {
|
|
20639
20721
|
method: "POST",
|
|
20640
20722
|
headers: {
|
|
20641
20723
|
"Content-Type": "application/json",
|
|
20642
20724
|
Authorization: `Bearer ${BOT_TOKEN}`
|
|
20643
20725
|
},
|
|
20644
|
-
body: JSON.stringify({ channel, timestamp: effectiveThreadTs, name: "lock" })
|
|
20726
|
+
body: JSON.stringify({ channel: effectiveChannel, timestamp: effectiveThreadTs, name: "lock" })
|
|
20645
20727
|
}).catch(() => {
|
|
20646
20728
|
});
|
|
20647
20729
|
}
|
|
@@ -20655,21 +20737,24 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20655
20737
|
isError: true
|
|
20656
20738
|
};
|
|
20657
20739
|
}
|
|
20740
|
+
const settleChannel = effectiveChannel;
|
|
20741
|
+
const settleMessageTs = effectiveMessageTs;
|
|
20742
|
+
const settleThreadTs = enforceBound ? binding.threadTs : channelGuard.corrected ? channelGuard.threadTs : thread_ts;
|
|
20658
20743
|
const settlePendingMarker = () => {
|
|
20659
|
-
if (!
|
|
20660
|
-
if (
|
|
20744
|
+
if (!settleChannel) return;
|
|
20745
|
+
if (settleMessageTs) {
|
|
20661
20746
|
if (interim) {
|
|
20662
|
-
markSeenSlackPendingMarkerByMessageTs2(
|
|
20663
|
-
if (
|
|
20747
|
+
markSeenSlackPendingMarkerByMessageTs2(settleChannel, settleMessageTs);
|
|
20748
|
+
if (settleThreadTs) markSeenAllSlackPendingMarkersForThread2(settleChannel, settleThreadTs);
|
|
20664
20749
|
} else {
|
|
20665
|
-
clearSlackPendingMarkerByMessageTs2(
|
|
20666
|
-
if (
|
|
20750
|
+
clearSlackPendingMarkerByMessageTs2(settleChannel, settleMessageTs);
|
|
20751
|
+
if (settleThreadTs) clearPendingMessage(settleChannel, settleThreadTs);
|
|
20667
20752
|
}
|
|
20668
|
-
} else if (
|
|
20669
|
-
if (interim) markSeenAllSlackPendingMarkersForThread2(
|
|
20670
|
-
else clearPendingMessage(
|
|
20753
|
+
} else if (settleThreadTs) {
|
|
20754
|
+
if (interim) markSeenAllSlackPendingMarkersForThread2(settleChannel, settleThreadTs);
|
|
20755
|
+
else clearPendingMessage(settleChannel, settleThreadTs);
|
|
20671
20756
|
} else if (!interim) {
|
|
20672
|
-
clearOldestSlackPendingMarkerInChannel2(
|
|
20757
|
+
clearOldestSlackPendingMarkerInChannel2(settleChannel);
|
|
20673
20758
|
}
|
|
20674
20759
|
};
|
|
20675
20760
|
const sanitized = stripRepostPreambleWithMeta(text);
|
|
@@ -20686,7 +20771,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20686
20771
|
Authorization: `Bearer ${BOT_TOKEN}`
|
|
20687
20772
|
},
|
|
20688
20773
|
body: JSON.stringify({
|
|
20689
|
-
channel,
|
|
20774
|
+
channel: effectiveChannel,
|
|
20690
20775
|
text: apiErr.text,
|
|
20691
20776
|
...effectiveThreadTs ? { thread_ts: effectiveThreadTs } : {},
|
|
20692
20777
|
...buildAugmentedSlackMetadata() ? { metadata: buildAugmentedSlackMetadata() } : {}
|
|
@@ -20702,11 +20787,13 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20702
20787
|
};
|
|
20703
20788
|
}
|
|
20704
20789
|
settlePendingMarker();
|
|
20705
|
-
recordReply(
|
|
20790
|
+
recordReply(effectiveChannel, throttleKey, throttleNow, throttleCfg);
|
|
20706
20791
|
recordActivity("reply");
|
|
20707
20792
|
if (THREAD_AUTO_FOLLOW !== "off") {
|
|
20708
20793
|
const trackTs = effectiveThreadTs ?? data.ts ?? void 0;
|
|
20709
|
-
rememberThread(
|
|
20794
|
+
rememberThread(effectiveChannel, trackTs, thread_ts ? "mentioned" : "started", {
|
|
20795
|
+
botPosted: true
|
|
20796
|
+
});
|
|
20710
20797
|
}
|
|
20711
20798
|
if (interactiveHostAvailable() && data.ts) {
|
|
20712
20799
|
const cfg = {
|
|
@@ -20720,7 +20807,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
20720
20807
|
try {
|
|
20721
20808
|
const runtime = await Promise.resolve().then(() => (init_slack_block_kit_runtime(), slack_block_kit_runtime_exports));
|
|
20722
20809
|
await runtime.recordSlackDelivery(cfg, {
|
|
20723
|
-
channel,
|
|
20810
|
+
channel: effectiveChannel,
|
|
20724
20811
|
messageTs: tsToRecord,
|
|
20725
20812
|
threadTs: threadTsToRecord
|
|
20726
20813
|
});
|
package/package.json
CHANGED
|
File without changes
|