@agent-beam/beam 0.2.30 → 0.2.33

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.
Files changed (47) hide show
  1. package/README.md +74 -4
  2. package/Skills/agentbeam-app-monitoring/SKILL.md +5 -4
  3. package/dist/cli.js +110 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cve.js +1 -1
  6. package/dist/cve.js.map +1 -1
  7. package/dist/monitor-client.d.ts +45 -1
  8. package/dist/monitor-client.js +3 -3
  9. package/dist/monitor-client.js.map +1 -1
  10. package/dist/monitor-pipeline.d.ts +60 -9
  11. package/dist/monitor-pipeline.js +325 -5
  12. package/dist/monitor-pipeline.js.map +1 -1
  13. package/dist/monitor-rules.d.ts +58 -0
  14. package/dist/monitor-rules.js +130 -1
  15. package/dist/monitor-rules.js.map +1 -1
  16. package/dist/monitor-signals.d.ts +63 -0
  17. package/dist/monitor-signals.js +125 -0
  18. package/dist/monitor-signals.js.map +1 -0
  19. package/dist/monitor-stacks.d.ts +41 -0
  20. package/dist/monitor-stacks.js +129 -0
  21. package/dist/monitor-stacks.js.map +1 -0
  22. package/dist/monitor.d.ts +2 -0
  23. package/dist/monitor.js +12 -4
  24. package/dist/monitor.js.map +1 -1
  25. package/dist/package-risk-rules.d.ts +27 -0
  26. package/dist/package-risk-rules.js +137 -0
  27. package/dist/package-risk-rules.js.map +1 -0
  28. package/dist/package-scan.d.ts +50 -0
  29. package/dist/package-scan.js +279 -0
  30. package/dist/package-scan.js.map +1 -0
  31. package/dist/packages.d.ts +43 -0
  32. package/dist/packages.js +228 -0
  33. package/dist/packages.js.map +1 -0
  34. package/dist/sdk.d.ts +61 -1
  35. package/dist/sdk.js +93 -8
  36. package/dist/sdk.js.map +1 -1
  37. package/dist/share-cli.d.ts +2 -0
  38. package/dist/share-cli.js +185 -0
  39. package/dist/share-cli.js.map +1 -0
  40. package/dist/share.d.ts +138 -0
  41. package/dist/share.js +384 -0
  42. package/dist/share.js.map +1 -0
  43. package/dist/stack-detect.d.ts +3 -0
  44. package/dist/stack-detect.js +62 -0
  45. package/dist/stack-detect.js.map +1 -0
  46. package/package.json +3 -1
  47. package/stress-report.json +78 -38
@@ -0,0 +1,138 @@
1
+ import type { Identity } from "./enroll.js";
2
+ import { type SkillScan } from "./skill-scan.js";
3
+ export declare const SHARE_KINDS: readonly ["SKILL", "INSTRUCTIONS", "COMMAND", "SUBAGENT", "RULE"];
4
+ export type ShareKind = (typeof SHARE_KINDS)[number];
5
+ export type ShareFile = {
6
+ path: string;
7
+ content: string;
8
+ };
9
+ export declare const KIND_NAMES: Record<ShareKind, string>;
10
+ export declare const MAX_FILES = 100;
11
+ export declare const MAX_FILE_BYTES: number;
12
+ export declare const MAX_TOTAL_BYTES: number;
13
+ export declare const SLUG: RegExp;
14
+ export declare const slugify: (name: string) => string;
15
+ export declare function pathProblem(path: string): string | null;
16
+ /** Same algorithm as the workspace: each path and its content's hash, sorted by path. */
17
+ export declare function contentHash(files: ShareFile[]): string;
18
+ export declare function validateShareFiles(kind: ShareKind, raw: ShareFile[]): ShareFile[];
19
+ export type CredentialHit = {
20
+ file: string;
21
+ line: number;
22
+ kind: string;
23
+ };
24
+ export declare function findCredentials(files: ShareFile[]): CredentialHit[];
25
+ /** What a path is, from where it lives and what it's called. null: ask with --kind. */
26
+ export declare function detectKind(target: string): Promise<ShareKind | null>;
27
+ export type CollectedShare = {
28
+ root: string;
29
+ files: ShareFile[];
30
+ skipped: string[];
31
+ defaultName: string;
32
+ };
33
+ export declare function collectShareFiles(target: string, kind: ShareKind): Promise<CollectedShare>;
34
+ export type SharedListing = {
35
+ slug: string;
36
+ name: string;
37
+ description: string;
38
+ kind: ShareKind;
39
+ author: string | null;
40
+ mine: boolean;
41
+ installs: number;
42
+ updatedAt: string;
43
+ version: number | null;
44
+ contentHash: string | null;
45
+ score: number | null;
46
+ pending: {
47
+ version: number;
48
+ status: string;
49
+ note: string | null;
50
+ } | null;
51
+ };
52
+ export type PublishResult = {
53
+ slug: string;
54
+ version: number;
55
+ status: "APPROVED" | "PENDING_REVIEW";
56
+ unchanged: boolean;
57
+ score: number;
58
+ level: string;
59
+ findings: Array<{
60
+ id: string;
61
+ title: string;
62
+ severity: string;
63
+ file: string;
64
+ line: number;
65
+ }>;
66
+ };
67
+ export type Download = {
68
+ slug: string;
69
+ name: string;
70
+ kind: ShareKind;
71
+ description: string;
72
+ version: number;
73
+ contentHash: string;
74
+ score: number;
75
+ files: ShareFile[];
76
+ };
77
+ export declare const listShares: (identity: Identity, kind?: ShareKind) => Promise<{
78
+ sharing: string;
79
+ assets: SharedListing[];
80
+ }>;
81
+ export declare const publishShare: (identity: Identity, input: {
82
+ kind: ShareKind;
83
+ name: string;
84
+ slug: string;
85
+ description: string;
86
+ changelog: string;
87
+ files: ShareFile[];
88
+ }) => Promise<PublishResult>;
89
+ export declare const deleteShare: (identity: Identity, slug: string) => Promise<{
90
+ slug: string;
91
+ }>;
92
+ export type InstallOptions = {
93
+ version?: number;
94
+ agent?: string[];
95
+ allAgents?: boolean;
96
+ global?: boolean;
97
+ force?: boolean;
98
+ cwd?: string;
99
+ home?: string;
100
+ };
101
+ type LockEntry = {
102
+ slug: string;
103
+ kind: ShareKind;
104
+ version: number;
105
+ contentHash: string;
106
+ localHash: string;
107
+ installedAt: string;
108
+ };
109
+ type Lock = Record<string, LockEntry>;
110
+ export declare function readLock(): Promise<Lock>;
111
+ /** Where a share goes: one folder per agent for a skill, one file for everything else. */
112
+ export declare function installTargets(kind: ShareKind, slug: string, fileName: string, options?: InstallOptions): string[];
113
+ export type InstallResult = {
114
+ slug: string;
115
+ name: string;
116
+ kind: ShareKind;
117
+ version: number;
118
+ installed: string[];
119
+ backups: string[];
120
+ scan: SkillScan;
121
+ blocked: boolean;
122
+ conflicts: string[];
123
+ };
124
+ export declare function installShare(identity: Identity, slug: string, options?: InstallOptions): Promise<InstallResult>;
125
+ export type UpdateReport = {
126
+ updated: InstallResult[];
127
+ current: string[];
128
+ removed: Array<{
129
+ slug: string;
130
+ paths: string[];
131
+ }>;
132
+ };
133
+ /** Brings every installed share (or one) up to its newest approved version, in the places it was installed. */
134
+ export declare function updateShares(identity: Identity, options?: {
135
+ slug?: string;
136
+ force?: boolean;
137
+ }): Promise<UpdateReport>;
138
+ export {};
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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"}
@@ -0,0 +1,3 @@
1
+ import type { Stack } from "./monitor-stacks.js";
2
+ /** The stack an app directory looks like, or null when nothing says. Cheap: reads a few manifests. */
3
+ export declare function detectStack(dir: string): Stack | null;
@@ -0,0 +1,62 @@
1
+ // Works out an app's framework from its files, for `beam monitor --app` without `--stack`.
2
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ const read = (dir, file) => {
5
+ try {
6
+ return readFileSync(join(dir, file), "utf8");
7
+ }
8
+ catch {
9
+ return "";
10
+ }
11
+ };
12
+ /** The stack an app directory looks like, or null when nothing says. Cheap: reads a few manifests. */
13
+ export function detectStack(dir) {
14
+ const has = (file) => existsSync(join(dir, file));
15
+ if (has("wp-config.php") || has("wp-content"))
16
+ return "wordpress";
17
+ const pkg = read(dir, "package.json");
18
+ if (pkg) {
19
+ let deps = {};
20
+ try {
21
+ const json = JSON.parse(pkg);
22
+ deps = { ...json.devDependencies, ...json.dependencies };
23
+ }
24
+ catch { /* unreadable package.json: fall through to the other manifests */ }
25
+ if ("next" in deps)
26
+ return "nextjs";
27
+ if ("@nestjs/core" in deps)
28
+ return "nestjs";
29
+ if ("express" in deps || "fastify" in deps || "koa" in deps || "hono" in deps)
30
+ return "express";
31
+ if ("vite" in deps)
32
+ return "vite";
33
+ if (Object.keys(deps).length)
34
+ return "node";
35
+ }
36
+ const composer = read(dir, "composer.json");
37
+ if (composer)
38
+ return /"laravel\/framework"/.test(composer) ? "laravel" : "php";
39
+ if (has("manage.py"))
40
+ return "django";
41
+ const python = read(dir, "requirements.txt") + read(dir, "pyproject.toml") + read(dir, "Pipfile");
42
+ if (/^\s*django\b|["']django/im.test(python))
43
+ return "django";
44
+ if (/^\s*fastapi\b|["']fastapi/im.test(python))
45
+ return "fastapi";
46
+ if (/^\s*flask\b|["']flask/im.test(python))
47
+ return "flask";
48
+ if (/\brails\b/.test(read(dir, "Gemfile")))
49
+ return "rails";
50
+ const jvm = read(dir, "pom.xml") + read(dir, "build.gradle") + read(dir, "build.gradle.kts");
51
+ if (jvm)
52
+ return /spring-boot/.test(jvm) ? "spring" : "java";
53
+ if (has("go.mod"))
54
+ return "go";
55
+ try {
56
+ if (readdirSync(dir).some(f => /\.(?:csproj|sln|fsproj)$/.test(f)))
57
+ return "dotnet";
58
+ }
59
+ catch { /* not a directory we can read */ }
60
+ return null;
61
+ }
62
+ //# sourceMappingURL=stack-detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-detect.js","sourceRoot":"","sources":["../src/stack-detect.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.30",
3
+ "version": "0.2.33",
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",
@@ -64,6 +64,8 @@
64
64
  "setup": "npm run build && node dist/cli.js setup",
65
65
  "setup:global": "bash scripts/setup-global.sh",
66
66
  "validate:skills": "node Skills/scripts/validate-skills.mjs",
67
+ "release": "bash scripts/release-local.sh",
68
+ "release:local": "bash scripts/release-local.sh",
67
69
  "stress": "npm run build && node --expose-gc scripts/stress-report.mjs"
68
70
  },
69
71
  "publishConfig": {