@integrity-labs/agt-cli 0.6.6 → 0.6.7
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 +433 -54
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-EUF2V4N5.js → chunk-UIWXBJSX.js} +98 -20
- package/dist/chunk-UIWXBJSX.js.map +1 -0
- package/dist/host-security-6PDFG7F5.js +36 -0
- package/dist/host-security-6PDFG7F5.js.map +1 -0
- package/dist/lib/manager-worker.js +77 -6
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +5 -3
- package/dist/chunk-EUF2V4N5.js.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/lib/host-security.ts
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
var SOCKETFILTERFW = "/usr/libexec/ApplicationFirewall/socketfilterfw";
|
|
5
|
+
function runCommand(cmd) {
|
|
6
|
+
try {
|
|
7
|
+
return execSync(cmd, { timeout: 5e3, encoding: "utf-8" }).trim();
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function parseBool(output, enabledPattern, disabledPattern) {
|
|
13
|
+
if (!output) return null;
|
|
14
|
+
if (enabledPattern.test(output)) return true;
|
|
15
|
+
if (disabledPattern.test(output)) return false;
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
function detectHostSecurity() {
|
|
19
|
+
const os = runCommand("uname -s");
|
|
20
|
+
if (os !== "Darwin") return null;
|
|
21
|
+
if (!existsSync(SOCKETFILTERFW)) return null;
|
|
22
|
+
const globalState = runCommand(`${SOCKETFILTERFW} --getglobalstate`);
|
|
23
|
+
if (!globalState) return null;
|
|
24
|
+
const stealthMode = runCommand(`${SOCKETFILTERFW} --getstealthmode`);
|
|
25
|
+
const blockAll = runCommand(`${SOCKETFILTERFW} --getblockall`);
|
|
26
|
+
return {
|
|
27
|
+
os: "darwin",
|
|
28
|
+
firewall_enabled: parseBool(globalState, /\benabled\b/i, /\bdisabled\b/i),
|
|
29
|
+
firewall_stealth: parseBool(stealthMode, /\bon\b/i, /\boff\b/i),
|
|
30
|
+
firewall_block_all: parseBool(blockAll, /\benabled\b/i, /\bdisabled\b/i)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
detectHostSecurity
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=host-security-6PDFG7F5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/host-security.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\n\nexport interface HostSecurityInfo {\n os: string;\n firewall_enabled: boolean | null;\n firewall_stealth: boolean | null;\n firewall_block_all: boolean | null;\n}\n\nconst SOCKETFILTERFW = '/usr/libexec/ApplicationFirewall/socketfilterfw';\n\nfunction runCommand(cmd: string): string | null {\n try {\n return execSync(cmd, { timeout: 5000, encoding: 'utf-8' }).trim();\n } catch {\n return null;\n }\n}\n\nfunction parseBool(\n output: string | null,\n enabledPattern: RegExp,\n disabledPattern: RegExp,\n): boolean | null {\n if (!output) return null;\n if (enabledPattern.test(output)) return true;\n if (disabledPattern.test(output)) return false;\n return null;\n}\n\n/**\n * Detect macOS Application Firewall state.\n * Returns null on non-macOS or if detection fails.\n */\nexport function detectHostSecurity(): HostSecurityInfo | null {\n const os = runCommand('uname -s');\n if (os !== 'Darwin') return null;\n\n if (!existsSync(SOCKETFILTERFW)) return null;\n\n const globalState = runCommand(`${SOCKETFILTERFW} --getglobalstate`);\n if (!globalState) return null;\n\n const stealthMode = runCommand(`${SOCKETFILTERFW} --getstealthmode`);\n const blockAll = runCommand(`${SOCKETFILTERFW} --getblockall`);\n\n return {\n os: 'darwin',\n firewall_enabled: parseBool(globalState, /\\benabled\\b/i, /\\bdisabled\\b/i),\n firewall_stealth: parseBool(stealthMode, /\\bon\\b/i, /\\boff\\b/i),\n firewall_block_all: parseBool(blockAll, /\\benabled\\b/i, /\\bdisabled\\b/i),\n };\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAS3B,IAAM,iBAAiB;AAEvB,SAAS,WAAW,KAA4B;AAC9C,MAAI;AACF,WAAO,SAAS,KAAK,EAAE,SAAS,KAAM,UAAU,QAAQ,CAAC,EAAE,KAAK;AAAA,EAClE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UACP,QACA,gBACA,iBACgB;AAChB,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,eAAe,KAAK,MAAM,EAAG,QAAO;AACxC,MAAI,gBAAgB,KAAK,MAAM,EAAG,QAAO;AACzC,SAAO;AACT;AAMO,SAAS,qBAA8C;AAC5D,QAAM,KAAK,WAAW,UAAU;AAChC,MAAI,OAAO,SAAU,QAAO;AAE5B,MAAI,CAAC,WAAW,cAAc,EAAG,QAAO;AAExC,QAAM,cAAc,WAAW,GAAG,cAAc,mBAAmB;AACnE,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,cAAc,WAAW,GAAG,cAAc,mBAAmB;AACnE,QAAM,WAAW,WAAW,GAAG,cAAc,gBAAgB;AAE7D,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,kBAAkB,UAAU,aAAa,gBAAgB,eAAe;AAAA,IACxE,kBAAkB,UAAU,aAAa,WAAW,UAAU;AAAA,IAC9D,oBAAoB,UAAU,UAAU,gBAAgB,eAAe;AAAA,EACzE;AACF;","names":[]}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
provision,
|
|
9
9
|
requireHost,
|
|
10
10
|
resolveChannels
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-UIWXBJSX.js";
|
|
12
12
|
import {
|
|
13
13
|
findTaskByTemplate,
|
|
14
14
|
getProjectDir,
|
|
@@ -775,6 +775,7 @@ var state = {
|
|
|
775
775
|
};
|
|
776
776
|
var registeredAgentsCache = /* @__PURE__ */ new Map();
|
|
777
777
|
var agentFrameworkCache = /* @__PURE__ */ new Map();
|
|
778
|
+
var frameworkBinaryChecked = /* @__PURE__ */ new Set();
|
|
778
779
|
function resolveAgentFramework(codeName) {
|
|
779
780
|
const frameworkId = agentFrameworkCache.get(codeName) ?? "openclaw";
|
|
780
781
|
return getFramework(frameworkId);
|
|
@@ -810,6 +811,63 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
810
811
|
var cachedFrameworkVersion = null;
|
|
811
812
|
var lastVersionCheckAt = 0;
|
|
812
813
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
814
|
+
async function ensureFrameworkBinary(frameworkId) {
|
|
815
|
+
if (frameworkId !== "claude-code") return;
|
|
816
|
+
if (frameworkBinaryChecked.has(frameworkId)) return;
|
|
817
|
+
frameworkBinaryChecked.add(frameworkId);
|
|
818
|
+
const { execFileSync } = await import("child_process");
|
|
819
|
+
let brewPath;
|
|
820
|
+
try {
|
|
821
|
+
brewPath = execFileSync("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
822
|
+
} catch {
|
|
823
|
+
log("Homebrew not found \u2014 cannot auto-install/upgrade Claude Code. Install manually: https://claude.ai/download");
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
let claudeExists = false;
|
|
827
|
+
try {
|
|
828
|
+
execFileSync("which", ["claude"], { timeout: 5e3 });
|
|
829
|
+
claudeExists = true;
|
|
830
|
+
} catch {
|
|
831
|
+
}
|
|
832
|
+
if (!claudeExists) {
|
|
833
|
+
log("Claude Code binary not found \u2014 installing via Homebrew...");
|
|
834
|
+
try {
|
|
835
|
+
execFileSync(brewPath, ["install", "--cask", "claude-code"], {
|
|
836
|
+
timeout: 12e4,
|
|
837
|
+
stdio: "pipe"
|
|
838
|
+
});
|
|
839
|
+
} catch (err) {
|
|
840
|
+
log(`Claude Code install failed: ${err.message}`);
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
try {
|
|
844
|
+
execFileSync("which", ["claude"], { timeout: 5e3 });
|
|
845
|
+
log("Claude Code installed successfully");
|
|
846
|
+
} catch {
|
|
847
|
+
log("Claude Code install completed but binary not found on PATH \u2014 you may need to restart your terminal");
|
|
848
|
+
}
|
|
849
|
+
} else {
|
|
850
|
+
log("Checking for Claude Code updates...");
|
|
851
|
+
try {
|
|
852
|
+
const output = execFileSync(brewPath, ["upgrade", "--cask", "claude-code"], {
|
|
853
|
+
timeout: 12e4,
|
|
854
|
+
stdio: "pipe"
|
|
855
|
+
}).toString();
|
|
856
|
+
if (output.includes("already installed") || output.includes("up-to-date")) {
|
|
857
|
+
log("Claude Code is already up to date");
|
|
858
|
+
} else {
|
|
859
|
+
log("Claude Code upgraded successfully");
|
|
860
|
+
}
|
|
861
|
+
} catch (err) {
|
|
862
|
+
const msg = err.message;
|
|
863
|
+
if (msg.includes("already installed") || msg.includes("up-to-date") || msg.includes("not upgraded")) {
|
|
864
|
+
log("Claude Code is already up to date");
|
|
865
|
+
} else {
|
|
866
|
+
log(`Claude Code upgrade failed: ${msg}`);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
813
871
|
function loadGatewayPorts() {
|
|
814
872
|
try {
|
|
815
873
|
return JSON.parse(readFileSync2(GATEWAY_PORTS_FILE, "utf-8"));
|
|
@@ -1126,15 +1184,21 @@ async function pollCycle() {
|
|
|
1126
1184
|
lastVersionCheckAt = now;
|
|
1127
1185
|
}
|
|
1128
1186
|
try {
|
|
1187
|
+
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
1129
1188
|
await api.post("/host/heartbeat", {
|
|
1130
1189
|
host_id: hostId,
|
|
1131
|
-
framework_version: cachedFrameworkVersion ?? void 0
|
|
1190
|
+
framework_version: cachedFrameworkVersion ?? void 0,
|
|
1191
|
+
host_security: detectHostSecurity() ?? void 0
|
|
1132
1192
|
});
|
|
1133
1193
|
} catch (err) {
|
|
1134
1194
|
log(`Heartbeat failed: ${err.message}`);
|
|
1135
1195
|
}
|
|
1136
1196
|
const data = await api.post("/host/agents", { host_id: hostId });
|
|
1137
1197
|
const agents = data.agents ?? [];
|
|
1198
|
+
const frameworksThisCycle = new Set(agents.map((a) => a.framework).filter(Boolean));
|
|
1199
|
+
for (const fw of frameworksThisCycle) {
|
|
1200
|
+
await ensureFrameworkBinary(fw);
|
|
1201
|
+
}
|
|
1138
1202
|
activeChannels.clear();
|
|
1139
1203
|
const agentStates = [];
|
|
1140
1204
|
for (const agent of agents) {
|
|
@@ -1203,6 +1267,13 @@ async function pollCycle() {
|
|
|
1203
1267
|
ensureRealtimeAssignStarted(agentStates);
|
|
1204
1268
|
ensureRealtimeConfigStarted(agentStates);
|
|
1205
1269
|
ensureRealtimeKanbanStarted(agentStates);
|
|
1270
|
+
try {
|
|
1271
|
+
const spawnData = await api.post("/host/kanban/recurring/spawn");
|
|
1272
|
+
if (spawnData.spawned > 0) {
|
|
1273
|
+
log(`Spawned ${spawnData.spawned} recurring kanban item(s)`);
|
|
1274
|
+
}
|
|
1275
|
+
} catch {
|
|
1276
|
+
}
|
|
1206
1277
|
state = {
|
|
1207
1278
|
...state,
|
|
1208
1279
|
lastPollAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3266,17 +3337,17 @@ function generateArtifacts(agent, refreshData, adapter) {
|
|
|
3266
3337
|
denied: [],
|
|
3267
3338
|
require_approval_to_change: true
|
|
3268
3339
|
};
|
|
3269
|
-
let
|
|
3340
|
+
let orgChannelPolicy;
|
|
3270
3341
|
const policyData = refreshData.team_channel_policy;
|
|
3271
3342
|
if (policyData) {
|
|
3272
|
-
|
|
3273
|
-
|
|
3343
|
+
orgChannelPolicy = {
|
|
3344
|
+
organization_id: policyData.team_id,
|
|
3274
3345
|
allowed_channels: policyData.allowed_channels ?? [],
|
|
3275
3346
|
denied_channels: policyData.denied_channels ?? [],
|
|
3276
3347
|
require_elevated_for_pii: policyData.require_elevated_for_pii ?? false
|
|
3277
3348
|
};
|
|
3278
3349
|
}
|
|
3279
|
-
const resolvedChannels = resolveChannels(agentChannelPolicy,
|
|
3350
|
+
const resolvedChannels = resolveChannels(agentChannelPolicy, orgChannelPolicy);
|
|
3280
3351
|
const effectiveChannels = agent.status === "paused" ? [] : resolvedChannels;
|
|
3281
3352
|
const provisionInput = {
|
|
3282
3353
|
agent: refreshData.agent,
|