@integrity-labs/agt-cli 0.28.96 → 0.28.97
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-LFTKXQEA.js → chunk-EN7ZKY4A.js} +2 -2
- package/dist/lib/manager-worker.js +2 -2
- package/dist/mcp/slack-channel.js +122 -18
- package/dist/mcp/telegram-channel.js +104 -3
- package/package.json +1 -1
- /package/dist/{chunk-LFTKXQEA.js.map → chunk-EN7ZKY4A.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
success,
|
|
38
38
|
table,
|
|
39
39
|
warn
|
|
40
|
-
} from "../chunk-
|
|
40
|
+
} from "../chunk-EN7ZKY4A.js";
|
|
41
41
|
import {
|
|
42
42
|
CHANNEL_REGISTRY,
|
|
43
43
|
DEPLOYMENT_TEMPLATES,
|
|
@@ -4777,7 +4777,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4777
4777
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4778
4778
|
import chalk18 from "chalk";
|
|
4779
4779
|
import ora16 from "ora";
|
|
4780
|
-
var cliVersion = true ? "0.28.
|
|
4780
|
+
var cliVersion = true ? "0.28.97" : "dev";
|
|
4781
4781
|
async function fetchLatestVersion() {
|
|
4782
4782
|
const host2 = getHost();
|
|
4783
4783
|
if (!host2) return null;
|
|
@@ -5791,7 +5791,7 @@ function handleError(err) {
|
|
|
5791
5791
|
}
|
|
5792
5792
|
|
|
5793
5793
|
// src/bin/agt.ts
|
|
5794
|
-
var cliVersion2 = true ? "0.28.
|
|
5794
|
+
var cliVersion2 = true ? "0.28.97" : "dev";
|
|
5795
5795
|
var program = new Command();
|
|
5796
5796
|
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");
|
|
5797
5797
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -7541,7 +7541,7 @@ function requireHost() {
|
|
|
7541
7541
|
}
|
|
7542
7542
|
|
|
7543
7543
|
// src/lib/api-client.ts
|
|
7544
|
-
var agtCliVersion = true ? "0.28.
|
|
7544
|
+
var agtCliVersion = true ? "0.28.97" : "dev";
|
|
7545
7545
|
var lastConfigHash = null;
|
|
7546
7546
|
function setConfigHash(hash) {
|
|
7547
7547
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -8838,4 +8838,4 @@ export {
|
|
|
8838
8838
|
managerInstallSystemUnitCommand,
|
|
8839
8839
|
managerUninstallSystemUnitCommand
|
|
8840
8840
|
};
|
|
8841
|
-
//# sourceMappingURL=chunk-
|
|
8841
|
+
//# sourceMappingURL=chunk-EN7ZKY4A.js.map
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
requireHost,
|
|
29
29
|
safeWriteJsonAtomic,
|
|
30
30
|
setConfigHash
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-EN7ZKY4A.js";
|
|
32
32
|
import {
|
|
33
33
|
getProjectDir as getProjectDir2,
|
|
34
34
|
getReadyTasks,
|
|
@@ -6953,7 +6953,7 @@ var cachedMaintenanceWindow = null;
|
|
|
6953
6953
|
var lastVersionCheckAt = 0;
|
|
6954
6954
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6955
6955
|
var lastResponsivenessProbeAt = 0;
|
|
6956
|
-
var agtCliVersion = true ? "0.28.
|
|
6956
|
+
var agtCliVersion = true ? "0.28.97" : "dev";
|
|
6957
6957
|
function resolveBrewPath(execFileSync4) {
|
|
6958
6958
|
try {
|
|
6959
6959
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -15327,6 +15327,12 @@ function decideProgressAction(input) {
|
|
|
15327
15327
|
const { now, heartbeat, target, tracked, freshnessMs, minPendingMs } = input;
|
|
15328
15328
|
const fresh = heartbeat != null && now - heartbeat.updatedAtMs <= freshnessMs;
|
|
15329
15329
|
const active = target != null && fresh;
|
|
15330
|
+
if (active && input.targetHasCard === true) {
|
|
15331
|
+
if (tracked) {
|
|
15332
|
+
return { type: "delete", channel: tracked.channel, threadTs: tracked.threadTs, ts: tracked.ts };
|
|
15333
|
+
}
|
|
15334
|
+
return { type: "none" };
|
|
15335
|
+
}
|
|
15330
15336
|
if (!active) {
|
|
15331
15337
|
if (tracked) {
|
|
15332
15338
|
return { type: "delete", channel: tracked.channel, threadTs: tracked.threadTs, ts: tracked.ts };
|
|
@@ -15355,6 +15361,12 @@ function progressMinPendingMs() {
|
|
|
15355
15361
|
const raw = parseInt(process.env.AGT_CHANNEL_PROGRESS_MIN_PENDING_MS ?? "", 10);
|
|
15356
15362
|
return Number.isFinite(raw) && raw > 0 ? raw : 12e3;
|
|
15357
15363
|
}
|
|
15364
|
+
function composeProgressBody(step) {
|
|
15365
|
+
const s = (step ?? "").trim();
|
|
15366
|
+
if (!s) return "Working\u2026";
|
|
15367
|
+
if (/^working/i.test(s)) return s;
|
|
15368
|
+
return `Working\u2026 \xB7 ${s}`;
|
|
15369
|
+
}
|
|
15358
15370
|
function parseProgressHeartbeat(raw) {
|
|
15359
15371
|
if (!raw) return null;
|
|
15360
15372
|
try {
|
|
@@ -15368,6 +15380,83 @@ function parseProgressHeartbeat(raw) {
|
|
|
15368
15380
|
}
|
|
15369
15381
|
}
|
|
15370
15382
|
|
|
15383
|
+
// src/kanban-card-active-client.ts
|
|
15384
|
+
var REQUEST_TIMEOUT_MS = 8e3;
|
|
15385
|
+
var POSITIVE_TTL_MS = 10 * 6e4;
|
|
15386
|
+
var NEGATIVE_TTL_MS = 15e3;
|
|
15387
|
+
function createKanbanCardActiveClient(args) {
|
|
15388
|
+
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
15389
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
15390
|
+
const now = args.now ?? (() => Date.now());
|
|
15391
|
+
const positiveTtlMs = args.positiveTtlMs ?? POSITIVE_TTL_MS;
|
|
15392
|
+
const negativeTtlMs = args.negativeTtlMs ?? NEGATIVE_TTL_MS;
|
|
15393
|
+
const log = args.log ?? (() => {
|
|
15394
|
+
});
|
|
15395
|
+
const base = args.agtHost.replace(/\/+$/, "");
|
|
15396
|
+
const agentId = args.agentId;
|
|
15397
|
+
const apiKey = args.agtApiKey;
|
|
15398
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
15399
|
+
let cachedToken = null;
|
|
15400
|
+
let cachedTokenExpiresAt = 0;
|
|
15401
|
+
async function getToken() {
|
|
15402
|
+
if (cachedToken && now() < cachedTokenExpiresAt) return cachedToken;
|
|
15403
|
+
const resp = await fetchImpl(`${base}/host/exchange`, {
|
|
15404
|
+
method: "POST",
|
|
15405
|
+
headers: { "Content-Type": "application/json" },
|
|
15406
|
+
body: JSON.stringify({ host_key: apiKey }),
|
|
15407
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
15408
|
+
});
|
|
15409
|
+
if (!resp.ok) {
|
|
15410
|
+
const body = await resp.text().catch(() => "");
|
|
15411
|
+
throw new Error(`/host/exchange failed (${resp.status}): ${body.slice(0, 200)}`);
|
|
15412
|
+
}
|
|
15413
|
+
const data = await resp.json();
|
|
15414
|
+
cachedToken = data.token;
|
|
15415
|
+
cachedTokenExpiresAt = data.expires_at ? new Date(data.expires_at).getTime() - 12e4 : now() + 55 * 6e4;
|
|
15416
|
+
return cachedToken;
|
|
15417
|
+
}
|
|
15418
|
+
async function queryOnce(sourceIntegration, sourceExternalId) {
|
|
15419
|
+
const token = await getToken();
|
|
15420
|
+
const qs = new URLSearchParams({
|
|
15421
|
+
agent_id: agentId,
|
|
15422
|
+
source_integration: sourceIntegration,
|
|
15423
|
+
source_external_id: sourceExternalId
|
|
15424
|
+
});
|
|
15425
|
+
return fetchImpl(`${base}/host/kanban/progress-card-active?${qs.toString()}`, {
|
|
15426
|
+
method: "GET",
|
|
15427
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
15428
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
15429
|
+
});
|
|
15430
|
+
}
|
|
15431
|
+
async function query(sourceIntegration, sourceExternalId) {
|
|
15432
|
+
let resp = await queryOnce(sourceIntegration, sourceExternalId);
|
|
15433
|
+
if (resp.status === 401) {
|
|
15434
|
+
cachedToken = null;
|
|
15435
|
+
cachedTokenExpiresAt = 0;
|
|
15436
|
+
resp = await queryOnce(sourceIntegration, sourceExternalId);
|
|
15437
|
+
}
|
|
15438
|
+
if (!resp.ok) return false;
|
|
15439
|
+
const data = await resp.json();
|
|
15440
|
+
return data.active === true;
|
|
15441
|
+
}
|
|
15442
|
+
return {
|
|
15443
|
+
async isCardActive(sourceIntegration, sourceExternalId) {
|
|
15444
|
+
const key2 = `${sourceIntegration}:${sourceExternalId}`;
|
|
15445
|
+
const t = now();
|
|
15446
|
+
const hit = cache2.get(key2);
|
|
15447
|
+
if (hit && t < hit.expiresAt) return hit.active;
|
|
15448
|
+
try {
|
|
15449
|
+
const active = await query(sourceIntegration, sourceExternalId);
|
|
15450
|
+
cache2.set(key2, { active, expiresAt: t + (active ? positiveTtlMs : negativeTtlMs) });
|
|
15451
|
+
return active;
|
|
15452
|
+
} catch (err) {
|
|
15453
|
+
log(`kanban-card-active: query threw key=${key2}: ${err.message}`);
|
|
15454
|
+
return false;
|
|
15455
|
+
}
|
|
15456
|
+
}
|
|
15457
|
+
};
|
|
15458
|
+
}
|
|
15459
|
+
|
|
15371
15460
|
// src/slack-reply-threading.ts
|
|
15372
15461
|
function isSlackDmChannel(channel) {
|
|
15373
15462
|
return typeof channel === "string" && channel.startsWith("D");
|
|
@@ -16343,7 +16432,7 @@ function parsePeerAgentModeEnv(raw) {
|
|
|
16343
16432
|
}
|
|
16344
16433
|
|
|
16345
16434
|
// src/cross-team-peer-audit-client.ts
|
|
16346
|
-
var
|
|
16435
|
+
var REQUEST_TIMEOUT_MS2 = 1e4;
|
|
16347
16436
|
function createCrossTeamPeerAuditClient(args) {
|
|
16348
16437
|
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
16349
16438
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
@@ -16360,7 +16449,7 @@ function createCrossTeamPeerAuditClient(args) {
|
|
|
16360
16449
|
method: "POST",
|
|
16361
16450
|
headers: { "Content-Type": "application/json" },
|
|
16362
16451
|
body: JSON.stringify({ host_key: apiKey }),
|
|
16363
|
-
signal: AbortSignal.timeout(
|
|
16452
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
16364
16453
|
});
|
|
16365
16454
|
if (!resp.ok) {
|
|
16366
16455
|
const body = await resp.text().catch(() => "");
|
|
@@ -16380,7 +16469,7 @@ function createCrossTeamPeerAuditClient(args) {
|
|
|
16380
16469
|
"Content-Type": "application/json"
|
|
16381
16470
|
},
|
|
16382
16471
|
body: JSON.stringify({ agent_id: agentId, ...event }),
|
|
16383
|
-
signal: AbortSignal.timeout(
|
|
16472
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS2)
|
|
16384
16473
|
});
|
|
16385
16474
|
}
|
|
16386
16475
|
async function emitAsync(event) {
|
|
@@ -16409,7 +16498,7 @@ function createCrossTeamPeerAuditClient(args) {
|
|
|
16409
16498
|
}
|
|
16410
16499
|
|
|
16411
16500
|
// src/conversation-ingest-client.ts
|
|
16412
|
-
var
|
|
16501
|
+
var REQUEST_TIMEOUT_MS3 = 1e4;
|
|
16413
16502
|
function createConversationIngestClient(args) {
|
|
16414
16503
|
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
16415
16504
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
@@ -16426,7 +16515,7 @@ function createConversationIngestClient(args) {
|
|
|
16426
16515
|
method: "POST",
|
|
16427
16516
|
headers: { "Content-Type": "application/json" },
|
|
16428
16517
|
body: JSON.stringify({ host_key: apiKey }),
|
|
16429
|
-
signal: AbortSignal.timeout(
|
|
16518
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS3)
|
|
16430
16519
|
});
|
|
16431
16520
|
if (!resp.ok) {
|
|
16432
16521
|
const body = await resp.text().catch(() => "");
|
|
@@ -16449,7 +16538,7 @@ function createConversationIngestClient(args) {
|
|
|
16449
16538
|
method: "POST",
|
|
16450
16539
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
16451
16540
|
body: JSON.stringify({ agent_id: agentId, ...payload }),
|
|
16452
|
-
signal: AbortSignal.timeout(
|
|
16541
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS3)
|
|
16453
16542
|
});
|
|
16454
16543
|
}
|
|
16455
16544
|
function refKey(payload) {
|
|
@@ -16481,7 +16570,7 @@ function createConversationIngestClient(args) {
|
|
|
16481
16570
|
}
|
|
16482
16571
|
|
|
16483
16572
|
// src/inbound-context-client.ts
|
|
16484
|
-
var
|
|
16573
|
+
var REQUEST_TIMEOUT_MS4 = 1e4;
|
|
16485
16574
|
function createInboundContextClient(args) {
|
|
16486
16575
|
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
16487
16576
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
@@ -16498,7 +16587,7 @@ function createInboundContextClient(args) {
|
|
|
16498
16587
|
method: "POST",
|
|
16499
16588
|
headers: { "Content-Type": "application/json" },
|
|
16500
16589
|
body: JSON.stringify({ host_key: apiKey }),
|
|
16501
|
-
signal: AbortSignal.timeout(
|
|
16590
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS4)
|
|
16502
16591
|
});
|
|
16503
16592
|
if (!resp.ok) {
|
|
16504
16593
|
const body = await resp.text().catch(() => "");
|
|
@@ -16515,7 +16604,7 @@ function createInboundContextClient(args) {
|
|
|
16515
16604
|
method: "POST",
|
|
16516
16605
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
16517
16606
|
body: JSON.stringify(body),
|
|
16518
|
-
signal: AbortSignal.timeout(
|
|
16607
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS4)
|
|
16519
16608
|
});
|
|
16520
16609
|
}
|
|
16521
16610
|
async function emit(args2) {
|
|
@@ -16550,7 +16639,7 @@ function createInboundContextClient(args) {
|
|
|
16550
16639
|
}
|
|
16551
16640
|
|
|
16552
16641
|
// src/slack-bot-user-id-client.ts
|
|
16553
|
-
var
|
|
16642
|
+
var REQUEST_TIMEOUT_MS5 = 1e4;
|
|
16554
16643
|
function createSlackBotUserIdClient(args) {
|
|
16555
16644
|
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
16556
16645
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
@@ -16568,7 +16657,7 @@ function createSlackBotUserIdClient(args) {
|
|
|
16568
16657
|
method: "POST",
|
|
16569
16658
|
headers: { "Content-Type": "application/json" },
|
|
16570
16659
|
body: JSON.stringify({ host_key: apiKey }),
|
|
16571
|
-
signal: AbortSignal.timeout(
|
|
16660
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
|
|
16572
16661
|
});
|
|
16573
16662
|
if (!resp.ok) {
|
|
16574
16663
|
const body = await resp.text().catch(() => "");
|
|
@@ -16585,7 +16674,7 @@ function createSlackBotUserIdClient(args) {
|
|
|
16585
16674
|
method: "POST",
|
|
16586
16675
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
16587
16676
|
body: JSON.stringify({ agent_id: agentId, bot_user_id: botUserId2 }),
|
|
16588
|
-
signal: AbortSignal.timeout(
|
|
16677
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
|
|
16589
16678
|
});
|
|
16590
16679
|
}
|
|
16591
16680
|
async function emitAsync(botUserId2) {
|
|
@@ -16617,7 +16706,7 @@ function createSlackBotUserIdClient(args) {
|
|
|
16617
16706
|
method: "POST",
|
|
16618
16707
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
16619
16708
|
body: JSON.stringify({ agent_id: agentId, channel_id: "slack", healthy }),
|
|
16620
|
-
signal: AbortSignal.timeout(
|
|
16709
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
|
|
16621
16710
|
});
|
|
16622
16711
|
};
|
|
16623
16712
|
try {
|
|
@@ -16935,6 +17024,13 @@ var inboundContextClient = createInboundContextClient({
|
|
|
16935
17024
|
log: (line) => process.stderr.write(`slack-channel: ${line}
|
|
16936
17025
|
`)
|
|
16937
17026
|
});
|
|
17027
|
+
var kanbanCardActiveClient = createKanbanCardActiveClient({
|
|
17028
|
+
agtHost: AGT_HOST,
|
|
17029
|
+
agtApiKey: AGT_API_KEY,
|
|
17030
|
+
agentId: AGT_AGENT_ID,
|
|
17031
|
+
log: (line) => process.stderr.write(`slack-channel: ${line}
|
|
17032
|
+
`)
|
|
17033
|
+
});
|
|
16938
17034
|
var SLACK_PEER_CLASSIFIER_CONFIG = {
|
|
16939
17035
|
peer_agent_mode: parsePeerAgentModeEnv(process.env.SLACK_PEER_AGENT_MODE),
|
|
16940
17036
|
peer_group_ids: parsePeerGroupIdsEnv(process.env.SLACK_PEER_GROUP_IDS),
|
|
@@ -17535,7 +17631,7 @@ function findSlackProgressTarget() {
|
|
|
17535
17631
|
}
|
|
17536
17632
|
var SLACK_PROGRESS_PREFIX = "\u23F3";
|
|
17537
17633
|
function slackProgressBlocks(step) {
|
|
17538
|
-
const text = `${SLACK_PROGRESS_PREFIX}
|
|
17634
|
+
const text = `${SLACK_PROGRESS_PREFIX} _${composeProgressBody(step)}_`;
|
|
17539
17635
|
return [{ type: "context", elements: [{ type: "mrkdwn", text }] }];
|
|
17540
17636
|
}
|
|
17541
17637
|
async function postSlackProgress(channel, threadTs, step) {
|
|
@@ -17547,7 +17643,7 @@ async function postSlackProgress(channel, threadTs, step) {
|
|
|
17547
17643
|
body: JSON.stringify({
|
|
17548
17644
|
channel,
|
|
17549
17645
|
thread_ts: threadTs,
|
|
17550
|
-
text: `${SLACK_PROGRESS_PREFIX}
|
|
17646
|
+
text: `${SLACK_PROGRESS_PREFIX} ${composeProgressBody(step)}`,
|
|
17551
17647
|
blocks: slackProgressBlocks(step)
|
|
17552
17648
|
}),
|
|
17553
17649
|
signal: AbortSignal.timeout(8e3)
|
|
@@ -17567,7 +17663,7 @@ async function updateSlackProgress(channel, ts, step) {
|
|
|
17567
17663
|
body: JSON.stringify({
|
|
17568
17664
|
channel,
|
|
17569
17665
|
ts,
|
|
17570
|
-
text: `${SLACK_PROGRESS_PREFIX}
|
|
17666
|
+
text: `${SLACK_PROGRESS_PREFIX} ${composeProgressBody(step)}`,
|
|
17571
17667
|
blocks: slackProgressBlocks(step)
|
|
17572
17668
|
}),
|
|
17573
17669
|
signal: AbortSignal.timeout(8e3)
|
|
@@ -17605,14 +17701,22 @@ async function slackProgressTick() {
|
|
|
17605
17701
|
}
|
|
17606
17702
|
return;
|
|
17607
17703
|
}
|
|
17608
|
-
const
|
|
17704
|
+
const baseInput = {
|
|
17609
17705
|
now: Date.now(),
|
|
17610
17706
|
heartbeat: readSlackProgressHeartbeat(),
|
|
17611
17707
|
target: findSlackProgressTarget(),
|
|
17612
17708
|
tracked: slackTrackedProgress,
|
|
17613
17709
|
freshnessMs: progressHeartbeatFreshMs(),
|
|
17614
17710
|
minPendingMs: progressMinPendingMs()
|
|
17615
|
-
}
|
|
17711
|
+
};
|
|
17712
|
+
let action = decideProgressAction(baseInput);
|
|
17713
|
+
if (kanbanCardActiveClient && baseInput.target && (action.type === "post" || action.type === "update" || action.type === "none" && slackTrackedProgress)) {
|
|
17714
|
+
const hasCard = await kanbanCardActiveClient.isCardActive(
|
|
17715
|
+
"slack",
|
|
17716
|
+
`${baseInput.target.channel}:${baseInput.target.threadTs}`
|
|
17717
|
+
);
|
|
17718
|
+
if (hasCard) action = decideProgressAction({ ...baseInput, targetHasCard: true });
|
|
17719
|
+
}
|
|
17616
17720
|
switch (action.type) {
|
|
17617
17721
|
case "post": {
|
|
17618
17722
|
const ts = await postSlackProgress(action.channel, action.threadTs, action.step);
|
|
@@ -16334,6 +16334,12 @@ function decideProgressAction(input) {
|
|
|
16334
16334
|
const { now, heartbeat, target, tracked, freshnessMs, minPendingMs } = input;
|
|
16335
16335
|
const fresh = heartbeat != null && now - heartbeat.updatedAtMs <= freshnessMs;
|
|
16336
16336
|
const active = target != null && fresh;
|
|
16337
|
+
if (active && input.targetHasCard === true) {
|
|
16338
|
+
if (tracked) {
|
|
16339
|
+
return { type: "delete", channel: tracked.channel, threadTs: tracked.threadTs, ts: tracked.ts };
|
|
16340
|
+
}
|
|
16341
|
+
return { type: "none" };
|
|
16342
|
+
}
|
|
16337
16343
|
if (!active) {
|
|
16338
16344
|
if (tracked) {
|
|
16339
16345
|
return { type: "delete", channel: tracked.channel, threadTs: tracked.threadTs, ts: tracked.ts };
|
|
@@ -16362,6 +16368,12 @@ function progressMinPendingMs() {
|
|
|
16362
16368
|
const raw = parseInt(process.env.AGT_CHANNEL_PROGRESS_MIN_PENDING_MS ?? "", 10);
|
|
16363
16369
|
return Number.isFinite(raw) && raw > 0 ? raw : 12e3;
|
|
16364
16370
|
}
|
|
16371
|
+
function composeProgressBody(step) {
|
|
16372
|
+
const s = (step ?? "").trim();
|
|
16373
|
+
if (!s) return "Working\u2026";
|
|
16374
|
+
if (/^working/i.test(s)) return s;
|
|
16375
|
+
return `Working\u2026 \xB7 ${s}`;
|
|
16376
|
+
}
|
|
16365
16377
|
function parseProgressHeartbeat(raw) {
|
|
16366
16378
|
if (!raw) return null;
|
|
16367
16379
|
try {
|
|
@@ -16375,6 +16387,83 @@ function parseProgressHeartbeat(raw) {
|
|
|
16375
16387
|
}
|
|
16376
16388
|
}
|
|
16377
16389
|
|
|
16390
|
+
// src/kanban-card-active-client.ts
|
|
16391
|
+
var REQUEST_TIMEOUT_MS6 = 8e3;
|
|
16392
|
+
var POSITIVE_TTL_MS = 10 * 6e4;
|
|
16393
|
+
var NEGATIVE_TTL_MS = 15e3;
|
|
16394
|
+
function createKanbanCardActiveClient(args) {
|
|
16395
|
+
if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
|
|
16396
|
+
const fetchImpl = args.fetchImpl ?? fetch;
|
|
16397
|
+
const now = args.now ?? (() => Date.now());
|
|
16398
|
+
const positiveTtlMs = args.positiveTtlMs ?? POSITIVE_TTL_MS;
|
|
16399
|
+
const negativeTtlMs = args.negativeTtlMs ?? NEGATIVE_TTL_MS;
|
|
16400
|
+
const log = args.log ?? (() => {
|
|
16401
|
+
});
|
|
16402
|
+
const base = args.agtHost.replace(/\/+$/, "");
|
|
16403
|
+
const agentId = args.agentId;
|
|
16404
|
+
const apiKey = args.agtApiKey;
|
|
16405
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
16406
|
+
let cachedToken = null;
|
|
16407
|
+
let cachedTokenExpiresAt = 0;
|
|
16408
|
+
async function getToken() {
|
|
16409
|
+
if (cachedToken && now() < cachedTokenExpiresAt) return cachedToken;
|
|
16410
|
+
const resp = await fetchImpl(`${base}/host/exchange`, {
|
|
16411
|
+
method: "POST",
|
|
16412
|
+
headers: { "Content-Type": "application/json" },
|
|
16413
|
+
body: JSON.stringify({ host_key: apiKey }),
|
|
16414
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS6)
|
|
16415
|
+
});
|
|
16416
|
+
if (!resp.ok) {
|
|
16417
|
+
const body = await resp.text().catch(() => "");
|
|
16418
|
+
throw new Error(`/host/exchange failed (${resp.status}): ${body.slice(0, 200)}`);
|
|
16419
|
+
}
|
|
16420
|
+
const data = await resp.json();
|
|
16421
|
+
cachedToken = data.token;
|
|
16422
|
+
cachedTokenExpiresAt = data.expires_at ? new Date(data.expires_at).getTime() - 12e4 : now() + 55 * 6e4;
|
|
16423
|
+
return cachedToken;
|
|
16424
|
+
}
|
|
16425
|
+
async function queryOnce(sourceIntegration, sourceExternalId) {
|
|
16426
|
+
const token = await getToken();
|
|
16427
|
+
const qs = new URLSearchParams({
|
|
16428
|
+
agent_id: agentId,
|
|
16429
|
+
source_integration: sourceIntegration,
|
|
16430
|
+
source_external_id: sourceExternalId
|
|
16431
|
+
});
|
|
16432
|
+
return fetchImpl(`${base}/host/kanban/progress-card-active?${qs.toString()}`, {
|
|
16433
|
+
method: "GET",
|
|
16434
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
16435
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS6)
|
|
16436
|
+
});
|
|
16437
|
+
}
|
|
16438
|
+
async function query(sourceIntegration, sourceExternalId) {
|
|
16439
|
+
let resp = await queryOnce(sourceIntegration, sourceExternalId);
|
|
16440
|
+
if (resp.status === 401) {
|
|
16441
|
+
cachedToken = null;
|
|
16442
|
+
cachedTokenExpiresAt = 0;
|
|
16443
|
+
resp = await queryOnce(sourceIntegration, sourceExternalId);
|
|
16444
|
+
}
|
|
16445
|
+
if (!resp.ok) return false;
|
|
16446
|
+
const data = await resp.json();
|
|
16447
|
+
return data.active === true;
|
|
16448
|
+
}
|
|
16449
|
+
return {
|
|
16450
|
+
async isCardActive(sourceIntegration, sourceExternalId) {
|
|
16451
|
+
const key2 = `${sourceIntegration}:${sourceExternalId}`;
|
|
16452
|
+
const t = now();
|
|
16453
|
+
const hit = cache2.get(key2);
|
|
16454
|
+
if (hit && t < hit.expiresAt) return hit.active;
|
|
16455
|
+
try {
|
|
16456
|
+
const active = await query(sourceIntegration, sourceExternalId);
|
|
16457
|
+
cache2.set(key2, { active, expiresAt: t + (active ? positiveTtlMs : negativeTtlMs) });
|
|
16458
|
+
return active;
|
|
16459
|
+
} catch (err) {
|
|
16460
|
+
log(`kanban-card-active: query threw key=${key2}: ${err.message}`);
|
|
16461
|
+
return false;
|
|
16462
|
+
}
|
|
16463
|
+
}
|
|
16464
|
+
};
|
|
16465
|
+
}
|
|
16466
|
+
|
|
16378
16467
|
// src/mcp-spawn-lock.ts
|
|
16379
16468
|
import {
|
|
16380
16469
|
existsSync as existsSync5,
|
|
@@ -16734,6 +16823,13 @@ var inboundContextClient = createInboundContextClient({
|
|
|
16734
16823
|
log: (line) => process.stderr.write(`telegram-channel(${AGENT_CODE_NAME}): ${line}
|
|
16735
16824
|
`)
|
|
16736
16825
|
});
|
|
16826
|
+
var kanbanCardActiveClient = createKanbanCardActiveClient({
|
|
16827
|
+
agtHost: AGT_HOST,
|
|
16828
|
+
agtApiKey: AGT_API_KEY,
|
|
16829
|
+
agentId: process.env.AGT_AGENT_ID ?? null,
|
|
16830
|
+
log: (line) => process.stderr.write(`telegram-channel(${AGENT_CODE_NAME}): ${line}
|
|
16831
|
+
`)
|
|
16832
|
+
});
|
|
16737
16833
|
var peerRateApiClient = createDefaultPeerRateApiClient({
|
|
16738
16834
|
agtHost: AGT_HOST,
|
|
16739
16835
|
agtApiKey: AGT_API_KEY,
|
|
@@ -18105,7 +18201,7 @@ function findTelegramProgressTarget() {
|
|
|
18105
18201
|
}
|
|
18106
18202
|
var TELEGRAM_PROGRESS_PREFIX = "\u23F3";
|
|
18107
18203
|
function telegramProgressText(step) {
|
|
18108
|
-
return `${TELEGRAM_PROGRESS_PREFIX}
|
|
18204
|
+
return `${TELEGRAM_PROGRESS_PREFIX} ${composeProgressBody(step)}`;
|
|
18109
18205
|
}
|
|
18110
18206
|
async function postTelegramProgress(chatId, step) {
|
|
18111
18207
|
if (!BOT_TOKEN) return null;
|
|
@@ -18158,14 +18254,19 @@ async function telegramProgressTick() {
|
|
|
18158
18254
|
}
|
|
18159
18255
|
return;
|
|
18160
18256
|
}
|
|
18161
|
-
const
|
|
18257
|
+
const baseInput = {
|
|
18162
18258
|
now: Date.now(),
|
|
18163
18259
|
heartbeat: readTelegramProgressHeartbeat(),
|
|
18164
18260
|
target: findTelegramProgressTarget(),
|
|
18165
18261
|
tracked: telegramTrackedProgress,
|
|
18166
18262
|
freshnessMs: progressHeartbeatFreshMs(),
|
|
18167
18263
|
minPendingMs: progressMinPendingMs()
|
|
18168
|
-
}
|
|
18264
|
+
};
|
|
18265
|
+
let action = decideProgressAction(baseInput);
|
|
18266
|
+
if (kanbanCardActiveClient && baseInput.target && (action.type === "post" || action.type === "update" || action.type === "none" && telegramTrackedProgress)) {
|
|
18267
|
+
const hasCard = await kanbanCardActiveClient.isCardActive("telegram", baseInput.target.channel);
|
|
18268
|
+
if (hasCard) action = decideProgressAction({ ...baseInput, targetHasCard: true });
|
|
18269
|
+
}
|
|
18169
18270
|
switch (action.type) {
|
|
18170
18271
|
case "post": {
|
|
18171
18272
|
const id = await postTelegramProgress(action.channel, action.step);
|
package/package.json
CHANGED
|
File without changes
|