@agent-beam/beam 0.2.27 → 0.2.29

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.
@@ -1 +1 @@
1
- {"version":3,"file":"monitor-rules.js","sourceRoot":"","sources":["../src/monitor-rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"monitor-rules.js","sourceRoot":"","sources":["../src/monitor-rules.ts"],"names":[],"mappings":"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"}
package/dist/monitor.d.ts CHANGED
@@ -1,39 +1,5 @@
1
- import { type MonitorFinding, type MonitorLevel, type MonitorSeverity, type Vulnerability } from "./monitor-client.js";
2
- import type { CustomDetector } from "./data-detectors.js";
3
- /** light: critical only · standard: high and up · strict: medium and up (same thresholds as the server). */
4
- export declare const meetsLevel: (severity: MonitorSeverity, level: MonitorLevel) => boolean;
5
- export declare const DEDUPE_WINDOW_MS: Record<MonitorLevel, number>;
6
- export declare const BRUTE_FORCE_THRESHOLD: Record<MonitorLevel, number>;
7
- export declare const MAX_NEW_FINDINGS_PER_10_MIN = 200;
8
- export type SendOutcome = "sent" | "retry" | "drop";
9
- export interface PipelineOptions {
10
- /** The active level, or null while capture is off (not enabled, or the allowance is spent). */
11
- level: () => MonitorLevel | null;
12
- customDetectors?: () => CustomDetector[];
13
- now?: () => number;
14
- }
15
- export declare class MonitorPipeline {
16
- private readonly opts;
17
- private seen;
18
- private queue;
19
- private queued;
20
- private authFailures;
21
- private floodBucket;
22
- private floodCount;
23
- private suppressed;
24
- constructor(opts: PipelineOptions);
25
- private now;
26
- get pending(): MonitorFinding[];
27
- /** Matches one line and queues any findings at or above the level. Returns the rule ids raised. */
28
- ingestLine(line: string, file?: string): string[];
29
- /** Queues a finding produced elsewhere (dependency checks) under its own stable id, once. */
30
- addFinding(finding: MonitorFinding): boolean;
31
- private raise;
32
- private emitSuppressed;
33
- private enqueue;
34
- /** Sends queued findings in batches; a "retry" outcome keeps the batch for the next flush. */
35
- flush(send: (batch: MonitorFinding[]) => Promise<SendOutcome>): Promise<void>;
36
- }
1
+ import { type MonitorFinding, type Vulnerability } from "./monitor-client.js";
2
+ export { BRUTE_FORCE_THRESHOLD, DEDUPE_WINDOW_MS, MAX_NEW_FINDINGS_PER_10_MIN, MonitorPipeline, meetsLevel, type PipelineOptions, type SendOutcome } from "./monitor-pipeline.js";
37
3
  /** Follows a log file like `tail -F`: survives rotation (new inode) and truncation (copytruncate). */
38
4
  export declare class FileTailer {
39
5
  private readonly path;
@@ -67,8 +33,35 @@ export interface MonitorOptions {
67
33
  fromStart?: boolean;
68
34
  /** Keep waiting while App monitoring is off in the dashboard (default) instead of exiting. */
69
35
  wait?: boolean;
36
+ /** LLM provider for the second opinion (--llm), with this server's own key; "beam" for Beam's model. */
37
+ llm?: string;
38
+ /** The most of one CPU core detection may use, in percent (--max-cpu). Default: monitor.json, else 25. */
39
+ maxCpu?: number;
70
40
  }
71
41
  export declare function runMonitor(options: MonitorOptions, log?: (message: string) => void): Promise<void>;
72
- export declare function monitorStatus(write?: (line: string) => void): Promise<number>;
73
- /** `beam monitor test`: one test finding through the real path, to prove an integration end to end. */
74
- export declare function monitorTest(write?: (line: string) => void): Promise<number>;
42
+ export declare function monitorStatus(write?: (line: string) => void, llm?: string): Promise<number>;
43
+ /**
44
+ * `beam monitor test`: one test finding through the real path, to prove an integration end to end.
45
+ * With an own LLM (--llm), also one LLM check on a harmless sample, to prove the key works.
46
+ */
47
+ export declare function monitorTest(write?: (line: string) => void, llm?: string): Promise<number>;
48
+ export interface ConfigureOptions {
49
+ llm?: string;
50
+ model?: string;
51
+ baseUrl?: string;
52
+ keyEnv?: string;
53
+ key?: string;
54
+ forgetKey?: boolean;
55
+ files?: string[];
56
+ noFiles?: boolean;
57
+ app?: string;
58
+ noApp?: boolean;
59
+ maxCpu?: number;
60
+ }
61
+ /**
62
+ * `beam monitor configure`: saves settings to monitor.json so `beam monitor` needs no flags. With
63
+ * no options, prints the current settings. A key is only ever stored from stdin (`key`), and a
64
+ * provider's key that isn't set in this shell is a warning, not an error: it may be set only where
65
+ * beam monitor runs (a systemd EnvironmentFile, a container's secrets).
66
+ */
67
+ export declare function monitorConfigure(options: ConfigureOptions, write?: (line: string) => void): Promise<number>;
package/dist/monitor.js CHANGED
@@ -15,158 +15,10 @@ import { StringDecoder } from "node:string_decoder";
15
15
  import { readPolicy } from "./policy.js";
16
16
  import { readInstalledPackages } from "./lockfiles.js";
17
17
  import { checkPackages, fetchMonitorConfig, monitorAuth, sendFindings, } from "./monitor-client.js";
18
- import { clientIp, isAuthFailure, lineSource, matchLine, redactLine } from "./monitor-rules.js";
19
- import { judgeWithOwnLlm, ownLlmConfig } from "./monitor-llm.js";
20
- const RANK = { critical: 3, high: 2, medium: 1, low: 0 };
21
- const MIN_RANK = { light: 3, standard: 2, strict: 1 };
22
- /** light: critical only · standard: high and up · strict: medium and up (same thresholds as the server). */
23
- export const meetsLevel = (severity, level) => RANK[severity] >= MIN_RANK[level];
24
- // One finding absorbs repeats (its `count` goes up) for this long before a new one is raised.
25
- export const DEDUPE_WINDOW_MS = { light: 60 * 60_000, standard: 15 * 60_000, strict: 5 * 60_000 };
26
- // Failed sign-ins from one address within five minutes before it counts as brute forcing.
27
- export const BRUTE_FORCE_THRESHOLD = { light: 50, standard: 20, strict: 10 };
28
- const BRUTE_FORCE_WINDOW_MS = 5 * 60_000;
29
- // A scan or a log loop can match thousands of distinct lines; past this many new findings in ten
30
- // minutes the rest are folded into one summary finding so a flood can't spend the month's allowance.
31
- export const MAX_NEW_FINDINGS_PER_10_MIN = 200;
32
- const FLOOD_WINDOW_MS = 10 * 60_000;
33
- const MAX_QUEUE = 1000;
34
- const BATCH_SIZE = 100;
35
- /** Groups lines that differ only in ids, numbers, addresses or timestamps. */
36
- function normalizeForGrouping(line) {
37
- return line.toLowerCase()
38
- .replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/g, "<ip>")
39
- .replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g, "<id>")
40
- .replace(/\b[0-9a-f]{16,}\b/g, "<hex>")
41
- .replace(/\d+/g, "0")
42
- .replace(/\s+/g, " ")
43
- .slice(0, 300);
44
- }
45
- export class MonitorPipeline {
46
- opts;
47
- seen = new Map();
48
- queue = [];
49
- queued = new Set();
50
- authFailures = new Map();
51
- floodBucket = -1;
52
- floodCount = 0;
53
- suppressed = null;
54
- constructor(opts) {
55
- this.opts = opts;
56
- }
57
- now() { return this.opts.now?.() ?? Date.now(); }
58
- get pending() { return [...this.queue]; }
59
- /** Matches one line and queues any findings at or above the level. Returns the rule ids raised. */
60
- ingestLine(line, file) {
61
- const level = this.opts.level();
62
- if (!level || !line.trim())
63
- return [];
64
- const custom = this.opts.customDetectors?.() ?? [];
65
- const source = lineSource(line);
66
- const ip = source === "http" ? clientIp(line) : undefined;
67
- const raised = [];
68
- for (const rule of matchLine(line, source)) {
69
- if (!meetsLevel(rule.severity, level))
70
- continue;
71
- // Traffic groups by client address (one scan = one finding); app logs group by line shape.
72
- this.raise(level, ip ?? normalizeForGrouping(line), {
73
- ruleId: rule.id, title: ip ? `${rule.title} from ${ip}` : rule.title, severity: rule.severity,
74
- category: rule.category, source, file, evidence: redactLine(line, custom),
75
- });
76
- raised.push(rule.id);
77
- }
78
- if (isAuthFailure(line, source) && meetsLevel("high", level)) {
79
- const key = clientIp(line) ?? "unknown address";
80
- const now = this.now();
81
- const recent = (this.authFailures.get(key) ?? []).filter(t => now - t < BRUTE_FORCE_WINDOW_MS);
82
- recent.push(now);
83
- this.authFailures.set(key, recent);
84
- if (this.authFailures.size > 10_000)
85
- this.authFailures.delete(this.authFailures.keys().next().value);
86
- if (recent.length >= BRUTE_FORCE_THRESHOLD[level]) {
87
- this.raise(level, key, {
88
- ruleId: "app.auth_bruteforce", title: `Repeated failed sign-ins from ${key}`, severity: "high", category: "recon",
89
- source, file, evidence: `${recent.length} failures in 5 minutes. Latest: ${redactLine(line, custom)}`.slice(0, 600),
90
- });
91
- raised.push("app.auth_bruteforce");
92
- }
93
- }
94
- return raised;
95
- }
96
- /** Queues a finding produced elsewhere (dependency checks) under its own stable id, once. */
97
- addFinding(finding) {
98
- const level = this.opts.level();
99
- if (!level || !meetsLevel(finding.severity, level) || this.queued.has(finding.id))
100
- return false;
101
- this.queued.add(finding.id);
102
- this.enqueue(finding);
103
- return true;
104
- }
105
- raise(level, groupKey, partial) {
106
- const now = this.now();
107
- const bucket = Math.floor(now / DEDUPE_WINDOW_MS[level]);
108
- const fp = createHash("sha256").update(`${partial.ruleId}\0${groupKey}`).digest("hex").slice(0, 24);
109
- const existing = this.seen.get(fp);
110
- if (existing && existing.bucket === bucket) {
111
- existing.finding.count++; // still queued: the batch carries the new count
112
- return;
113
- }
114
- const flood = Math.floor(now / FLOOD_WINDOW_MS);
115
- if (flood !== this.floodBucket) {
116
- this.emitSuppressed();
117
- this.floodBucket = flood;
118
- this.floodCount = 0;
119
- }
120
- if (this.floodCount >= MAX_NEW_FINDINGS_PER_10_MIN) {
121
- const worst = this.suppressed && RANK[this.suppressed.severity] >= RANK[partial.severity] ? this.suppressed.severity : partial.severity;
122
- this.suppressed = { count: (this.suppressed?.count ?? 0) + 1, severity: worst };
123
- return;
124
- }
125
- this.floodCount++;
126
- const finding = { id: `${fp}-${bucket}`, ...partial, count: 1, firstSeen: new Date(now).toISOString() };
127
- this.seen.set(fp, { bucket, finding, at: now });
128
- this.enqueue(finding);
129
- }
130
- emitSuppressed() {
131
- if (!this.suppressed)
132
- return;
133
- const { count, severity } = this.suppressed;
134
- this.suppressed = null;
135
- this.enqueue({
136
- id: `flood-${this.floodBucket}`, ruleId: "beam.monitor.flood", title: "Too many findings to send individually", severity,
137
- category: "integrity", source: "log", count,
138
- evidence: `${count} more findings within 10 minutes were not sent one by one, to protect the monthly allowance. Check this server's logs.`,
139
- firstSeen: new Date(this.floodBucket * FLOOD_WINDOW_MS).toISOString(),
140
- });
141
- }
142
- enqueue(finding) {
143
- if (this.queue.length >= MAX_QUEUE) {
144
- // Full (usually: the workspace is unreachable). Make room by dropping the least severe, oldest.
145
- let drop = 0;
146
- for (let i = 1; i < this.queue.length; i++)
147
- if (RANK[this.queue[i].severity] < RANK[this.queue[drop].severity])
148
- drop = i;
149
- this.queue.splice(drop, 1);
150
- }
151
- this.queue.push(finding);
152
- }
153
- /** Sends queued findings in batches; a "retry" outcome keeps the batch for the next flush. */
154
- async flush(send) {
155
- if (this.suppressed && Math.floor(this.now() / FLOOD_WINDOW_MS) !== this.floodBucket)
156
- this.emitSuppressed();
157
- while (this.queue.length) {
158
- const batch = this.queue.splice(0, BATCH_SIZE);
159
- if ((await send(batch)) === "retry") {
160
- this.queue.unshift(...batch);
161
- break;
162
- }
163
- }
164
- const cutoff = this.now() - 2 * DEDUPE_WINDOW_MS.light;
165
- for (const [fp, entry] of this.seen)
166
- if (entry.at < cutoff)
167
- this.seen.delete(fp);
168
- }
169
- }
18
+ import { LLM_PROVIDERS, describeOwnLlm, detectedLlmKeys, judgeWithOwnLlm, ownLlmConfig } from "./monitor-llm.js";
19
+ import { describeMonitorConfig, ensureMonitorConfig, monitorConfigPath, writeMonitorConfig } from "./monitor-config.js";
20
+ export { BRUTE_FORCE_THRESHOLD, DEDUPE_WINDOW_MS, MAX_NEW_FINDINGS_PER_10_MIN, MonitorPipeline, meetsLevel } from "./monitor-pipeline.js";
21
+ import { MonitorPipeline } from "./monitor-pipeline.js";
170
22
  /** Follows a log file like `tail -F`: survives rotation (new inode) and truncation (copytruncate). */
171
23
  export class FileTailer {
172
24
  path;
@@ -271,36 +123,63 @@ export function vulnerabilityFinding(v) {
271
123
  evidence: `${v.name} ${v.version} (${v.ecosystem}) is in the affected range ${v.vulnerable}; ${v.patched ? `fixed in ${v.patched}` : "no fixed version yet"}. ${v.title} ${v.url}`.slice(0, 600),
272
124
  };
273
125
  }
126
+ const MAX_BACKOFF_MS = 5 * 60_000;
127
+ const backoff = (failures) => Math.min(MAX_BACKOFF_MS, 5_000 * 2 ** Math.min(failures, 10)) * (0.5 + Math.random() / 2);
128
+ /** A server-provided resume time, sanity-checked: never in the past, never more than a day away. */
129
+ function pauseUntil(resetAt, fallbackMs) {
130
+ const at = resetAt ? Date.parse(resetAt) : Number.NaN;
131
+ const now = Date.now();
132
+ return Number.isFinite(at) && at > now ? Math.min(at, now + 24 * 60 * 60_000) : now + fallbackMs;
133
+ }
134
+ /** Points at a key that's already here when no provider was chosen; it is never used without --llm. */
135
+ function llmKeyHint(own) {
136
+ if (own)
137
+ return "";
138
+ const [found] = detectedLlmKeys();
139
+ return found ? ` ${found.variable} is set here: add --llm ${found.provider} to review findings with your own key instead (Beam never sees it).` : "";
140
+ }
274
141
  const sleep = (ms) => new Promise(r => setTimeout(r, ms));
275
142
  export async function runMonitor(options, log = m => console.error(`[beam monitor] ${m}`)) {
276
- const files = (options.files ?? []).map(f => resolve(f));
277
- const appDir = options.app ? resolve(options.app) : undefined;
143
+ const { config: saved, created } = await ensureMonitorConfig();
144
+ if (created)
145
+ log(`Created ${monitorConfigPath()} for App monitoring settings. Edit it, or run 'beam monitor configure'.`);
146
+ // Sources on the command line replace the file's; with none, the file says what to watch.
147
+ const fromCli = Boolean(options.files?.length || options.stdin || options.app);
148
+ const files = (fromCli ? options.files ?? [] : saved.files).map(f => resolve(f));
149
+ const app = fromCli ? options.app : saved.app ?? undefined;
150
+ const appDir = app ? resolve(app) : undefined;
278
151
  if (!files.length && !options.stdin && !appDir)
279
- throw new Error("Tell beam monitor what to watch: --file <path> (repeatable) for log files, --stdin to read piped output, and/or --app <dir> for dependency checks.");
152
+ throw new Error(`Tell beam monitor what to watch: --file <path> (repeatable) for log files, --stdin to read piped output, and/or --app <dir> for dependency checks. Or save them with 'beam monitor configure --file <path>' (${monitorConfigPath()}).`);
280
153
  const identity = await monitorAuth();
281
154
  if (!identity)
282
155
  throw new Error("Set BEAM_APP_TOKEN to the app's token from the dashboard's App monitoring page, or connect this machine with 'beam connect'.");
283
156
  const custom = (await readPolicy())?.rules.customDetectors ?? [];
284
- const ownLlm = ownLlmConfig();
157
+ const ownLlm = ownLlmConfig(process.env, options.llm, saved.llm);
285
158
  let config = null;
286
159
  let lastRefresh = 0;
287
160
  let pausedUntil = 0;
288
161
  let offNotice = false;
162
+ // A rejected token or a missing API while running pauses capture and is checked again every 15
163
+ // minutes, rather than exiting: during an AgentBeam incident those can be transient.
164
+ let rejected = false;
289
165
  let fatal = null;
290
- const refresh = async () => {
166
+ const refresh = async (startup = false) => {
291
167
  lastRefresh = Date.now();
292
168
  const result = await fetchMonitorConfig(identity);
293
169
  if (result.ok) {
294
170
  if (!config) {
295
171
  log(`App monitoring is on${result.config.app ? ` for ${result.config.app}` : ""} (${result.config.level} level). Findings go to your workspace${result.config.webhooks ? ` and ${result.config.webhooks} webhook${result.config.webhooks === 1 ? "" : "s"}` : ""}.`);
296
172
  log(ownLlm
297
- ? `LLM checks: your own model, ${ownLlm.model} at ${new URL(ownLlm.baseUrl).host}.`
298
- : `LLM checks: ${result.config.llm ? "Beam's model (set in the dashboard)" : "off"}.`);
173
+ ? `LLM checks: ${describeOwnLlm(ownLlm)}. Only redacted excerpts go there, and the key never leaves this server.`
174
+ : `LLM checks: ${result.config.llm ? "Beam's model (set in the dashboard)" : "off"}.${llmKeyHint(ownLlm)}`);
299
175
  }
300
176
  else if (config.level !== result.config.level)
301
177
  log(`Level changed to ${result.config.level}.`);
178
+ if (rejected)
179
+ log("AgentBeam accepted this server again. Capture resumed.");
302
180
  config = result.config;
303
181
  offNotice = false;
182
+ rejected = false;
304
183
  return;
305
184
  }
306
185
  if (result.status === "disabled") {
@@ -310,20 +189,29 @@ export async function runMonitor(options, log = m => console.error(`[beam monito
310
189
  config = null;
311
190
  return;
312
191
  }
313
- if (result.status === "revoked" || result.status === "unsupported")
314
- throw new Error(result.message);
192
+ if (result.status === "revoked" || result.status === "unsupported") {
193
+ if (startup)
194
+ throw new Error(result.message);
195
+ if (!rejected)
196
+ log(`${result.message} Capture paused; checking again every 15 minutes.`);
197
+ rejected = true;
198
+ config = null;
199
+ return;
200
+ }
315
201
  log(`${result.message} Retrying.`); // unreachable: keep the last known settings
316
202
  };
317
- await refresh();
203
+ await refresh(true);
318
204
  while (!config) {
319
205
  if (options.wait === false)
320
206
  throw new Error("App monitoring is not on for this workspace.");
321
207
  await sleep(60_000);
322
- await refresh();
208
+ await refresh(true);
323
209
  }
210
+ const maxCpu = Math.min(100, Math.max(1, Number(options.maxCpu ?? saved.maxCpuPercent) || 25));
324
211
  const pipeline = new MonitorPipeline({
325
212
  level: () => (config && Date.now() >= pausedUntil ? config.level : null),
326
213
  customDetectors: () => custom,
214
+ cpuBudgetMsPerMinute: 600 * maxCpu, // 1% of a core = 600 ms per minute
327
215
  });
328
216
  const send = async (batch) => {
329
217
  if (ownLlm && config)
@@ -338,12 +226,15 @@ export async function runMonitor(options, log = m => console.error(`[beam monito
338
226
  return "drop";
339
227
  }
340
228
  if (result.status === "quota") {
341
- pausedUntil = result.resetAt ? Date.parse(result.resetAt) : Date.now() + 60 * 60_000;
229
+ pausedUntil = pauseUntil(result.resetAt, 60 * 60_000);
342
230
  log(`${result.message} Capture paused until then.`);
343
231
  return "drop";
344
232
  }
345
233
  if (result.status === "revoked" || result.status === "unsupported") {
346
- fatal = new Error(result.message);
234
+ if (!rejected)
235
+ log(`${result.message} Capture paused; checking again every 15 minutes.`);
236
+ rejected = true;
237
+ config = null;
347
238
  return "drop";
348
239
  }
349
240
  return "retry";
@@ -371,36 +262,92 @@ export async function runMonitor(options, log = m => console.error(`[beam monito
371
262
  tailer.start();
372
263
  if (files.length)
373
264
  log(`Watching ${files.join(", ")}.`);
265
+ // When AgentBeam is unreachable or erroring, sends back off (with jitter, up to 5 minutes) instead
266
+ // of retrying every few seconds; findings wait in a queue capped at 1,000.
374
267
  let flushing = false;
375
- const flush = async () => {
376
- if (flushing)
268
+ let sendFailures = 0;
269
+ let nextSendAt = 0;
270
+ const flush = async (force = false) => {
271
+ if (flushing || (!force && Date.now() < nextSendAt))
377
272
  return;
378
273
  flushing = true;
274
+ let retry = false;
379
275
  try {
380
- await pipeline.flush(send);
276
+ await pipeline.flush(async (batch) => {
277
+ const outcome = await send(batch);
278
+ retry = outcome === "retry";
279
+ return outcome;
280
+ });
381
281
  }
382
282
  finally {
383
283
  flushing = false;
284
+ if (retry)
285
+ nextSendAt = Date.now() + backoff(++sendFailures);
286
+ else
287
+ sendFailures = 0;
384
288
  }
385
289
  };
290
+ // Piped output: the app's lines go straight through (honoring backpressure, as without Beam),
291
+ // and detection works through a bounded backlog in short slices. If detection can't keep up,
292
+ // lines are skipped for detection, never held back from the app's output.
293
+ const MAX_BACKLOG = 10_000;
294
+ const backlog = [];
295
+ let backlogHead = 0;
296
+ let pipedSkipped = 0;
297
+ let draining = false;
298
+ const drain = () => {
299
+ const until = performance.now() + 20;
300
+ while (backlogHead < backlog.length && performance.now() < until)
301
+ pipeline.ingestLine(backlog[backlogHead++], "stdin");
302
+ if (backlogHead > 1000) {
303
+ backlog.splice(0, backlogHead);
304
+ backlogHead = 0;
305
+ }
306
+ if (backlogHead < backlog.length)
307
+ setImmediate(drain);
308
+ else
309
+ draining = false;
310
+ };
386
311
  const timers = [
387
312
  setInterval(() => void flush(), 5_000),
388
313
  setInterval(() => {
389
- if (Date.now() - lastRefresh >= (config ? 5 * 60_000 : 60_000))
314
+ const every = config ? 5 * 60_000 : rejected ? 15 * 60_000 : 60_000;
315
+ if (Date.now() - lastRefresh >= every)
390
316
  void refresh().catch(e => { fatal = e; });
391
317
  }, 15_000),
318
+ setInterval(() => {
319
+ const skipped = (pipeline.budget?.takeSkipped() ?? 0) + pipedSkipped;
320
+ pipedSkipped = 0;
321
+ if (skipped)
322
+ log(`Skipped ${skipped} lines in the last minute to stay under ${maxCpu}% of a CPU (--max-cpu).`);
323
+ }, 60_000),
392
324
  setInterval(() => void checkDependencies(), 24 * 60 * 60_000),
393
325
  ];
326
+ for (const timer of timers)
327
+ timer.unref?.();
394
328
  void checkDependencies();
395
329
  let stdinDone = !options.stdin;
396
330
  if (options.stdin) {
397
- if (options.echo !== false)
331
+ const echo = options.echo !== false;
332
+ if (echo)
398
333
  process.stdout.on("error", () => { });
399
334
  const lines = createInterface({ input: process.stdin, crlfDelay: Infinity });
335
+ let paused = false;
400
336
  lines.on("line", line => {
401
- if (options.echo !== false)
402
- process.stdout.write(`${line}\n`);
403
- pipeline.ingestLine(line, "stdin");
337
+ if (echo && !process.stdout.write(`${line}\n`) && !paused) {
338
+ paused = true;
339
+ lines.pause();
340
+ process.stdout.once("drain", () => { paused = false; lines.resume(); });
341
+ }
342
+ if (backlog.length - backlogHead >= MAX_BACKLOG) {
343
+ pipedSkipped++;
344
+ return;
345
+ }
346
+ backlog.push(line);
347
+ if (!draining) {
348
+ draining = true;
349
+ setImmediate(drain);
350
+ }
404
351
  });
405
352
  lines.on("close", () => { stdinDone = true; });
406
353
  }
@@ -418,15 +365,17 @@ export async function runMonitor(options, log = m => console.error(`[beam monito
418
365
  tailer.stop();
419
366
  process.removeListener("SIGINT", stop);
420
367
  process.removeListener("SIGTERM", stop);
421
- // Last flush, bounded so a dead network can't hold up shutdown.
368
+ // What's left of the piped backlog, then a last flush, bounded so a dead network can't hold up shutdown.
369
+ while (backlogHead < backlog.length)
370
+ pipeline.ingestLine(backlog[backlogHead++], "stdin");
422
371
  let giveUp;
423
- await Promise.race([flush(), new Promise(r => { giveUp = setTimeout(r, 5_000); })]);
372
+ await Promise.race([flush(true), new Promise(r => { giveUp = setTimeout(r, 5_000); })]);
424
373
  clearTimeout(giveUp);
425
374
  if (fatal)
426
375
  throw fatal;
427
376
  }
428
377
  const fmt = (n) => (n >= 2_147_483_647 ? "unlimited" : n.toLocaleString("en-US"));
429
- export async function monitorStatus(write = console.log) {
378
+ export async function monitorStatus(write = console.log, llm) {
430
379
  let identity;
431
380
  try {
432
381
  identity = await monitorAuth();
@@ -444,11 +393,11 @@ export async function monitorStatus(write = console.log) {
444
393
  write(result.status === "disabled" ? `App monitoring: off\n${result.message}` : result.message);
445
394
  return result.status === "disabled" ? 0 : 1;
446
395
  }
447
- const { app, level, llm, webhooks, usage, limits, resetAt, settingsUrl } = result.config;
396
+ const { app, level, llm: beamLlm, webhooks, usage, limits, resetAt, settingsUrl } = result.config;
448
397
  let own = null;
449
398
  let ownError = "";
450
399
  try {
451
- own = ownLlmConfig();
400
+ own = ownLlmConfig(process.env, llm, (await ensureMonitorConfig()).config.llm);
452
401
  }
453
402
  catch (error) {
454
403
  ownError = error.message;
@@ -457,15 +406,19 @@ export async function monitorStatus(write = console.log) {
457
406
  "App monitoring: on",
458
407
  ...(app ? [`App: ${app}`] : []),
459
408
  `Level: ${level}`,
460
- `LLM checks: ${own ? `your own model, ${own.model} at ${new URL(own.baseUrl).host}` : ownError ? `misconfigured: ${ownError}` : llm ? "Beam's model" : "off"}`,
409
+ `LLM checks: ${own ? describeOwnLlm(own) : ownError ? `misconfigured: ${ownError}` : `${beamLlm ? "Beam's model" : "off"}${llmKeyHint(own)}`}`,
461
410
  `Webhooks: ${webhooks}`,
462
411
  `This month: ${fmt(usage.findings)} / ${fmt(limits.findings)} findings · ${fmt(usage.cveChecks)} / ${fmt(limits.cveChecks)} dependency checks · ${fmt(usage.llmChecks)} / ${fmt(limits.llmChecks)} LLM checks (resets ${resetAt.slice(0, 10)})`,
463
412
  `Settings: ${settingsUrl}`,
413
+ `This server: ${monitorConfigPath()}`,
464
414
  ].join("\n"));
465
415
  return 0;
466
416
  }
467
- /** `beam monitor test`: one test finding through the real path, to prove an integration end to end. */
468
- export async function monitorTest(write = console.log) {
417
+ /**
418
+ * `beam monitor test`: one test finding through the real path, to prove an integration end to end.
419
+ * With an own LLM (--llm), also one LLM check on a harmless sample, to prove the key works.
420
+ */
421
+ export async function monitorTest(write = console.log, llm) {
469
422
  let identity;
470
423
  try {
471
424
  identity = await monitorAuth();
@@ -496,6 +449,72 @@ export async function monitorTest(write = console.log) {
496
449
  return 1;
497
450
  }
498
451
  write(`✔ Test finding sent for ${where}. Check the dashboard's App monitoring page${config.config.webhooks ? ` and your ${config.config.webhooks} webhook${config.config.webhooks === 1 ? "" : "s"}` : ""}.`);
452
+ let own;
453
+ try {
454
+ own = ownLlmConfig(process.env, llm, (await ensureMonitorConfig()).config.llm);
455
+ }
456
+ catch (error) {
457
+ write(`✖ LLM check: ${error.message}`);
458
+ return 1;
459
+ }
460
+ if (!own)
461
+ return 0;
462
+ // A harmless sample, judged separately: its verdict isn't attached to the test finding, which must reach the webhooks.
463
+ const sample = {
464
+ id: "llm-test", ruleId: "web.sql_injection", title: "SQL injection attempt from 203.0.113.9", severity: "high", category: "exploit",
465
+ source: "http", count: 1, firstSeen: now, evidence: '203.0.113.9 - - "GET /items?id=1 UNION SELECT password FROM users-- HTTP/1.1" 200 "sqlmap/1.8"',
466
+ };
467
+ await judgeWithOwnLlm([sample], "strict", own);
468
+ const verdict = sample.llm;
469
+ if (!verdict || verdict.verdict === "error") {
470
+ write(`✖ LLM check with ${describeOwnLlm(own)} failed: ${verdict?.reason ?? "no answer"}`);
471
+ return 1;
472
+ }
473
+ write(`✔ LLM check works: ${describeOwnLlm(own)} judged a sample attack "${verdict.verdict}".`);
474
+ return 0;
475
+ }
476
+ /**
477
+ * `beam monitor configure`: saves settings to monitor.json so `beam monitor` needs no flags. With
478
+ * no options, prints the current settings. A key is only ever stored from stdin (`key`), and a
479
+ * provider's key that isn't set in this shell is a warning, not an error: it may be set only where
480
+ * beam monitor runs (a systemd EnvironmentFile, a container's secrets).
481
+ */
482
+ export async function monitorConfigure(options, write = console.log) {
483
+ const { config: current } = await ensureMonitorConfig();
484
+ const changing = Object.values(options).some(v => v !== undefined && v !== false);
485
+ if (!changing) {
486
+ write(`${monitorConfigPath()}\n${JSON.stringify(describeMonitorConfig(current), null, 2)}`);
487
+ return 0;
488
+ }
489
+ const provider = options.llm?.trim().toLowerCase();
490
+ if (provider && provider !== "beam" && !(provider in LLM_PROVIDERS))
491
+ throw new Error(`Unknown LLM provider "${provider}". Use one of ${Object.keys(LLM_PROVIDERS).join(", ")}, or beam for Beam's model.`);
492
+ const switching = provider !== undefined && provider !== current.llm.provider;
493
+ const next = {
494
+ ...current,
495
+ files: options.noFiles ? [] : options.files?.length ? options.files.map(f => resolve(f)) : current.files,
496
+ app: options.noApp ? null : options.app ? resolve(options.app) : current.app,
497
+ maxCpuPercent: options.maxCpu ?? current.maxCpuPercent,
498
+ llm: {
499
+ provider: provider ?? current.llm.provider,
500
+ // A new provider starts from its own defaults rather than the old provider's model and endpoint.
501
+ model: options.model ?? (switching ? null : current.llm.model),
502
+ baseUrl: options.baseUrl ?? (switching ? null : current.llm.baseUrl),
503
+ apiKeyEnv: options.keyEnv ?? (switching ? null : current.llm.apiKeyEnv),
504
+ ...(options.key ? { apiKey: options.key } : !options.forgetKey && !switching && current.llm.apiKey ? { apiKey: current.llm.apiKey } : {}),
505
+ },
506
+ };
507
+ await writeMonitorConfig(next);
508
+ write(`Saved ${monitorConfigPath()} (0600).`);
509
+ try {
510
+ const own = ownLlmConfig(process.env, undefined, next.llm);
511
+ write(own ? `LLM checks: ${describeOwnLlm(own)}. The key stays on this server and is never sent to Beam.` : "LLM checks: Beam's model, when an admin turns it on in the dashboard.");
512
+ }
513
+ catch (error) {
514
+ write(`⚠ ${error.message} (Saved anyway: that may be set only where beam monitor runs.)`);
515
+ }
516
+ if (next.files.length || next.app)
517
+ write(`Watches: ${[...next.files, ...(next.app ? [`dependencies in ${next.app}`] : [])].join(", ")}. Start with 'beam monitor'.`);
499
518
  return 0;
500
519
  }
501
520
  //# sourceMappingURL=monitor.js.map