@agent-beam/beam 0.2.30 → 0.2.31
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 +48 -3
- package/Skills/agentbeam-app-monitoring/SKILL.md +5 -4
- package/dist/cli.js +108 -0
- package/dist/cli.js.map +1 -1
- package/dist/cve.js +1 -1
- package/dist/cve.js.map +1 -1
- package/dist/monitor-client.d.ts +1 -1
- package/dist/monitor-client.js +3 -3
- package/dist/monitor-client.js.map +1 -1
- package/dist/monitor.js +3 -3
- package/dist/monitor.js.map +1 -1
- package/dist/package-risk-rules.d.ts +27 -0
- package/dist/package-risk-rules.js +137 -0
- package/dist/package-risk-rules.js.map +1 -0
- package/dist/package-scan.d.ts +50 -0
- package/dist/package-scan.js +279 -0
- package/dist/package-scan.js.map +1 -0
- package/dist/packages.d.ts +43 -0
- package/dist/packages.js +228 -0
- package/dist/packages.js.map +1 -0
- package/dist/sdk.d.ts +1 -1
- package/dist/share-cli.d.ts +2 -0
- package/dist/share-cli.js +185 -0
- package/dist/share-cli.js.map +1 -0
- package/dist/share.d.ts +138 -0
- package/dist/share.js +384 -0
- package/dist/share.js.map +1 -0
- package/package.json +1 -1
- package/stress-report.json +68 -35
package/dist/share.js
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { lstat, mkdir, mkdtemp, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir, tmpdir } from "node:os";
|
|
4
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
5
|
+
import { getDataDirectory } from "./config.js";
|
|
6
|
+
import { scanSkillDir, scanSkillFile } from "./skill-scan.js";
|
|
7
|
+
import { isBlocked, SKILL_TARGETS } from "./skills.js";
|
|
8
|
+
// `beam share`: the team library. Shares a skill, CLAUDE.md / AGENTS.md, slash command, subagent
|
|
9
|
+
// or Cursor rule with everyone in the workspace, and installs what teammates shared.
|
|
10
|
+
//
|
|
11
|
+
// What leaves the machine: exactly the files listed before you confirm -- never anything else in
|
|
12
|
+
// the folder (hidden files, node_modules, symlinks and non-text files are left out). A file with a
|
|
13
|
+
// credential is refused here before upload, and again by the workspace. Downloads are checked
|
|
14
|
+
// against the workspace's content hash, validated, and re-scanned before anything is written.
|
|
15
|
+
//
|
|
16
|
+
// The file rules mirror the dashboard's lib/shared-assets/files.ts -- keep the two in step.
|
|
17
|
+
export const SHARE_KINDS = ["SKILL", "INSTRUCTIONS", "COMMAND", "SUBAGENT", "RULE"];
|
|
18
|
+
export const KIND_NAMES = { SKILL: "skill", INSTRUCTIONS: "instructions", COMMAND: "slash command", SUBAGENT: "subagent", RULE: "Cursor rule" };
|
|
19
|
+
export const MAX_FILES = 100;
|
|
20
|
+
export const MAX_FILE_BYTES = 128 * 1024;
|
|
21
|
+
export const MAX_TOTAL_BYTES = 512 * 1024;
|
|
22
|
+
const TEXT_EXT = /\.(?:md|mdx|mdc|txt|json|ya?ml|toml|sh|bash|zsh|py|js|mjs|cjs|ts|rb|ps1)$/i;
|
|
23
|
+
const SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._ -]{0,99}$/;
|
|
24
|
+
export const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
25
|
+
const INSTRUCTION_FILES = new Set(["CLAUDE.md", "AGENTS.md", "GEMINI.md"]);
|
|
26
|
+
const SKIP_DIR = new Set(["node_modules", "__pycache__", ".git", ".venv"]);
|
|
27
|
+
export const slugify = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
|
|
28
|
+
const sha256 = (text) => createHash("sha256").update(text, "utf8").digest("hex");
|
|
29
|
+
const byPath = (a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
30
|
+
export function pathProblem(path) {
|
|
31
|
+
if (path.length > 300)
|
|
32
|
+
return "is too long";
|
|
33
|
+
const segments = path.split("/");
|
|
34
|
+
if (segments.length > 7)
|
|
35
|
+
return "is nested too deeply";
|
|
36
|
+
if (!segments.every(s => SEGMENT.test(s)))
|
|
37
|
+
return "has an unsupported name";
|
|
38
|
+
if (!TEXT_EXT.test(path))
|
|
39
|
+
return "is not a supported text file";
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/** Same algorithm as the workspace: each path and its content's hash, sorted by path. */
|
|
43
|
+
export function contentHash(files) {
|
|
44
|
+
return sha256([...files].sort(byPath).map(f => `${f.path}\0${sha256(f.content)}\n`).join(""));
|
|
45
|
+
}
|
|
46
|
+
export function validateShareFiles(kind, raw) {
|
|
47
|
+
const files = [...raw].sort(byPath);
|
|
48
|
+
const seen = new Set();
|
|
49
|
+
let total = 0;
|
|
50
|
+
if (!files.length)
|
|
51
|
+
throw new Error("There are no files to share.");
|
|
52
|
+
if (files.length > MAX_FILES)
|
|
53
|
+
throw new Error(`More than ${MAX_FILES} files.`);
|
|
54
|
+
for (const f of files) {
|
|
55
|
+
const problem = pathProblem(f.path);
|
|
56
|
+
if (problem)
|
|
57
|
+
throw new Error(`"${f.path}" ${problem}.`);
|
|
58
|
+
if (seen.has(f.path.toLowerCase()))
|
|
59
|
+
throw new Error(`"${f.path}" appears more than once.`);
|
|
60
|
+
seen.add(f.path.toLowerCase());
|
|
61
|
+
if (f.content.includes("\u0000"))
|
|
62
|
+
throw new Error(`"${f.path}" is not a text file.`);
|
|
63
|
+
const size = Buffer.byteLength(f.content, "utf8");
|
|
64
|
+
if (size > MAX_FILE_BYTES)
|
|
65
|
+
throw new Error(`"${f.path}" is over ${MAX_FILE_BYTES / 1024} KB.`);
|
|
66
|
+
total += size;
|
|
67
|
+
}
|
|
68
|
+
if (total > MAX_TOTAL_BYTES)
|
|
69
|
+
throw new Error(`The files add up to more than ${MAX_TOTAL_BYTES / 1024} KB.`);
|
|
70
|
+
if (kind === "SKILL") {
|
|
71
|
+
if (!files.some(f => f.path === "SKILL.md"))
|
|
72
|
+
throw new Error("A skill needs a SKILL.md at the top of its folder.");
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
if (files.length !== 1 || files[0].path.includes("/"))
|
|
76
|
+
throw new Error(`A ${KIND_NAMES[kind]} is a single file.`);
|
|
77
|
+
if (kind === "INSTRUCTIONS" && !INSTRUCTION_FILES.has(files[0].path))
|
|
78
|
+
throw new Error("Instructions are shared as CLAUDE.md, AGENTS.md or GEMINI.md.");
|
|
79
|
+
if (kind === "RULE" ? !/\.mdc?$/.test(files[0].path) : !/\.md$/.test(files[0].path))
|
|
80
|
+
throw new Error(kind === "RULE" ? "A Cursor rule is an .mdc or .md file." : `A ${KIND_NAMES[kind]} is a .md file.`);
|
|
81
|
+
return files;
|
|
82
|
+
}
|
|
83
|
+
// Shaped credentials, same set the workspace refuses. Reported by file and line only.
|
|
84
|
+
const CREDENTIALS = [
|
|
85
|
+
{ kind: "private key", re: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },
|
|
86
|
+
{ kind: "API key", re: /\b(?:sk-(?:proj-|ant-)?[A-Za-z0-9_-]{20,}|AKIA[A-Z0-9]{16}|AIza[0-9A-Za-z_-]{35}|xox[baprs]-[A-Za-z0-9-]{10,}|beam_app_[\w-]{20,})\b/ },
|
|
87
|
+
{ kind: "access token", re: /\b(?:gh[pousr]_[A-Za-z0-9_]{30,}|github_pat_[A-Za-z0-9_]{30,}|glpat-[A-Za-z0-9_-]{20,}|npm_[A-Za-z0-9]{36})\b/ },
|
|
88
|
+
{ kind: "credential in a URL", re: /\b[a-z][a-z0-9+.-]*:\/\/[^\s/:@]+:[^\s/@]{6,}@/i },
|
|
89
|
+
];
|
|
90
|
+
export function findCredentials(files) {
|
|
91
|
+
const hits = [];
|
|
92
|
+
for (const f of files)
|
|
93
|
+
f.content.split(/\r?\n/).forEach((line, i) => {
|
|
94
|
+
const found = CREDENTIALS.find(c => c.re.test(line));
|
|
95
|
+
if (found)
|
|
96
|
+
hits.push({ file: f.path, line: i + 1, kind: found.kind });
|
|
97
|
+
});
|
|
98
|
+
return hits;
|
|
99
|
+
}
|
|
100
|
+
async function isDirectory(path) { try {
|
|
101
|
+
return (await stat(path)).isDirectory();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
} }
|
|
106
|
+
/** What a path is, from where it lives and what it's called. null: ask with --kind. */
|
|
107
|
+
export async function detectKind(target) {
|
|
108
|
+
const full = resolve(target);
|
|
109
|
+
if (await isDirectory(full))
|
|
110
|
+
return (await stat(join(full, "SKILL.md")).then(s => s.isFile(), () => false)) ? "SKILL" : null;
|
|
111
|
+
const name = basename(full);
|
|
112
|
+
const parts = full.split(sep);
|
|
113
|
+
if (name === "SKILL.md")
|
|
114
|
+
return "SKILL";
|
|
115
|
+
if (INSTRUCTION_FILES.has(name))
|
|
116
|
+
return "INSTRUCTIONS";
|
|
117
|
+
if (name.endsWith(".mdc") || parts.slice(-3, -1).join("/") === ".cursor/rules")
|
|
118
|
+
return "RULE";
|
|
119
|
+
if (parts.at(-2) === "commands")
|
|
120
|
+
return "COMMAND";
|
|
121
|
+
if (parts.at(-2) === "agents")
|
|
122
|
+
return "SUBAGENT";
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
// Reads exactly what would be shared. Hidden files and folders, node_modules, symlinks and
|
|
126
|
+
// non-text files are left out (and listed, so nothing is dropped silently).
|
|
127
|
+
export async function collectShareFiles(target, kind) {
|
|
128
|
+
let full = resolve(target);
|
|
129
|
+
if (kind === "SKILL" && basename(full) === "SKILL.md")
|
|
130
|
+
full = dirname(full);
|
|
131
|
+
const skipped = [];
|
|
132
|
+
if (kind !== "SKILL") {
|
|
133
|
+
if ((await lstat(full)).isSymbolicLink())
|
|
134
|
+
throw new Error(`${target} is a symlink; share the file it points to.`);
|
|
135
|
+
const content = await readFile(full, "utf8");
|
|
136
|
+
return { root: dirname(full), files: validateShareFiles(kind, [{ path: basename(full), content }]), skipped, defaultName: basename(full).replace(/\.mdc?$/, "") };
|
|
137
|
+
}
|
|
138
|
+
const files = [];
|
|
139
|
+
const walk = async (dir) => {
|
|
140
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
141
|
+
const abs = join(dir, entry.name);
|
|
142
|
+
const rel = relative(full, abs).split(sep).join("/");
|
|
143
|
+
if (entry.isSymbolicLink()) {
|
|
144
|
+
skipped.push(`${rel} (symlink)`);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (entry.name.startsWith(".") || SKIP_DIR.has(entry.name)) {
|
|
148
|
+
skipped.push(`${rel}${entry.isDirectory() ? "/" : ""} (hidden or generated)`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (entry.isDirectory()) {
|
|
152
|
+
await walk(abs);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (!entry.isFile())
|
|
156
|
+
continue;
|
|
157
|
+
const problem = pathProblem(rel);
|
|
158
|
+
if (problem) {
|
|
159
|
+
skipped.push(`${rel} (${problem})`);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if ((await stat(abs)).size > MAX_FILE_BYTES) {
|
|
163
|
+
skipped.push(`${rel} (over ${MAX_FILE_BYTES / 1024} KB)`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const content = await readFile(abs, "utf8");
|
|
167
|
+
if (content.includes("\u0000")) {
|
|
168
|
+
skipped.push(`${rel} (binary)`);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
files.push({ path: rel, content });
|
|
172
|
+
if (files.length > MAX_FILES)
|
|
173
|
+
throw new Error(`${target} has more than ${MAX_FILES} files to share.`);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
await walk(full);
|
|
177
|
+
const frontmatterName = files.find(f => f.path === "SKILL.md")?.content.match(/^---[\s\S]*?^name:\s*["']?([^"'\n]+)["']?\s*$/m)?.[1]?.trim();
|
|
178
|
+
return { root: full, files: validateShareFiles(kind, files), skipped, defaultName: frontmatterName || basename(full) };
|
|
179
|
+
}
|
|
180
|
+
async function call(identity, method, path, body) {
|
|
181
|
+
let response;
|
|
182
|
+
try {
|
|
183
|
+
response = await fetch(`${identity.apiBase}${path}`, {
|
|
184
|
+
method,
|
|
185
|
+
headers: { Authorization: `Bearer ${identity.deviceSecret}`, ...(body ? { "Content-Type": "application/json" } : {}) },
|
|
186
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
187
|
+
signal: AbortSignal.timeout(30_000),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
throw new Error(`Could not reach ${identity.apiBase}.`);
|
|
192
|
+
}
|
|
193
|
+
let json = {};
|
|
194
|
+
try {
|
|
195
|
+
json = await response.json();
|
|
196
|
+
}
|
|
197
|
+
catch { /* non-JSON error page */ }
|
|
198
|
+
if (response.status === 401)
|
|
199
|
+
throw new Error("This device's credentials were revoked. Run 'beam setup' again.");
|
|
200
|
+
if (!response.ok) {
|
|
201
|
+
if (response.status === 404 && !json.error)
|
|
202
|
+
throw new Error("This workspace doesn't have the team library yet.");
|
|
203
|
+
throw new Error(json.error ?? `The workspace answered ${response.status}.`);
|
|
204
|
+
}
|
|
205
|
+
return json;
|
|
206
|
+
}
|
|
207
|
+
export const listShares = (identity, kind) => call(identity, "GET", `/v1/shares${kind ? `?kind=${kind}` : ""}`);
|
|
208
|
+
export const publishShare = (identity, input) => call(identity, "POST", "/v1/shares", input);
|
|
209
|
+
export const deleteShare = (identity, slug) => call(identity, "DELETE", `/v1/shares/${encodeURIComponent(slug)}`);
|
|
210
|
+
async function downloadShare(identity, slug, version) {
|
|
211
|
+
if (!SLUG.test(slug))
|
|
212
|
+
throw new Error(`"${slug}" isn't a valid share name.`);
|
|
213
|
+
return call(identity, "POST", `/v1/shares/${slug}/install${version ? `?version=${version}` : ""}`);
|
|
214
|
+
}
|
|
215
|
+
const lockFile = () => join(getDataDirectory(), "shared-installs.json");
|
|
216
|
+
export async function readLock() {
|
|
217
|
+
try {
|
|
218
|
+
return JSON.parse(await readFile(lockFile(), "utf8"));
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return {};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function writeLock(lock) {
|
|
225
|
+
await mkdir(getDataDirectory(), { recursive: true, mode: 0o700 });
|
|
226
|
+
const temp = `${lockFile()}.tmp`;
|
|
227
|
+
await writeFile(temp, `${JSON.stringify(lock, null, 2)}\n`, { mode: 0o600 });
|
|
228
|
+
await rename(temp, lockFile());
|
|
229
|
+
}
|
|
230
|
+
const GLOBAL_INSTRUCTIONS = { "CLAUDE.md": ".claude/CLAUDE.md", "AGENTS.md": ".codex/AGENTS.md", "GEMINI.md": ".gemini/GEMINI.md" };
|
|
231
|
+
/** Where a share goes: one folder per agent for a skill, one file for everything else. */
|
|
232
|
+
export function installTargets(kind, slug, fileName, options = {}) {
|
|
233
|
+
const base = options.global ? (options.home ?? homedir()) : (options.cwd ?? process.cwd());
|
|
234
|
+
if (kind === "SKILL") {
|
|
235
|
+
const agents = options.allAgents ? Object.keys(SKILL_TARGETS) : options.agent?.length ? options.agent : ["claude-code"];
|
|
236
|
+
for (const a of agents)
|
|
237
|
+
if (!SKILL_TARGETS[a])
|
|
238
|
+
throw new Error(`Unknown agent "${a}". Choose from: ${Object.keys(SKILL_TARGETS).join(", ")}.`);
|
|
239
|
+
return [...new Set(agents.map(a => join(base, SKILL_TARGETS[a][options.global ? "global" : "project"], slug)))];
|
|
240
|
+
}
|
|
241
|
+
if (kind === "INSTRUCTIONS")
|
|
242
|
+
return [join(base, options.global ? GLOBAL_INSTRUCTIONS[fileName] ?? fileName : fileName)];
|
|
243
|
+
if (kind === "COMMAND")
|
|
244
|
+
return [join(base, ".claude/commands", `${slug}.md`)];
|
|
245
|
+
if (kind === "SUBAGENT")
|
|
246
|
+
return [join(base, ".claude/agents", `${slug}.md`)];
|
|
247
|
+
if (options.global)
|
|
248
|
+
throw new Error("Cursor rules are per project; run without -g inside the project.");
|
|
249
|
+
return [join(base, ".cursor/rules", `${slug}${fileName.endsWith(".mdc") ? ".mdc" : ".md"}`)];
|
|
250
|
+
}
|
|
251
|
+
async function exists(path) { try {
|
|
252
|
+
await lstat(path);
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return false;
|
|
257
|
+
} }
|
|
258
|
+
/** Hash of what's on disk at an install path, to tell "still as we installed it" from "edited locally". */
|
|
259
|
+
async function localHash(path) {
|
|
260
|
+
try {
|
|
261
|
+
const info = await lstat(path);
|
|
262
|
+
if (info.isFile())
|
|
263
|
+
return sha256(await readFile(path, "utf8"));
|
|
264
|
+
if (!info.isDirectory())
|
|
265
|
+
return null;
|
|
266
|
+
const files = [];
|
|
267
|
+
const walk = async (dir) => {
|
|
268
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
269
|
+
const abs = join(dir, entry.name);
|
|
270
|
+
if (entry.isDirectory())
|
|
271
|
+
await walk(abs);
|
|
272
|
+
else if (entry.isFile())
|
|
273
|
+
files.push({ path: relative(path, abs).split(sep).join("/"), content: await readFile(abs, "utf8") });
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
await walk(path);
|
|
277
|
+
return contentHash(files);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Writes into `target` only: every path is re-validated and must resolve inside it.
|
|
284
|
+
async function writeTree(target, files) {
|
|
285
|
+
await mkdir(target, { recursive: true, mode: 0o755 });
|
|
286
|
+
for (const f of files) {
|
|
287
|
+
if (pathProblem(f.path))
|
|
288
|
+
throw new Error(`Refusing unsafe path "${f.path}".`);
|
|
289
|
+
const dest = resolve(target, f.path);
|
|
290
|
+
if (!dest.startsWith(resolve(target) + sep))
|
|
291
|
+
throw new Error(`Refusing path outside the install folder: "${f.path}".`);
|
|
292
|
+
await mkdir(dirname(dest), { recursive: true, mode: 0o755 });
|
|
293
|
+
await writeFile(dest, f.content, { mode: 0o644 }); // never executable
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async function placeDownload(download, dests, force) {
|
|
297
|
+
// Never trust the response: same validation as an upload, and the hash must match the workspace's.
|
|
298
|
+
const files = validateShareFiles(download.kind, download.files.map(f => ({ path: String(f.path), content: String(f.content) })));
|
|
299
|
+
if (contentHash(files) !== download.contentHash)
|
|
300
|
+
throw new Error(`The download of "${download.slug}" doesn't match its content hash. Nothing was installed.`);
|
|
301
|
+
const staging = await mkdtemp(join(tmpdir(), "beam-share-"));
|
|
302
|
+
try {
|
|
303
|
+
const stagedRoot = join(staging, download.slug);
|
|
304
|
+
await writeTree(stagedRoot, files);
|
|
305
|
+
// beam's own full skill scan on this machine, on top of the workspace's.
|
|
306
|
+
const scan = download.kind === "SKILL" ? await scanSkillDir(stagedRoot, download.slug) : await scanSkillFile(join(stagedRoot, files[0].path));
|
|
307
|
+
const result = { slug: download.slug, name: download.name, kind: download.kind, version: download.version, installed: [], backups: [], scan, blocked: false, conflicts: [] };
|
|
308
|
+
if (isBlocked(scan) && !force) {
|
|
309
|
+
result.blocked = true;
|
|
310
|
+
return result;
|
|
311
|
+
}
|
|
312
|
+
const lock = await readLock();
|
|
313
|
+
for (const dest of dests) {
|
|
314
|
+
if (await exists(dest)) {
|
|
315
|
+
if ((await lstat(dest)).isSymbolicLink())
|
|
316
|
+
throw new Error(`${dest} is a symlink; refusing to write through it.`);
|
|
317
|
+
const ours = lock[dest];
|
|
318
|
+
const untouched = ours && ours.slug === download.slug && (await localHash(dest)) === ours.localHash;
|
|
319
|
+
if (!untouched && !force) {
|
|
320
|
+
result.conflicts.push(dest);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if (!untouched) {
|
|
324
|
+
const backup = `${dest}.beam-backup-${new Date().toISOString().replace(/[:.]/g, "-")}`;
|
|
325
|
+
await rename(dest, backup);
|
|
326
|
+
result.backups.push(backup);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
330
|
+
// Write beside the destination, then swap it in, so a failure never leaves half a skill.
|
|
331
|
+
const temp = `${dest}.beam-tmp-${randomBytes(4).toString("hex")}`;
|
|
332
|
+
try {
|
|
333
|
+
if (download.kind === "SKILL")
|
|
334
|
+
await writeTree(temp, files);
|
|
335
|
+
else
|
|
336
|
+
await writeFile(temp, files[0].content, { mode: 0o644 });
|
|
337
|
+
await rm(dest, { recursive: true, force: true });
|
|
338
|
+
await rename(temp, dest);
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
await rm(temp, { recursive: true, force: true });
|
|
342
|
+
}
|
|
343
|
+
lock[dest] = { slug: download.slug, kind: download.kind, version: download.version, contentHash: download.contentHash, localHash: (await localHash(dest)) ?? "", installedAt: new Date().toISOString() };
|
|
344
|
+
result.installed.push(dest);
|
|
345
|
+
}
|
|
346
|
+
await writeLock(lock);
|
|
347
|
+
return result;
|
|
348
|
+
}
|
|
349
|
+
finally {
|
|
350
|
+
await rm(staging, { recursive: true, force: true });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
export async function installShare(identity, slug, options = {}) {
|
|
354
|
+
const download = await downloadShare(identity, slug, options.version);
|
|
355
|
+
const fileName = download.files[0]?.path ?? "";
|
|
356
|
+
return placeDownload(download, installTargets(download.kind, download.slug, fileName, options), Boolean(options.force));
|
|
357
|
+
}
|
|
358
|
+
/** Brings every installed share (or one) up to its newest approved version, in the places it was installed. */
|
|
359
|
+
export async function updateShares(identity, options = {}) {
|
|
360
|
+
const lock = await readLock();
|
|
361
|
+
const bySlug = new Map();
|
|
362
|
+
for (const [path, entry] of Object.entries(lock))
|
|
363
|
+
if (!options.slug || entry.slug === options.slug)
|
|
364
|
+
bySlug.set(entry.slug, [...(bySlug.get(entry.slug) ?? []), path]);
|
|
365
|
+
if (options.slug && !bySlug.size)
|
|
366
|
+
throw new Error(`"${options.slug}" isn't installed on this device. Install it with 'beam share install ${options.slug}'.`);
|
|
367
|
+
const { assets } = await listShares(identity);
|
|
368
|
+
const latest = new Map(assets.map(a => [a.slug, a.version]));
|
|
369
|
+
const report = { updated: [], current: [], removed: [] };
|
|
370
|
+
for (const [slug, paths] of bySlug) {
|
|
371
|
+
const available = latest.get(slug);
|
|
372
|
+
if (available === undefined) {
|
|
373
|
+
report.removed.push({ slug, paths });
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (available === null || paths.every(p => lock[p].version >= available)) {
|
|
377
|
+
report.current.push(slug);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
report.updated.push(await placeDownload(await downloadShare(identity, slug), paths, Boolean(options.force)));
|
|
381
|
+
}
|
|
382
|
+
return report;
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=share.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share.js","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-beam/beam",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"description": "Local-first observation and heuristic risk scanning for AI coding agents (Claude Code, Codex, Cursor, Copilot CLI, Gemini). Redacts secrets, flags risky tool calls, scans skills and MCP configs offline.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai agent security",
|
package/stress-report.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
3
|
"package": "@agent-beam/beam",
|
|
4
|
-
"version": "0.2.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.2.31",
|
|
5
|
+
"generatedAt": "2026-10-24T07:03:56.978Z",
|
|
6
6
|
"passed": true,
|
|
7
7
|
"environment": {
|
|
8
8
|
"node": "v24.5.0",
|
|
@@ -16,42 +16,75 @@
|
|
|
16
16
|
"id": "hostile-input",
|
|
17
17
|
"title": "Hostile input",
|
|
18
18
|
"passed": true,
|
|
19
|
-
"summary": "41 attack shapes at 16 KB; the slowest took
|
|
19
|
+
"summary": "41 attack shapes at 16 KB; the slowest took 6.41 ms (unicode tags)",
|
|
20
20
|
"measured": {
|
|
21
|
-
"worstMs":
|
|
21
|
+
"worstMs": 6.41,
|
|
22
22
|
"cases": 41,
|
|
23
23
|
"slowest": [
|
|
24
24
|
{
|
|
25
25
|
"input": "unicode tags",
|
|
26
|
-
"ms":
|
|
26
|
+
"ms": 6.41
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"input": "curl|",
|
|
30
|
-
"ms":
|
|
30
|
+
"ms": 5.97
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"input": "",
|
|
53
|
+
"measured": {
|
|
54
|
+
"worstMs": 135.3,
|
|
55
|
+
"cases": 17,
|
|
56
|
+
"slowest": [
|
|
57
|
+
{
|
|
58
|
+
"input": "curl ",
|
|
59
|
+
"ms": 135.3
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"input": "short lines",
|
|
63
|
+
"ms": 114.7
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"input": "ngrok",
|
|
67
|
+
"ms": 75
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"input": "webhook",
|
|
71
|
+
"ms": 57.1
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"input": "one long line",
|
|
75
|
+
"ms": 55.6
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"limit": "under 1 s for any single 3 MB file"
|
|
80
|
+
},
|
|
48
81
|
{
|
|
49
82
|
"id": "throughput",
|
|
50
83
|
"title": "Log throughput",
|
|
51
84
|
"passed": true,
|
|
52
|
-
"summary": "
|
|
85
|
+
"summary": "79,283 log lines per second on one core, attacks included",
|
|
53
86
|
"measured": {
|
|
54
|
-
"linesPerSecond":
|
|
87
|
+
"linesPerSecond": 79283,
|
|
55
88
|
"lines": 300000
|
|
56
89
|
},
|
|
57
90
|
"limit": "over 10,000 lines per second"
|
|
@@ -60,10 +93,10 @@
|
|
|
60
93
|
"id": "per-call",
|
|
61
94
|
"title": "Cost per call in your app",
|
|
62
95
|
"passed": true,
|
|
63
|
-
"summary": "request()
|
|
96
|
+
"summary": "request() 12.5 µs, prompt() 8.7 µs on a short message",
|
|
64
97
|
"measured": {
|
|
65
|
-
"requestMicros":
|
|
66
|
-
"promptMicros":
|
|
98
|
+
"requestMicros": 12.5,
|
|
99
|
+
"promptMicros": 8.7
|
|
67
100
|
},
|
|
68
101
|
"limit": "request() under 100 µs and prompt() under 200 µs"
|
|
69
102
|
},
|
|
@@ -71,18 +104,18 @@
|
|
|
71
104
|
"id": "memory-cli",
|
|
72
105
|
"title": "Memory under load (beam monitor)",
|
|
73
106
|
"passed": true,
|
|
74
|
-
"summary": "8.
|
|
107
|
+
"summary": "8.8 MB at start; 10.3, 10.4, 10.3, 10.4, 10.4, 10.4 MB after each 500,000 lines; +0 MB from 1M to 3M lines",
|
|
75
108
|
"measured": {
|
|
76
109
|
"heapMb": [
|
|
77
|
-
|
|
78
|
-
10.
|
|
79
|
-
10,
|
|
80
|
-
10,
|
|
81
|
-
10,
|
|
82
|
-
10
|
|
110
|
+
10.3,
|
|
111
|
+
10.4,
|
|
112
|
+
10.3,
|
|
113
|
+
10.4,
|
|
114
|
+
10.4,
|
|
115
|
+
10.4
|
|
83
116
|
],
|
|
84
|
-
"startMb": 8.
|
|
85
|
-
"growthMb":
|
|
117
|
+
"startMb": 8.8,
|
|
118
|
+
"growthMb": 0,
|
|
86
119
|
"footprint": {
|
|
87
120
|
"seen": 200,
|
|
88
121
|
"queue": 1000,
|
|
@@ -97,13 +130,13 @@
|
|
|
97
130
|
"id": "memory-sdk",
|
|
98
131
|
"title": "Memory in your app while AgentBeam is down",
|
|
99
132
|
"passed": true,
|
|
100
|
-
"summary": "8.
|
|
133
|
+
"summary": "8.8, 8.8, 8.8, 8.8 MB after each 250,000 requests and prompts",
|
|
101
134
|
"measured": {
|
|
102
135
|
"heapMb": [
|
|
103
|
-
8.
|
|
104
|
-
8.
|
|
105
|
-
8.
|
|
106
|
-
8.
|
|
136
|
+
8.8,
|
|
137
|
+
8.8,
|
|
138
|
+
8.8,
|
|
139
|
+
8.8
|
|
107
140
|
],
|
|
108
141
|
"growthMb": 0
|
|
109
142
|
},
|
|
@@ -113,12 +146,12 @@
|
|
|
113
146
|
"id": "outage",
|
|
114
147
|
"title": "AgentBeam down or slow",
|
|
115
148
|
"passed": true,
|
|
116
|
-
"summary": "request() stayed at
|
|
149
|
+
"summary": "request() stayed at 9 µs; 1 send attempt, then none while backing off; a hung connection was dropped after 5.0 s, off the request path",
|
|
117
150
|
"measured": {
|
|
118
|
-
"requestMicros":
|
|
151
|
+
"requestMicros": 9,
|
|
119
152
|
"attemptsBeforeBackoff": 1,
|
|
120
153
|
"attemptsDuringBackoff": 0,
|
|
121
|
-
"hungFlushMs":
|
|
154
|
+
"hungFlushMs": 5003
|
|
122
155
|
},
|
|
123
156
|
"limit": "no slowdown, no retries during backoff, hung sends dropped within 7 s"
|
|
124
157
|
},
|
|
@@ -126,13 +159,13 @@
|
|
|
126
159
|
"id": "cpu-budget",
|
|
127
160
|
"title": "CPU cap",
|
|
128
161
|
"passed": true,
|
|
129
|
-
"summary": "with a 1% cap (600 ms a minute), a flood of 200 KB documents got 642 ms of checking (
|
|
162
|
+
"summary": "with a 1% cap (600 ms a minute), a flood of 200 KB documents got 642 ms of checking (76 documents); the rest were skipped, flagged as skipped, at 0.08 µs each",
|
|
130
163
|
"measured": {
|
|
131
164
|
"capMs": 600,
|
|
132
165
|
"spentMs": 642,
|
|
133
|
-
"checked":
|
|
166
|
+
"checked": 76,
|
|
134
167
|
"skipped": 100000,
|
|
135
|
-
"skippedCallMicros": 0.
|
|
168
|
+
"skippedCallMicros": 0.08
|
|
136
169
|
},
|
|
137
170
|
"limit": "under twice the cap (one check can finish after the cap is reached)"
|
|
138
171
|
}
|