@atbash/cli 0.5.15-dev.8 → 0.6.0-dev.1
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/README.md +287 -26
- package/dist/bin/atbash.js +31 -5
- package/dist/bin/atbash.js.map +1 -1
- package/dist/commands/connect.d.ts +40 -50
- package/dist/commands/connect.js +60 -108
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/github-scan.d.ts +104 -0
- package/dist/commands/github-scan.js +1054 -0
- package/dist/commands/github-scan.js.map +1 -0
- package/dist/commands/held.js +7 -2
- package/dist/commands/held.js.map +1 -1
- package/dist/commands/history.js +4 -1
- package/dist/commands/history.js.map +1 -1
- package/dist/commands/judge-options.d.ts +21 -0
- package/dist/commands/judge-options.js +24 -0
- package/dist/commands/judge-options.js.map +1 -0
- package/dist/commands/judge.js +4 -1
- package/dist/commands/judge.js.map +1 -1
- package/dist/commands/policy.js +4 -1
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/scan.d.ts +45 -0
- package/dist/commands/scan.js +301 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/setup.d.ts +1 -209
- package/dist/commands/setup.js +128 -947
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/stats.js +3 -1
- package/dist/commands/stats.js.map +1 -1
- package/dist/commands/status.js +4 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/tier.js +4 -1
- package/dist/commands/tier.js.map +1 -1
- package/dist/commands/tools.js +11 -4
- package/dist/commands/tools.js.map +1 -1
- package/dist/commands/whoami.js +4 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/lib/grade-llm.d.ts +38 -0
- package/dist/lib/grade-llm.js +64 -0
- package/dist/lib/grade-llm.js.map +1 -0
- package/dist/lib/llm.d.ts +34 -0
- package/dist/lib/llm.js +101 -0
- package/dist/lib/llm.js.map +1 -0
- package/dist/lib/policy.d.ts +40 -0
- package/dist/lib/policy.js +94 -0
- package/dist/lib/policy.js.map +1 -0
- package/dist/lib/risk.d.ts +112 -0
- package/dist/lib/risk.js +288 -0
- package/dist/lib/risk.js.map +1 -0
- package/dist/lib/threats-llm.d.ts +39 -0
- package/dist/lib/threats-llm.js +72 -0
- package/dist/lib/threats-llm.js.map +1 -0
- package/package.json +4 -4
- package/dist/commands/mcp-cmd.d.ts +0 -13
- package/dist/commands/mcp-cmd.js +0 -216
- package/dist/commands/mcp-cmd.js.map +0 -1
- package/dist/shared/atbash-targets.d.ts +0 -49
- package/dist/shared/atbash-targets.js +0 -63
- package/dist/shared/atbash-targets.js.map +0 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.toRows = toRows;
|
|
7
|
+
exports.toScanTools = toScanTools;
|
|
8
|
+
exports.countNetworkRequests = countNetworkRequests;
|
|
9
|
+
exports.registerScanCommand = registerScanCommand;
|
|
10
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const connect_1 = require("./connect");
|
|
13
|
+
const introspect_mcp_1 = require("./introspect-mcp");
|
|
14
|
+
const risk_1 = require("../lib/risk");
|
|
15
|
+
const grade_llm_1 = require("../lib/grade-llm");
|
|
16
|
+
const threats_llm_1 = require("../lib/threats-llm");
|
|
17
|
+
const policy_1 = require("../lib/policy");
|
|
18
|
+
const llm_1 = require("../lib/llm");
|
|
19
|
+
/** One row per discovered runtime, with its tool names flattened for display. */
|
|
20
|
+
function toRows(agents) {
|
|
21
|
+
return agents.map((a) => {
|
|
22
|
+
const tools = a.type === "declared" && Array.isArray(a.declaredTools)
|
|
23
|
+
? a.declaredTools.map((t) => t.name)
|
|
24
|
+
: a.type === "config" && a.config?.mcpServers
|
|
25
|
+
? Object.keys(a.config.mcpServers)
|
|
26
|
+
: [];
|
|
27
|
+
return { label: a.label, detail: a.detail, kind: a.type, tools };
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The tool surface the risk engine grades.
|
|
32
|
+
*
|
|
33
|
+
* A config's SERVER names are deliberately not included: "gmail" is a server, not
|
|
34
|
+
* a capability, and grading it would invent a finding out of a filename. That is
|
|
35
|
+
* why a config-only machine needs --introspect before it gets a risk report — the
|
|
36
|
+
* scan says so rather than quietly reporting "Low".
|
|
37
|
+
*/
|
|
38
|
+
function toScanTools(agents, introspection) {
|
|
39
|
+
const out = [];
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
const add = (name, description, source) => {
|
|
42
|
+
const key = (0, risk_1.toolKey)(source, name);
|
|
43
|
+
if (!name || seen.has(key))
|
|
44
|
+
return;
|
|
45
|
+
seen.add(key);
|
|
46
|
+
out.push({ name, description, source });
|
|
47
|
+
};
|
|
48
|
+
// Declared runtimes enumerated their own tools locally.
|
|
49
|
+
for (const a of agents) {
|
|
50
|
+
if (a.type === "declared")
|
|
51
|
+
for (const t of a.declaredTools ?? [])
|
|
52
|
+
add(t.name, t.description, a.label);
|
|
53
|
+
}
|
|
54
|
+
// Introspection is the authoritative surface for a config source: the names the
|
|
55
|
+
// server itself advertised, rather than what a config file claims.
|
|
56
|
+
for (const r of introspection) {
|
|
57
|
+
for (const s of r.servers) {
|
|
58
|
+
if (!s.ok)
|
|
59
|
+
continue;
|
|
60
|
+
for (const t of s.tools)
|
|
61
|
+
add(t.name, t.description, `${r.label}/${s.server}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/** Tool names each MCP server advertised, keyed by server name. */
|
|
67
|
+
function introspectedByServer(results) {
|
|
68
|
+
const out = new Map();
|
|
69
|
+
for (const r of results) {
|
|
70
|
+
for (const s of r.servers) {
|
|
71
|
+
if (s.ok)
|
|
72
|
+
out.set(s.server, s.tools.map((t) => t.name));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Requests that actually left the machine. Only HTTP-transport servers are
|
|
79
|
+
* reached over the network — and then at the URL the user's own config names,
|
|
80
|
+
* never an Atbash host. stdio servers are spawned locally and spoken to over a
|
|
81
|
+
* pipe, so they are not counted here.
|
|
82
|
+
*/
|
|
83
|
+
function countNetworkRequests(results) {
|
|
84
|
+
return results.reduce((n, r) => n + r.servers.filter((s) => s.transport === "http").length, 0);
|
|
85
|
+
}
|
|
86
|
+
const LEVEL_RANK = { Low: 0, Elevated: 1, High: 2 };
|
|
87
|
+
const FAIL_ON = { low: "Low", elevated: "Elevated", high: "High" };
|
|
88
|
+
const SEV_COLOR = {
|
|
89
|
+
high: chalk_1.default.red,
|
|
90
|
+
medium: chalk_1.default.yellow,
|
|
91
|
+
low: chalk_1.default.green,
|
|
92
|
+
};
|
|
93
|
+
function renderThreats(threats) {
|
|
94
|
+
console.log(" " + chalk_1.default.bold("Threat paths") + "\n " + "\u2500".repeat(28));
|
|
95
|
+
console.log(chalk_1.default.dim(" Combinations the per-tool rules cannot see. Model-generated.\n"));
|
|
96
|
+
for (const t of threats) {
|
|
97
|
+
console.log(` ${SEV_COLOR[t.severity](t.severity.padEnd(6))} ${chalk_1.default.bold(t.title)} ${chalk_1.default.dim("\u2014 " + t.category)}`);
|
|
98
|
+
if (t.enabledBy)
|
|
99
|
+
console.log(chalk_1.default.dim(` enabled by: ${t.enabledBy}`));
|
|
100
|
+
if (t.consequence)
|
|
101
|
+
console.log(chalk_1.default.dim(` ${t.consequence}`));
|
|
102
|
+
}
|
|
103
|
+
console.log();
|
|
104
|
+
}
|
|
105
|
+
function renderPolicy(policy) {
|
|
106
|
+
console.log(" " + chalk_1.default.bold("Recommended boundary") + "\n " + "\u2500".repeat(28));
|
|
107
|
+
console.log(` ${chalk_1.default.dim("Mandate:")} ${policy.mandate}\n`);
|
|
108
|
+
console.log(` ${chalk_1.default.bold("Red lines")} ${chalk_1.default.dim("(auto-deny)")}`);
|
|
109
|
+
for (const r of policy.redLines)
|
|
110
|
+
console.log(` \u2022 ${r}`);
|
|
111
|
+
console.log(`\n ${chalk_1.default.bold("Needs approval")}`);
|
|
112
|
+
if (policy.approvals.length === 0)
|
|
113
|
+
console.log(chalk_1.default.dim(" (none)"));
|
|
114
|
+
for (const a of policy.approvals)
|
|
115
|
+
console.log(` \u2022 ${a}`);
|
|
116
|
+
console.log("\n" + chalk_1.default.dim(` ${policy.notes}`) + "\n");
|
|
117
|
+
}
|
|
118
|
+
function renderRisk(report, hasKey, enrichError) {
|
|
119
|
+
const levelColor = report.level === "High" ? chalk_1.default.red : report.level === "Elevated" ? chalk_1.default.yellow : chalk_1.default.green;
|
|
120
|
+
console.log(" " + chalk_1.default.bold("Risk") + "\n " + "─".repeat(28));
|
|
121
|
+
console.log(` Level : ${levelColor.bold(report.level)} ${chalk_1.default.dim(`(${report.score}/100)`)}`);
|
|
122
|
+
console.log(` Method : ${report.method === "llm" ? "deterministic + model-graded" : "deterministic"}`);
|
|
123
|
+
console.log(` ${chalk_1.default.dim(report.summary)}\n`);
|
|
124
|
+
// Secondary paths are extra harms on a tool already listed; showing them inline
|
|
125
|
+
// would read as duplicate findings, so the primary carries the line.
|
|
126
|
+
const primary = report.paths.filter((p) => !p.secondary);
|
|
127
|
+
const shown = primary.slice(0, 12);
|
|
128
|
+
for (const p of shown) {
|
|
129
|
+
const sev = SEV_COLOR[p.severity](p.severity.padEnd(6));
|
|
130
|
+
console.log(` ${sev} ${chalk_1.default.bold(p.tool)} ${chalk_1.default.dim("— " + p.category)}`);
|
|
131
|
+
console.log(` ${chalk_1.default.dim(p.consequence)}`);
|
|
132
|
+
}
|
|
133
|
+
if (primary.length > shown.length) {
|
|
134
|
+
console.log(chalk_1.default.dim(` … ${primary.length - shown.length} more`));
|
|
135
|
+
}
|
|
136
|
+
console.log();
|
|
137
|
+
if (enrichError) {
|
|
138
|
+
console.log(chalk_1.default.yellow(` Model grading unavailable (${enrichError}) — deterministic result kept.\n`));
|
|
139
|
+
}
|
|
140
|
+
const unclassified = primary.filter(risk_1.isUnclassifiedPath).length;
|
|
141
|
+
if (unclassified > 0 && !hasKey) {
|
|
142
|
+
console.log(chalk_1.default.dim(` ${unclassified} tool${unclassified === 1 ? "" : "s"} matched no rule. Pass --api-key <key> to grade\n` +
|
|
143
|
+
" them with your own LLM provider (tool names and descriptions are sent there).\n"));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function render(rows, introspected, introspectRan, report, toolCount, hasKey, enrichError) {
|
|
147
|
+
console.log("\n" + chalk_1.default.bold(" Atbash local scan") + "\n " + "─".repeat(28));
|
|
148
|
+
console.log(` Machine : ${node_os_1.default.hostname()}`);
|
|
149
|
+
console.log(` Found : ${rows.length} runtime${rows.length === 1 ? "" : "s"}\n`);
|
|
150
|
+
if (rows.length === 0) {
|
|
151
|
+
console.log(chalk_1.default.dim(" No agents or MCP configs found in the usual locations.\n"));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
for (const r of rows) {
|
|
155
|
+
console.log(` ${chalk_1.default.bold(r.label)} ${chalk_1.default.dim("— " + r.detail)}`);
|
|
156
|
+
for (const name of r.tools) {
|
|
157
|
+
// A name the server itself advertised is worth more than one read out of a
|
|
158
|
+
// config file, so say which this is rather than presenting them alike.
|
|
159
|
+
const confirmed = introspected.get(name);
|
|
160
|
+
if (confirmed) {
|
|
161
|
+
console.log(` • ${name} ${chalk_1.default.dim(`(${confirmed.length} tool${confirmed.length === 1 ? "" : "s"} confirmed)`)}`);
|
|
162
|
+
for (const t of confirmed.slice(0, 8))
|
|
163
|
+
console.log(chalk_1.default.dim(` - ${t}`));
|
|
164
|
+
if (confirmed.length > 8)
|
|
165
|
+
console.log(chalk_1.default.dim(` … ${confirmed.length - 8} more`));
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
console.log(` • ${name}${introspectRan && r.kind === "config" ? chalk_1.default.dim(" (not reached)") : ""}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
console.log();
|
|
172
|
+
}
|
|
173
|
+
if (toolCount === 0) {
|
|
174
|
+
console.log(chalk_1.default.dim(" No tool surface was resolved, so no risk could be derived. Config files name\n" +
|
|
175
|
+
" servers, not capabilities — add --introspect to ask each server what it\n" +
|
|
176
|
+
" actually advertises.\n"));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
renderRisk(report, hasKey, enrichError);
|
|
180
|
+
}
|
|
181
|
+
if (!introspectRan) {
|
|
182
|
+
console.log(chalk_1.default.dim(" Tool names above are what the configs declare. Add --introspect to ask\n each MCP server what it actually advertises.\n"));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function registerScanCommand(program) {
|
|
186
|
+
program
|
|
187
|
+
.command("scan")
|
|
188
|
+
.description("Scan this machine for installed agents and MCP tools, grade the risk, and print the report here (the report is never sent anywhere)")
|
|
189
|
+
.option("--home <dir>", "Home directory to scan (for testing)")
|
|
190
|
+
.option("--introspect", "Also ask each configured MCP server which tools it advertises: stdio servers are started locally, HTTP servers are contacted at the URL their own config names. Never calls a tool")
|
|
191
|
+
.option("--api-key <key>", "YOUR LLM provider key (OpenRouter), used to grade tools the built-in rules could not classify. Sends those tool names and descriptions to that provider. Also read from ATBASH_SCAN_API_KEY or OPENROUTER_API_KEY")
|
|
192
|
+
.option("--model <id>", `Model for --api-key grading (default: ${llm_1.DEFAULT_MODEL})`)
|
|
193
|
+
.option("--threats", "Also enumerate CROSS-TOOL threat chains (e.g. read customer data + external send = exfiltration). Requires --api-key; never changes the risk score")
|
|
194
|
+
.option("--policy", "Also print a draft governance boundary derived from the findings: red lines and approval-required actions. Deterministic, no key needed")
|
|
195
|
+
.option("--fail-on <level>", "Exit 1 when the risk level reaches this: low, elevated or high (for CI)")
|
|
196
|
+
.option("--json", "Emit machine-readable JSON instead of formatted text")
|
|
197
|
+
.action(async (opts) => {
|
|
198
|
+
const home = opts.home || node_os_1.default.homedir();
|
|
199
|
+
let failOn;
|
|
200
|
+
if (opts.failOn) {
|
|
201
|
+
failOn = FAIL_ON[opts.failOn.toLowerCase()];
|
|
202
|
+
if (!failOn) {
|
|
203
|
+
console.error(chalk_1.default.red(` Invalid --fail-on "${opts.failOn}". Choose: low, elevated, high.`));
|
|
204
|
+
process.exitCode = 2;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const agents = (0, connect_1.discover)(home);
|
|
209
|
+
const rows = toRows(agents);
|
|
210
|
+
let introspection = [];
|
|
211
|
+
if (opts.introspect) {
|
|
212
|
+
if (!opts.json)
|
|
213
|
+
console.log(chalk_1.default.dim("\n Asking configured MCP servers to list their tools…"));
|
|
214
|
+
try {
|
|
215
|
+
// The RAW specs, not the ones `discover` returns. Those are sanitized for
|
|
216
|
+
// relay — absolute command paths reduced to a basename, `env`/`headers`
|
|
217
|
+
// dropped — which is right for a payload and fatal for actually starting a
|
|
218
|
+
// server: a command installed outside PATH fails with ENOENT and the report
|
|
219
|
+
// blames the user's server for the scan's own omission. Nothing raw is
|
|
220
|
+
// printed; introspection returns only sanitized names and redacted errors.
|
|
221
|
+
const sources = (0, connect_1.readAllMcpServers)(home);
|
|
222
|
+
introspection = await (0, introspect_mcp_1.introspectServers)(sources);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
// Introspection is the optional half: a server that will not start must
|
|
226
|
+
// not cost the user the discovery result they already have.
|
|
227
|
+
if (!opts.json)
|
|
228
|
+
console.error(chalk_1.default.yellow(` Introspection failed: ${err.message}`));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const tools = toScanTools(agents, introspection);
|
|
232
|
+
let report = (0, risk_1.deriveRisk)(tools);
|
|
233
|
+
let networkRequests = countNetworkRequests(introspection);
|
|
234
|
+
// The user's own key, never a platform one. Env vars are accepted so a CI
|
|
235
|
+
// job never has to put a secret in argv, where it is visible in the process
|
|
236
|
+
// list to every other user on the box.
|
|
237
|
+
const apiKey = opts.apiKey || process.env.ATBASH_SCAN_API_KEY || process.env.OPENROUTER_API_KEY;
|
|
238
|
+
let enrichError;
|
|
239
|
+
if (apiKey && tools.length > 0) {
|
|
240
|
+
// Matched on source+name, not name alone: two different MCP servers can
|
|
241
|
+
// expose a same-named tool, and a name-only match would sweep an ALREADY
|
|
242
|
+
// classified tool's real description into the LLM batch just because some
|
|
243
|
+
// other server's same-named tool is unclassified.
|
|
244
|
+
const unclassified = tools.filter((t) => report.paths.some((p) => (0, risk_1.toolKey)(p.source, p.tool) === (0, risk_1.toolKey)(t.source, t.name) && !p.secondary && (0, risk_1.isUnclassifiedPath)(p)));
|
|
245
|
+
if (unclassified.length > 0) {
|
|
246
|
+
if (!opts.json) {
|
|
247
|
+
console.log(chalk_1.default.dim(`\n Grading ${unclassified.length} unclassified tool${unclassified.length === 1 ? "" : "s"} with your provider…`));
|
|
248
|
+
}
|
|
249
|
+
const outcome = await (0, grade_llm_1.gradeToolsWithLlm)(unclassified, { apiKey, model: opts.model });
|
|
250
|
+
networkRequests += outcome.requests;
|
|
251
|
+
enrichError = outcome.error;
|
|
252
|
+
report = (0, risk_1.gradeUnclassifiedPaths)(report, outcome.grades);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
let threats = [];
|
|
256
|
+
let threatError;
|
|
257
|
+
if (opts.threats && tools.length > 0) {
|
|
258
|
+
if (!apiKey) {
|
|
259
|
+
threatError = "no API key — threat chains need one (--api-key, ATBASH_SCAN_API_KEY or OPENROUTER_API_KEY)";
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
if (!opts.json)
|
|
263
|
+
console.log(chalk_1.default.dim("\n Looking for cross-tool threat chains\u2026"));
|
|
264
|
+
const outcome = await (0, threats_llm_1.deriveThreats)(tools, { apiKey, model: opts.model });
|
|
265
|
+
networkRequests += outcome.requests;
|
|
266
|
+
threatError = outcome.error;
|
|
267
|
+
threats = outcome.threats;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Derived from the report, so it reflects any model grading that ran. The
|
|
271
|
+
// boundary is a SUGGESTION printed here; nothing is deployed anywhere.
|
|
272
|
+
const policy = opts.policy ? (0, policy_1.suggestPolicy)(report) : undefined;
|
|
273
|
+
if (failOn && LEVEL_RANK[report.level] >= LEVEL_RANK[failOn]) {
|
|
274
|
+
process.exitCode = 1;
|
|
275
|
+
}
|
|
276
|
+
if (opts.json) {
|
|
277
|
+
console.log(JSON.stringify({
|
|
278
|
+
ok: true,
|
|
279
|
+
machine: node_os_1.default.hostname(),
|
|
280
|
+
local: true,
|
|
281
|
+
networkRequests,
|
|
282
|
+
agents: rows,
|
|
283
|
+
introspection,
|
|
284
|
+
risk: report,
|
|
285
|
+
...(threats.length > 0 ? { threats } : {}),
|
|
286
|
+
...(policy ? { policy } : {}),
|
|
287
|
+
...(enrichError ? { enrichmentError: enrichError } : {}),
|
|
288
|
+
...(threatError ? { threatError } : {}),
|
|
289
|
+
}, null, 2));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
render(rows, introspectedByServer(introspection), !!opts.introspect, report, tools.length, !!apiKey, enrichError);
|
|
293
|
+
if (threatError)
|
|
294
|
+
console.log(chalk_1.default.yellow(` Threat analysis unavailable (${threatError}).\n`));
|
|
295
|
+
if (threats.length > 0)
|
|
296
|
+
renderThreats(threats);
|
|
297
|
+
if (policy)
|
|
298
|
+
renderPolicy(policy);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -20,27 +20,7 @@ interface KeyMaterial {
|
|
|
20
20
|
export declare function parseKeyMaterial(raw: string): KeyMaterial | null;
|
|
21
21
|
/** Normalize to the lowercase 64-hex the SDK validates, or "" if it is not one. */
|
|
22
22
|
export declare function normalizePrivkey(raw: string): string;
|
|
23
|
-
/**
|
|
24
|
-
* Files in a directory that plausibly hold an Atbash agent key, newest first.
|
|
25
|
-
*
|
|
26
|
-
* TWO PASSES, and the second one is the point.
|
|
27
|
-
*
|
|
28
|
-
* By name first — `guard-client-key`, `agent-keys-*.txt` and friends — because
|
|
29
|
-
* matching the name is cheap and unambiguous. But a name-only match is a cliff:
|
|
30
|
-
* rename the download, or export from a wallet UI that picks its own filename,
|
|
31
|
-
* and the operator gets "no key file found" while the key sits right there in the
|
|
32
|
-
* directory they explicitly pointed at.
|
|
33
|
-
*
|
|
34
|
-
* So if no name matches, read the small files and keep the ones that actually
|
|
35
|
-
* PARSE as key material. That is a narrow test — `privkey=`, the documented JSON
|
|
36
|
-
* shape, or a file that is nothing but a 64-hex key — not "contains something
|
|
37
|
-
* hex-looking", so an unrelated file does not get mistaken for an identity.
|
|
38
|
-
*
|
|
39
|
-
* Reading files the operator did not name individually is justified by the flag
|
|
40
|
-
* itself: `--keys-dir` is an explicit instruction to look in that directory. It
|
|
41
|
-
* is bounded to small regular files and a file count, nothing is transmitted, and
|
|
42
|
-
* the caller prints WHICH file it used before doing anything with it.
|
|
43
|
-
*/
|
|
23
|
+
/** Files in a directory that plausibly hold an Atbash agent key, newest first. */
|
|
44
24
|
export declare function keyCandidatesInDir(dir: string): string[];
|
|
45
25
|
interface KeySource {
|
|
46
26
|
material: KeyMaterial;
|
|
@@ -121,194 +101,6 @@ export declare function isJsonc(text: string): boolean;
|
|
|
121
101
|
* does not exist and a plugin that never loads.
|
|
122
102
|
*/
|
|
123
103
|
export declare function mergeOpenclawConfig(config: Record<string, unknown>, home: string): Record<string, unknown>;
|
|
124
|
-
/**
|
|
125
|
-
* Detect the indentation a JSON file already uses, so a merge does not reformat
|
|
126
|
-
* the parts it did not touch.
|
|
127
|
-
*
|
|
128
|
-
* Without this, `JSON.stringify(obj, null, 2)` re-indents a tab-indented or
|
|
129
|
-
* 4-space config from top to bottom. The RESULT is still correct, but the diff
|
|
130
|
-
* shown for approval becomes every line in the file, which buries the two lines
|
|
131
|
-
* that actually changed — and the operator's own formatting choice is collateral
|
|
132
|
-
* damage in a file we were asked to make one addition to.
|
|
133
|
-
*
|
|
134
|
-
* Falls back to two spaces, which is what the published docs show.
|
|
135
|
-
*/
|
|
136
|
-
export declare function detectIndent(text: string | null): string | number;
|
|
137
|
-
/**
|
|
138
|
-
* Serialize a merged config the way the file was already written: same
|
|
139
|
-
* indentation, and a trailing newline only if the original had one.
|
|
140
|
-
*/
|
|
141
|
-
export declare function serializeLike(original: string | null, value: unknown): string;
|
|
142
|
-
interface McpClient {
|
|
143
|
-
label: string;
|
|
144
|
-
file: string;
|
|
145
|
-
format: "json" | "toml";
|
|
146
|
-
/** Which key holds the server map — VS Code and some others use `servers`. */
|
|
147
|
-
serversKey: "mcpServers" | "servers";
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* MCP client configs present under this home directory.
|
|
151
|
-
*
|
|
152
|
-
* Paths come from the shared MCP_CONFIGS so the writer and the scanner cannot
|
|
153
|
-
* drift: a client the scan reports but setup cannot find would look like a bug in
|
|
154
|
-
* whichever of the two the operator happened to trust.
|
|
155
|
-
*/
|
|
156
|
-
export declare function detectMcpClients(home: string): McpClient[];
|
|
157
|
-
/**
|
|
158
|
-
* Find the Python interpreter that actually runs Hermes.
|
|
159
|
-
*
|
|
160
|
-
* This is the difference between installing the plugin and only appearing to.
|
|
161
|
-
* `pip install atbash-hermes-plugin` puts the package wherever the *shell's*
|
|
162
|
-
* `pip` points — commonly a system or conda Python — while Hermes typically runs
|
|
163
|
-
* from its own virtualenv. The install succeeds, prints nothing alarming, and the
|
|
164
|
-
* plugin is invisible to Hermes forever. Nobody can debug that from the output.
|
|
165
|
-
*
|
|
166
|
-
* The launcher knows the answer. A pip-installed console script begins with a
|
|
167
|
-
* shebang naming the interpreter that created it:
|
|
168
|
-
*
|
|
169
|
-
* $ head -1 $(command -v hermes)
|
|
170
|
-
* #!/Users/me/.hermes/hermes-agent/venv/bin/python3
|
|
171
|
-
*
|
|
172
|
-
* So resolve `hermes`, read its first line, and use that interpreter directly via
|
|
173
|
-
* `-m pip`. Falls back to the conventional venv location under ~/.hermes, then to
|
|
174
|
-
* null — and a null becomes a printed command rather than a guess, because a
|
|
175
|
-
* wrong guess here is the silent failure this whole function exists to avoid.
|
|
176
|
-
*/
|
|
177
|
-
export declare function findHermesPython(home: string): {
|
|
178
|
-
python: string;
|
|
179
|
-
how: string;
|
|
180
|
-
} | null;
|
|
181
|
-
/** Same rule as buildPlan's `wanted`: an empty --runtime list means everything. */
|
|
182
|
-
export declare function wantedRuntime(id: string, only: string[]): boolean;
|
|
183
|
-
/**
|
|
184
|
-
* Add the plugin to Hermes' opt-in allow-list at `plugins.enabled` in
|
|
185
|
-
* `~/.hermes/config.yaml`.
|
|
186
|
-
*
|
|
187
|
-
* WHY NOT `hermes plugins enable`: that command cannot accept this plugin, on
|
|
188
|
-
* this version, ever. `_plugin_exists` (hermes_cli/plugins_cmd.py) looks only for
|
|
189
|
-
* a DIRECTORY in the user plugins dir or a bundled dir — it never consults entry
|
|
190
|
-
* points. Meanwhile the runtime loader (`plugins.py:_scan_entry_points`) does
|
|
191
|
-
* discover them. So Hermes will happily LOAD a pip-installed plugin but refuses
|
|
192
|
-
* to put one on the allow-list it requires, and since plugins are opt-in, a
|
|
193
|
-
* package that cannot get onto the list can never load. Running that command
|
|
194
|
-
* exits 1 with "not installed or bundled". Writing the list entry directly is the
|
|
195
|
-
* only route that works.
|
|
196
|
-
*
|
|
197
|
-
* A LINE MERGE, not a parse-and-reserialize. config.yaml is tens of kilobytes of
|
|
198
|
-
* heavily commented configuration; round-tripping it through a YAML emitter would
|
|
199
|
-
* strip every comment and reflow the file. So this inserts the one line needed and
|
|
200
|
-
* leaves every other byte alone — the same discipline as the .env merge.
|
|
201
|
-
*/
|
|
202
|
-
export declare function mergeHermesEnabledPlugins(existing: string | null, plugin?: string): string;
|
|
203
|
-
/**
|
|
204
|
-
* Whether Hermes has actually picked the plugin up.
|
|
205
|
-
*
|
|
206
|
-
* Installing the package is NOT the same as governing the agent. Hermes requires
|
|
207
|
-
* plugins to be enabled explicitly — a real run installed `atbash-hermes-plugin`
|
|
208
|
-
* into the right interpreter, with the right `hermes_agent.plugins` entry point,
|
|
209
|
-
* and `hermes plugins list` still showed only the bundled plugins, all "not
|
|
210
|
-
* enabled". The machine looked wired and enforced nothing, which is the exact
|
|
211
|
-
* failure this command exists to prevent.
|
|
212
|
-
*
|
|
213
|
-
* Parsing a rendered table is inherently fragile, so an unreadable result is
|
|
214
|
-
* reported as "unknown" and treated as "probably needs enabling" rather than as
|
|
215
|
-
* success. Claiming enforcement we have not observed is the one wrong answer.
|
|
216
|
-
*/
|
|
217
|
-
export type HermesPluginState = "configured" | "not-enabled" | "not-installed" | "unknown";
|
|
218
|
-
/**
|
|
219
|
-
* Is a Hermes gateway service running, and therefore restartable?
|
|
220
|
-
*
|
|
221
|
-
* "Restart Hermes" only means something when there is a service to bounce.
|
|
222
|
-
* Hermes has two shapes: `hermes` starts an interactive chat session, and
|
|
223
|
-
* `hermes gateway install` registers a launchd/systemd background service. A
|
|
224
|
-
* setup command must not conflate them —
|
|
225
|
-
*
|
|
226
|
-
* - with a service running, `hermes gateway restart` picks up the new config and
|
|
227
|
-
* is worth doing for the operator;
|
|
228
|
-
* - without one, there is nothing to restart. The plugin loads the next time
|
|
229
|
-
* they run `hermes`, and anything we "restarted" would either be a no-op or,
|
|
230
|
-
* worse, an interactive session someone is in the middle of using.
|
|
231
|
-
*
|
|
232
|
-
* `gateway status` exits 0 either way, so the state comes from its text.
|
|
233
|
-
*/
|
|
234
|
-
export declare function hermesGatewayRunning(): boolean;
|
|
235
|
-
/**
|
|
236
|
-
* Is Hermes CONFIGURED to load the plugin?
|
|
237
|
-
*
|
|
238
|
-
* This used to shell out to `hermes plugins list` and look for an atbash row —
|
|
239
|
-
* a signal that can never be true. `_discover_all_plugins` (plugins_cmd.py) walks
|
|
240
|
-
* plugin DIRECTORIES only: bundled, user, project. It never scans entry points,
|
|
241
|
-
* exactly like the `_plugin_exists` gate behind `plugins enable`. So a
|
|
242
|
-
* pip-installed plugin is invisible to both, and the check reported "not picked
|
|
243
|
-
* up" while everything was in fact correct — then told the operator to run the
|
|
244
|
-
* enable command that cannot work. Advising a known-impossible fix is worse than
|
|
245
|
-
* saying nothing.
|
|
246
|
-
*
|
|
247
|
-
* The two facts that actually decide it are both on disk:
|
|
248
|
-
*
|
|
249
|
-
* 1. the package is importable by the interpreter that runs Hermes, and
|
|
250
|
-
* 2. its name is on the `plugins.enabled` allow-list in config.yaml, which is
|
|
251
|
-
* what the RUNTIME loader (`plugins.py:_scan_entry_points`) honours.
|
|
252
|
-
*
|
|
253
|
-
* "configured" is as far as a setup command can honestly go. Proof of loading is
|
|
254
|
-
* a line in the agent log after Hermes next starts, which is why the caller points
|
|
255
|
-
* at that rather than claiming enforcement.
|
|
256
|
-
*/
|
|
257
|
-
export declare function hermesPluginState(home: string): HermesPluginState;
|
|
258
|
-
/**
|
|
259
|
-
* How to install a Python package into a specific interpreter on THIS machine.
|
|
260
|
-
*
|
|
261
|
-
* `<python> -m pip install` is the obvious answer and it is frequently wrong: a
|
|
262
|
-
* venv created by `uv venv` has no pip at all (that is uv's default), so the
|
|
263
|
-
* command fails with
|
|
264
|
-
*
|
|
265
|
-
* /path/venv/bin/python3: No module named pip
|
|
266
|
-
*
|
|
267
|
-
* after setup has already written every config file — which is exactly what
|
|
268
|
-
* happened on a real Hermes box. So probe, in order of what suits the venv:
|
|
269
|
-
*
|
|
270
|
-
* 1. `uv pip install --python <python>` when uv is present. Correct for a
|
|
271
|
-
* uv-created venv and fast; uv is also what created most pip-less venvs.
|
|
272
|
-
* 2. `<python> -m pip install` when pip actually answers.
|
|
273
|
-
* 3. Neither — hand it over, with `ensurepip` named, rather than planning a
|
|
274
|
-
* command that is known in advance to fail.
|
|
275
|
-
*/
|
|
276
|
-
export declare function pythonInstallStrategy(python: string, pkg: string): {
|
|
277
|
-
kind: "exec";
|
|
278
|
-
command: string;
|
|
279
|
-
args: string[];
|
|
280
|
-
how: string;
|
|
281
|
-
} | {
|
|
282
|
-
kind: "manual";
|
|
283
|
-
why: string;
|
|
284
|
-
snippet: string;
|
|
285
|
-
};
|
|
286
|
-
/**
|
|
287
|
-
* The env vars the Hermes plugin documents, merged into an existing `.env`.
|
|
288
|
-
*
|
|
289
|
-
* A `.env` is line-oriented and hand-maintained, so this is a line merge rather
|
|
290
|
-
* than a parse-and-reserialize: keys Atbash owns are replaced in place (keeping
|
|
291
|
-
* their position), keys it does not own are never touched, and anything else in
|
|
292
|
-
* the file — comments, blank lines, unrelated settings, ordering — survives
|
|
293
|
-
* exactly as written. Reformatting someone's .env to add four lines would be a
|
|
294
|
-
* poor trade.
|
|
295
|
-
*
|
|
296
|
-
* Values are from the published plugin README (PyPI atbash-hermes-plugin 0.4.5).
|
|
297
|
-
* `ATBASH_ORG_NAME` is deliberately NOT written: its value is the operator's org,
|
|
298
|
-
* which this command has no reliable way to know, and a wrong org sends the SDK
|
|
299
|
-
* at the wrong chain. It is called out in the manual step instead.
|
|
300
|
-
*/
|
|
301
|
-
export declare function mergeHermesEnv(existing: string | null): string;
|
|
302
|
-
/**
|
|
303
|
-
* Does this config's existing Atbash entry carry a key in its `env` block?
|
|
304
|
-
*
|
|
305
|
-
* True means the operator hand-wired it from the published docs and their private
|
|
306
|
-
* key is sitting in that file today. Setup takes it out, but the backup it writes
|
|
307
|
-
* first still has it — so this exists to make that sayable rather than silently
|
|
308
|
-
* relocating the leak.
|
|
309
|
-
*/
|
|
310
|
-
export declare function hadInlineKey(config: Record<string, unknown>, serversKey?: "mcpServers" | "servers"): boolean;
|
|
311
|
-
export declare function mergeMcpServer(config: Record<string, unknown>, serversKey?: "mcpServers" | "servers"): Record<string, unknown>;
|
|
312
104
|
/**
|
|
313
105
|
* Work out everything that needs doing on this machine, without doing any of it.
|
|
314
106
|
*
|