@integrity-labs/agt-cli 0.28.205 → 0.28.207
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-7VPPMJA6.js → chunk-ELBYWACS.js} +15 -1
- package/dist/chunk-ELBYWACS.js.map +1 -0
- package/dist/{chunk-P2VXGL63.js → chunk-GWBOA7ZY.js} +2 -2
- package/dist/{chunk-46I4PFYV.js → chunk-TPFTAFG3.js} +3 -3
- package/dist/{claude-pair-runtime-K2G3ZQGH.js → claude-pair-runtime-Q4Q2OTTV.js} +2 -2
- package/dist/lib/manager-worker.js +197 -9
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +131 -3
- package/dist/{persistent-session-4B36WJ4A.js → persistent-session-6662WBSH.js} +3 -3
- package/dist/{responsiveness-probe-JPUF2QPK.js → responsiveness-probe-TOLTTG6I.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-7VPPMJA6.js.map +0 -1
- /package/dist/{chunk-P2VXGL63.js.map → chunk-GWBOA7ZY.js.map} +0 -0
- /package/dist/{chunk-46I4PFYV.js.map → chunk-TPFTAFG3.js.map} +0 -0
- /package/dist/{claude-pair-runtime-K2G3ZQGH.js.map → claude-pair-runtime-Q4Q2OTTV.js.map} +0 -0
- /package/dist/{persistent-session-4B36WJ4A.js.map → persistent-session-6662WBSH.js.map} +0 -0
- /package/dist/{responsiveness-probe-JPUF2QPK.js.map → responsiveness-probe-TOLTTG6I.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
formatMissingVar,
|
|
4
4
|
isClaudeFastMode,
|
|
5
5
|
probeMcpEnvSubstitution
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ELBYWACS.js";
|
|
7
7
|
import {
|
|
8
8
|
reapOrphanChannelMcps
|
|
9
9
|
} from "./chunk-XWVM4KPK.js";
|
|
@@ -1631,4 +1631,4 @@ export {
|
|
|
1631
1631
|
stopAllSessionsAndWait,
|
|
1632
1632
|
getProjectDir
|
|
1633
1633
|
};
|
|
1634
|
-
//# sourceMappingURL=chunk-
|
|
1634
|
+
//# sourceMappingURL=chunk-GWBOA7ZY.js.map
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveConnectivityProbe,
|
|
18
18
|
worseConnectivityOutcome,
|
|
19
19
|
wrapScheduledTaskPrompt
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ELBYWACS.js";
|
|
21
21
|
|
|
22
22
|
// ../../packages/core/dist/provisioning/mcp-config-guards.js
|
|
23
23
|
import { chmodSync, existsSync, readFileSync, renameSync, writeFileSync, unlinkSync } from "fs";
|
|
@@ -5525,7 +5525,7 @@ function requireHost() {
|
|
|
5525
5525
|
}
|
|
5526
5526
|
|
|
5527
5527
|
// src/lib/api-client.ts
|
|
5528
|
-
var agtCliVersion = true ? "0.28.
|
|
5528
|
+
var agtCliVersion = true ? "0.28.207" : "dev";
|
|
5529
5529
|
var lastConfigHash = null;
|
|
5530
5530
|
function setConfigHash(hash) {
|
|
5531
5531
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -6833,4 +6833,4 @@ export {
|
|
|
6833
6833
|
managerInstallSystemUnitCommand,
|
|
6834
6834
|
managerUninstallSystemUnitCommand
|
|
6835
6835
|
};
|
|
6836
|
-
//# sourceMappingURL=chunk-
|
|
6836
|
+
//# sourceMappingURL=chunk-TPFTAFG3.js.map
|
|
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
|
|
|
100
100
|
return { ok: true };
|
|
101
101
|
} catch {
|
|
102
102
|
}
|
|
103
|
-
const { resolveClaudeBinary } = await import("./persistent-session-
|
|
103
|
+
const { resolveClaudeBinary } = await import("./persistent-session-6662WBSH.js");
|
|
104
104
|
const claudeBin = resolveClaudeBinary();
|
|
105
105
|
const pairEnv = {
|
|
106
106
|
...process.env,
|
|
@@ -373,4 +373,4 @@ export {
|
|
|
373
373
|
startClaudePair,
|
|
374
374
|
submitClaudePairCode
|
|
375
375
|
};
|
|
376
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
376
|
+
//# sourceMappingURL=claude-pair-runtime-Q4Q2OTTV.js.map
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
requireHost,
|
|
29
29
|
safeWriteJsonAtomic,
|
|
30
30
|
setConfigHash
|
|
31
|
-
} from "../chunk-
|
|
31
|
+
} from "../chunk-TPFTAFG3.js";
|
|
32
32
|
import {
|
|
33
33
|
getProjectDir as getProjectDir2,
|
|
34
34
|
getReadyTasks,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
takeZombieDetection,
|
|
71
71
|
transcriptActivityAgeSeconds,
|
|
72
72
|
writeEgressAllowlist
|
|
73
|
-
} from "../chunk-
|
|
73
|
+
} from "../chunk-GWBOA7ZY.js";
|
|
74
74
|
import {
|
|
75
75
|
CONVERSATION_FAILURE_CATEGORIES,
|
|
76
76
|
DEFAULT_FRAMEWORK,
|
|
@@ -114,7 +114,7 @@ import {
|
|
|
114
114
|
resolveChannels,
|
|
115
115
|
resolveDmTarget,
|
|
116
116
|
sumTranscriptUsageInWindow
|
|
117
|
-
} from "../chunk-
|
|
117
|
+
} from "../chunk-ELBYWACS.js";
|
|
118
118
|
import {
|
|
119
119
|
parsePsRows,
|
|
120
120
|
reapOrphanChannelMcps
|
|
@@ -1804,6 +1804,116 @@ function isDirectChatMessageExpired(createdAt, nowMs, maxAgeMs) {
|
|
|
1804
1804
|
return nowMs - created > maxAgeMs;
|
|
1805
1805
|
}
|
|
1806
1806
|
|
|
1807
|
+
// src/lib/session-tool-probe.ts
|
|
1808
|
+
function classifyMcpServer(entry) {
|
|
1809
|
+
if (!entry || typeof entry !== "object") return "unknown";
|
|
1810
|
+
const e = entry;
|
|
1811
|
+
if (typeof e.command === "string") return "stdio";
|
|
1812
|
+
if (typeof e.url === "string") return "http";
|
|
1813
|
+
return "unknown";
|
|
1814
|
+
}
|
|
1815
|
+
function splitServerKeysByKind(mcpJson, serverKeys) {
|
|
1816
|
+
const servers = mcpJson?.mcpServers ?? {};
|
|
1817
|
+
const stdio = [];
|
|
1818
|
+
const http = [];
|
|
1819
|
+
for (const key of serverKeys) {
|
|
1820
|
+
const kind = classifyMcpServer(servers[key]);
|
|
1821
|
+
if (kind === "stdio") stdio.push(key);
|
|
1822
|
+
else if (kind === "http") http.push(key);
|
|
1823
|
+
}
|
|
1824
|
+
return { stdio, http };
|
|
1825
|
+
}
|
|
1826
|
+
function computeSessionToolBindStatus(input) {
|
|
1827
|
+
const { stdioServerKeys, httpServerKeys, missingStdioKeys, httpReachable, httpSessionLoaded } = input;
|
|
1828
|
+
if (stdioServerKeys.length === 0 && httpServerKeys.length === 0) return "unknown";
|
|
1829
|
+
if (stdioServerKeys.some((k) => missingStdioKeys.has(k))) return "missing";
|
|
1830
|
+
let anyHttpUnconfirmed = false;
|
|
1831
|
+
for (const k of httpServerKeys) {
|
|
1832
|
+
const reachable = httpReachable.get(k);
|
|
1833
|
+
if (reachable === false) return "unreachable";
|
|
1834
|
+
if (reachable === void 0) {
|
|
1835
|
+
anyHttpUnconfirmed = true;
|
|
1836
|
+
} else if (!httpSessionLoaded) {
|
|
1837
|
+
anyHttpUnconfirmed = true;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
if (anyHttpUnconfirmed && stdioServerKeys.length === 0) return "unknown";
|
|
1841
|
+
return "bound";
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
// src/lib/session-tool-bind-runner.ts
|
|
1845
|
+
var DEFAULT_INTERVAL_MS2 = 60 * 60 * 1e3;
|
|
1846
|
+
var DEFAULT_MAX_PER_RUN2 = 25;
|
|
1847
|
+
function sanitizeServerKey(definitionId) {
|
|
1848
|
+
return definitionId.replace(/[^a-z0-9]/gi, "_").toLowerCase();
|
|
1849
|
+
}
|
|
1850
|
+
function resolveIntegrationServerKeys(definitionId, declaredKeys, hint) {
|
|
1851
|
+
const declared = new Set(declaredKeys);
|
|
1852
|
+
const candidates = [hint, definitionId, sanitizeServerKey(definitionId)].filter(
|
|
1853
|
+
(k) => typeof k === "string" && k.length > 0
|
|
1854
|
+
);
|
|
1855
|
+
const out = /* @__PURE__ */ new Set();
|
|
1856
|
+
for (const c of candidates) if (declared.has(c)) out.add(c);
|
|
1857
|
+
return [...out];
|
|
1858
|
+
}
|
|
1859
|
+
function isDue2(last, now, intervalMs) {
|
|
1860
|
+
if (!last) return true;
|
|
1861
|
+
const t = Date.parse(last);
|
|
1862
|
+
if (Number.isNaN(t)) return true;
|
|
1863
|
+
return now - t >= intervalMs;
|
|
1864
|
+
}
|
|
1865
|
+
async function runSessionToolBindProbes(integrations, options) {
|
|
1866
|
+
const now = (options.now?.() ?? /* @__PURE__ */ new Date()).getTime();
|
|
1867
|
+
const intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS2;
|
|
1868
|
+
const maxPerRun = options.maxPerRun ?? DEFAULT_MAX_PER_RUN2;
|
|
1869
|
+
const due = integrations.filter((i) => isDue2(i.last_session_tool_bind_at, now, intervalMs)).sort((a, b) => {
|
|
1870
|
+
const ta = a.last_session_tool_bind_at ? Date.parse(a.last_session_tool_bind_at) : 0;
|
|
1871
|
+
const tb = b.last_session_tool_bind_at ? Date.parse(b.last_session_tool_bind_at) : 0;
|
|
1872
|
+
return ta - tb;
|
|
1873
|
+
});
|
|
1874
|
+
const batch = due.slice(0, maxPerRun);
|
|
1875
|
+
const declaredKeys = Object.keys(options.mcpJson?.mcpServers ?? {});
|
|
1876
|
+
const reports = [];
|
|
1877
|
+
let skipped = 0;
|
|
1878
|
+
let probed = 0;
|
|
1879
|
+
for (const integ of batch) {
|
|
1880
|
+
const keys = resolveIntegrationServerKeys(
|
|
1881
|
+
integ.definition_id,
|
|
1882
|
+
declaredKeys,
|
|
1883
|
+
integ.mcp_server_key
|
|
1884
|
+
);
|
|
1885
|
+
if (keys.length === 0) {
|
|
1886
|
+
skipped += 1;
|
|
1887
|
+
continue;
|
|
1888
|
+
}
|
|
1889
|
+
probed += 1;
|
|
1890
|
+
const { stdio, http } = splitServerKeysByKind(options.mcpJson, keys);
|
|
1891
|
+
const httpReachable = /* @__PURE__ */ new Map();
|
|
1892
|
+
for (const key of http) {
|
|
1893
|
+
let reachable;
|
|
1894
|
+
try {
|
|
1895
|
+
reachable = await options.probeHttp(key);
|
|
1896
|
+
} catch {
|
|
1897
|
+
reachable = void 0;
|
|
1898
|
+
}
|
|
1899
|
+
if (reachable !== void 0) httpReachable.set(key, reachable);
|
|
1900
|
+
}
|
|
1901
|
+
const status = computeSessionToolBindStatus({
|
|
1902
|
+
stdioServerKeys: stdio,
|
|
1903
|
+
httpServerKeys: http,
|
|
1904
|
+
missingStdioKeys: options.missingStdioKeys,
|
|
1905
|
+
httpReachable,
|
|
1906
|
+
httpSessionLoaded: options.httpSessionLoaded ?? false
|
|
1907
|
+
});
|
|
1908
|
+
if (status === "unknown") {
|
|
1909
|
+
skipped += 1;
|
|
1910
|
+
continue;
|
|
1911
|
+
}
|
|
1912
|
+
reports.push({ integration_id: integ.id, scope: integ.scope, status });
|
|
1913
|
+
}
|
|
1914
|
+
return { reports, due: due.length, probed, skipped };
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1807
1917
|
// ../../packages/core/dist/host-config/capture.js
|
|
1808
1918
|
import { createHash as createHash3 } from "crypto";
|
|
1809
1919
|
var NON_SECRET_ENV_GATES = [
|
|
@@ -6504,6 +6614,76 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
|
|
|
6504
6614
|
);
|
|
6505
6615
|
}
|
|
6506
6616
|
}
|
|
6617
|
+
async function runAgentSessionToolBindProbes(agent, integrations, projectDir) {
|
|
6618
|
+
if (integrations.length === 0) return;
|
|
6619
|
+
let mcpJson = null;
|
|
6620
|
+
try {
|
|
6621
|
+
mcpJson = JSON.parse(readFileSync14(join16(projectDir, ".mcp.json"), "utf-8"));
|
|
6622
|
+
} catch {
|
|
6623
|
+
return;
|
|
6624
|
+
}
|
|
6625
|
+
if (!mcpJson?.mcpServers || Object.keys(mcpJson.mcpServers).length === 0) return;
|
|
6626
|
+
const isolated = isolationMode(agent.code_name) === "docker";
|
|
6627
|
+
let missingStdioKeys = /* @__PURE__ */ new Set();
|
|
6628
|
+
try {
|
|
6629
|
+
const psOutput = isolated ? syncExecFile("docker", ["exec", `agt-${agent.code_name}`, "ps", "-eo", "pid,ppid,args"], {
|
|
6630
|
+
encoding: "utf-8",
|
|
6631
|
+
timeout: 8e3
|
|
6632
|
+
}) : syncExecFile("ps", ["-eo", "pid,ppid,args"], { encoding: "utf-8", timeout: 5e3 });
|
|
6633
|
+
missingStdioKeys = new Set(
|
|
6634
|
+
findMissingMcpServers({
|
|
6635
|
+
rows: parsePsRows(psOutput),
|
|
6636
|
+
codeName: agent.code_name,
|
|
6637
|
+
mcpJson,
|
|
6638
|
+
inContainer: isolated
|
|
6639
|
+
})
|
|
6640
|
+
);
|
|
6641
|
+
} catch {
|
|
6642
|
+
}
|
|
6643
|
+
const probeEnv = buildProbeEnv(projectDir);
|
|
6644
|
+
const probeDeps = buildConnectivityProbeDeps(projectDir, probeEnv);
|
|
6645
|
+
const probeHttp = async (serverKey) => {
|
|
6646
|
+
if (!probeDeps.mcpProbe) return void 0;
|
|
6647
|
+
const outcome = await probeDeps.mcpProbe({ serverKey, definitionId: serverKey });
|
|
6648
|
+
if (outcome.status === "ok") return true;
|
|
6649
|
+
if (outcome.status === "down") return false;
|
|
6650
|
+
return void 0;
|
|
6651
|
+
};
|
|
6652
|
+
let httpSessionLoaded = false;
|
|
6653
|
+
try {
|
|
6654
|
+
const sessionStartedMs = getSessionState(agent.code_name)?.startedAt ?? null;
|
|
6655
|
+
const mcpMtimeMs = statSync4(join16(projectDir, ".mcp.json")).mtimeMs;
|
|
6656
|
+
httpSessionLoaded = sessionStartedMs != null && sessionStartedMs >= mcpMtimeMs;
|
|
6657
|
+
} catch {
|
|
6658
|
+
}
|
|
6659
|
+
const intervalSec = Number(process.env.AGT_CONNECTIVITY_PROBE_INTERVAL_SECONDS) || 3600;
|
|
6660
|
+
const result = await runSessionToolBindProbes(
|
|
6661
|
+
integrations.map((i) => ({
|
|
6662
|
+
id: i.id,
|
|
6663
|
+
definition_id: i.definition_id,
|
|
6664
|
+
scope: i.scope,
|
|
6665
|
+
last_session_tool_bind_at: i.last_session_tool_bind_at ?? null,
|
|
6666
|
+
// Server-key hint for managed/remote-MCP kinds; the runner also tries the
|
|
6667
|
+
// raw + sanitised definition_id against the real `.mcp.json` keys.
|
|
6668
|
+
mcp_server_key: deriveMcpServerKey({
|
|
6669
|
+
definitionId: i.definition_id,
|
|
6670
|
+
sourceType: i.source_type ?? null,
|
|
6671
|
+
authType: i.auth_type,
|
|
6672
|
+
connectivityTest: i.connectivity_test ?? null
|
|
6673
|
+
})
|
|
6674
|
+
})),
|
|
6675
|
+
{ mcpJson, missingStdioKeys, probeHttp, httpSessionLoaded, intervalMs: intervalSec * 1e3 }
|
|
6676
|
+
);
|
|
6677
|
+
if (result.reports.length > 0) {
|
|
6678
|
+
await api.post("/host/session-tool-bind", {
|
|
6679
|
+
agent_id: agent.agent_id,
|
|
6680
|
+
results: result.reports
|
|
6681
|
+
});
|
|
6682
|
+
log(
|
|
6683
|
+
`Session-tool-bind probe for '${agent.code_name}': probed=${result.probed} reported=${result.reports.length} due=${result.due}`
|
|
6684
|
+
);
|
|
6685
|
+
}
|
|
6686
|
+
}
|
|
6507
6687
|
function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gateReason = breakerReason) {
|
|
6508
6688
|
const gate = restartGateFor(codeName, gateReason);
|
|
6509
6689
|
if (gate !== "bypass" && gate !== "proceed") {
|
|
@@ -6686,7 +6866,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
6686
6866
|
var lastVersionCheckAt = 0;
|
|
6687
6867
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6688
6868
|
var lastResponsivenessProbeAt = 0;
|
|
6689
|
-
var agtCliVersion = true ? "0.28.
|
|
6869
|
+
var agtCliVersion = true ? "0.28.207" : "dev";
|
|
6690
6870
|
function resolveBrewPath(execFileSync4) {
|
|
6691
6871
|
try {
|
|
6692
6872
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -7595,7 +7775,7 @@ async function pollCycle() {
|
|
|
7595
7775
|
}
|
|
7596
7776
|
try {
|
|
7597
7777
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
7598
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
7778
|
+
const { collectDiagnostics } = await import("../persistent-session-6662WBSH.js");
|
|
7599
7779
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
7600
7780
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
7601
7781
|
let tailscaleHostname;
|
|
@@ -7743,7 +7923,7 @@ async function pollCycle() {
|
|
|
7743
7923
|
const {
|
|
7744
7924
|
collectResponsivenessProbes,
|
|
7745
7925
|
getResponsivenessIntervalMs
|
|
7746
|
-
} = await import("../responsiveness-probe-
|
|
7926
|
+
} = await import("../responsiveness-probe-TOLTTG6I.js");
|
|
7747
7927
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
7748
7928
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
7749
7929
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -7775,7 +7955,7 @@ async function pollCycle() {
|
|
|
7775
7955
|
collectResponsivenessProbes,
|
|
7776
7956
|
livePendingInboundOldestAgeSeconds,
|
|
7777
7957
|
parkPendingInbound
|
|
7778
|
-
} = await import("../responsiveness-probe-
|
|
7958
|
+
} = await import("../responsiveness-probe-TOLTTG6I.js");
|
|
7779
7959
|
const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
7780
7960
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
7781
7961
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -9135,7 +9315,7 @@ async function processAgent(agent, agentStates) {
|
|
|
9135
9315
|
log(`OAuth token refresh failed for '${agent.code_name}/${integration.definition_id}': ${err.message}`);
|
|
9136
9316
|
}
|
|
9137
9317
|
}
|
|
9138
|
-
if (
|
|
9318
|
+
if (hostFlagStore().getBoolean("connectivity-probe")) {
|
|
9139
9319
|
try {
|
|
9140
9320
|
const probeProjectDir = join16(homedir9(), ".augmented", agent.code_name, "project");
|
|
9141
9321
|
await runAgentConnectivityProbes(agent, integrations, probeProjectDir);
|
|
@@ -9143,6 +9323,14 @@ async function processAgent(agent, agentStates) {
|
|
|
9143
9323
|
log(`Connectivity probe failed for '${agent.code_name}': ${err.message}`);
|
|
9144
9324
|
}
|
|
9145
9325
|
}
|
|
9326
|
+
if (hostFlagStore().getBoolean("session-tool-probe")) {
|
|
9327
|
+
try {
|
|
9328
|
+
const probeProjectDir = join16(homedir9(), ".augmented", agent.code_name, "project");
|
|
9329
|
+
await runAgentSessionToolBindProbes(agent, integrations, probeProjectDir);
|
|
9330
|
+
} catch (err) {
|
|
9331
|
+
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
9332
|
+
}
|
|
9333
|
+
}
|
|
9146
9334
|
if (integrations.length > 0) {
|
|
9147
9335
|
const intHash = computeIntegrationsHash(integrations);
|
|
9148
9336
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
@@ -10794,7 +10982,7 @@ async function processClaudePairSessions(agents) {
|
|
|
10794
10982
|
killPairSession,
|
|
10795
10983
|
pairTmuxSession,
|
|
10796
10984
|
finalizeClaudePairOnboarding
|
|
10797
|
-
} = await import("../claude-pair-runtime-
|
|
10985
|
+
} = await import("../claude-pair-runtime-Q4Q2OTTV.js");
|
|
10798
10986
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
10799
10987
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
10800
10988
|
const killed = await killPairSession(pairTmuxSession(pairId));
|