@agent-beam/beam 0.1.0 → 0.2.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.
Files changed (48) hide show
  1. package/dist/account.d.ts +21 -0
  2. package/dist/account.js +59 -0
  3. package/dist/account.js.map +1 -0
  4. package/dist/agents.d.ts +6 -0
  5. package/dist/agents.js +44 -6
  6. package/dist/agents.js.map +1 -1
  7. package/dist/banner.d.ts +1 -0
  8. package/dist/banner.js +10 -0
  9. package/dist/banner.js.map +1 -0
  10. package/dist/cli.js +137 -4
  11. package/dist/cli.js.map +1 -1
  12. package/dist/client.js +9 -3
  13. package/dist/client.js.map +1 -1
  14. package/dist/config.d.ts +1 -0
  15. package/dist/config.js +5 -1
  16. package/dist/config.js.map +1 -1
  17. package/dist/connect.d.ts +11 -0
  18. package/dist/connect.js +92 -0
  19. package/dist/connect.js.map +1 -0
  20. package/dist/elevate.d.ts +3 -0
  21. package/dist/elevate.js +40 -0
  22. package/dist/elevate.js.map +1 -0
  23. package/dist/enroll.d.ts +2 -0
  24. package/dist/enroll.js +15 -4
  25. package/dist/enroll.js.map +1 -1
  26. package/dist/enterprise-install.d.ts +10 -0
  27. package/dist/enterprise-install.js +55 -0
  28. package/dist/enterprise-install.js.map +1 -0
  29. package/dist/forward.d.ts +13 -1
  30. package/dist/forward.js +87 -0
  31. package/dist/forward.js.map +1 -1
  32. package/dist/install.d.ts +9 -0
  33. package/dist/install.js +54 -0
  34. package/dist/install.js.map +1 -1
  35. package/dist/open-browser.js +6 -1
  36. package/dist/open-browser.js.map +1 -1
  37. package/dist/prompts.d.ts +11 -0
  38. package/dist/prompts.js +113 -0
  39. package/dist/prompts.js.map +1 -0
  40. package/dist/serve.js +7 -2
  41. package/dist/serve.js.map +1 -1
  42. package/dist/server.d.ts +2 -0
  43. package/dist/server.js +16 -3
  44. package/dist/server.js.map +1 -1
  45. package/dist/setup.d.ts +2 -0
  46. package/dist/setup.js +128 -0
  47. package/dist/setup.js.map +1 -0
  48. package/package.json +2 -5
@@ -0,0 +1,92 @@
1
+ import { generateKeyPairSync, randomBytes } from "node:crypto";
2
+ import { hostname } from "node:os";
3
+ import { getDashboardUrl } from "./config.js";
4
+ import { writeIdentity } from "./enroll.js";
5
+ function sleep(ms) {
6
+ return new Promise((resolve) => setTimeout(resolve, ms));
7
+ }
8
+ async function readError(response, fallback) {
9
+ try {
10
+ const body = (await response.json());
11
+ return body.error ?? fallback;
12
+ }
13
+ catch {
14
+ return fallback;
15
+ }
16
+ }
17
+ // Starts a browser-based pairing request: registers this device's public key and a one-time
18
+ // connect token with the dashboard, then hands back a URL to open and a poll() to wait on.
19
+ // Unlike 'beam enroll', there's no code to type -- the dashboard authorizes the token once the
20
+ // signed-in user's browser session confirms it, and poll() picks that up on the CLI side.
21
+ export async function startConnect() {
22
+ const base = getDashboardUrl();
23
+ const token = randomBytes(32).toString("hex");
24
+ const { publicKey, privateKey } = generateKeyPairSync("ed25519");
25
+ const pub = publicKey.export({ type: "spki", format: "der" }).toString("base64");
26
+ const priv = privateKey.export({ type: "pkcs8", format: "der" }).toString("base64");
27
+ const os = process.platform;
28
+ const host = hostname();
29
+ let response;
30
+ try {
31
+ response = await fetch(`${base}/api/connect/start`, {
32
+ method: "POST",
33
+ headers: { "Content-Type": "application/json" },
34
+ body: JSON.stringify({ token, device: { hostname: host, os, public_key: pub } }),
35
+ signal: AbortSignal.timeout(10_000),
36
+ });
37
+ }
38
+ catch {
39
+ throw new Error(`Could not reach ${base}. Is the dashboard running?`);
40
+ }
41
+ if (!response.ok)
42
+ throw new Error(await readError(response, `Could not start a connection request (${response.status}).`));
43
+ const url = `${base}/connect?token=${encodeURIComponent(token)}`;
44
+ async function poll(options = {}) {
45
+ const timeoutMs = options.timeoutMs ?? 5 * 60_000;
46
+ const intervalMs = options.intervalMs ?? 2000;
47
+ const deadline = Date.now() + timeoutMs;
48
+ while (Date.now() < deadline) {
49
+ let pollResponse;
50
+ try {
51
+ pollResponse = await fetch(`${base}/api/connect/poll`, {
52
+ method: "POST",
53
+ headers: { "Content-Type": "application/json" },
54
+ body: JSON.stringify({ token }),
55
+ signal: AbortSignal.timeout(10_000),
56
+ });
57
+ }
58
+ catch {
59
+ await sleep(intervalMs);
60
+ continue;
61
+ }
62
+ if (pollResponse.status === 202) {
63
+ await sleep(intervalMs);
64
+ continue;
65
+ }
66
+ if (pollResponse.status === 404)
67
+ throw new Error("Connection request expired. Run 'beam connect' again.");
68
+ if (!pollResponse.ok)
69
+ throw new Error(await readError(pollResponse, `Connection request failed (${pollResponse.status}).`));
70
+ const data = (await pollResponse.json());
71
+ if (!data.device_id || !data.device_secret || !data.org_id) {
72
+ throw new Error("Connect response is missing device credentials.");
73
+ }
74
+ const identity = {
75
+ deviceId: data.device_id,
76
+ deviceSecret: data.device_secret,
77
+ orgId: data.org_id,
78
+ apiBase: (data.api_base ?? base).replace(/\/+$/, ""),
79
+ publicKey: pub,
80
+ privateKey: priv,
81
+ hostname: host,
82
+ os,
83
+ enrolledAt: new Date().toISOString(),
84
+ };
85
+ await writeIdentity(identity);
86
+ return identity;
87
+ }
88
+ throw new Error("Timed out waiting for confirmation in the browser. Run 'beam connect' again.");
89
+ }
90
+ return { url, poll };
91
+ }
92
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function runWithSudoFallback(cmd: string, args: string[], options?: {
2
+ timeout?: number;
3
+ }): Promise<void>;
@@ -0,0 +1,40 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const run = promisify(execFile);
4
+ function isPermissionError(err) {
5
+ const e = err;
6
+ if (e?.code === "EACCES" || e?.code === "EPERM")
7
+ return true;
8
+ const text = `${e?.stderr ?? ""} ${e?.message ?? ""}`.toLowerCase();
9
+ return text.includes("eacces") || text.includes("permission denied");
10
+ }
11
+ function sudoSpawn(cmd, args) {
12
+ return new Promise((resolve, reject) => {
13
+ console.error(`\nThis step needs administrator privileges. Running: sudo ${cmd} ${args.join(" ")}`);
14
+ // stdio: "inherit" so sudo's own password prompt reaches the user's terminal directly.
15
+ const child = spawn("sudo", [cmd, ...args], { stdio: "inherit" });
16
+ child.on("error", reject);
17
+ child.on("exit", (code) => {
18
+ if (code === 0)
19
+ resolve();
20
+ else
21
+ reject(new Error(`sudo ${cmd} exited with code ${code}`));
22
+ });
23
+ });
24
+ }
25
+ // Runs a command normally; if it fails with a permission error, retries once under sudo with
26
+ // inherited stdio so the user can type their password at the terminal. Never elevates anything
27
+ // that writes to the invoking user's own home directory (e.g. service install) -- only use this
28
+ // for genuinely system-level operations, since running those under sudo would write as root
29
+ // instead of the real user.
30
+ export async function runWithSudoFallback(cmd, args, options = {}) {
31
+ try {
32
+ await run(cmd, args, options);
33
+ }
34
+ catch (err) {
35
+ if (!isPermissionError(err))
36
+ throw err;
37
+ await sudoSpawn(cmd, args);
38
+ }
39
+ }
40
+ //# sourceMappingURL=elevate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevate.js","sourceRoot":"","sources":["../src/elevate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhC,SAAS,iBAAiB,CAAC,GAAY;IACrC,MAAM,CAAC,GAAG,GAA2D,CAAC;IACtE,IAAI,CAAC,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,EAAE,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC;IACpE,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,IAAc;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,OAAO,CAAC,KAAK,CAAC,6DAA6D,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpG,uFAAuF;QACvF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAClE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;;gBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6FAA6F;AAC7F,+FAA+F;AAC/F,gGAAgG;AAChG,4FAA4F;AAC5F,4BAA4B;AAC5B,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAW,EAAE,IAAc,EAAE,UAAgC,EAAE;IACvG,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC;YAAE,MAAM,GAAG,CAAC;QACvC,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC"}
package/dist/enroll.d.ts CHANGED
@@ -10,6 +10,8 @@ export interface Identity {
10
10
  enrolledAt: string;
11
11
  }
12
12
  export declare function readIdentity(): Promise<Identity | null>;
13
+ export declare function writeIdentity(identity: Identity): Promise<void>;
14
+ export declare function clearIdentity(): Promise<void>;
13
15
  export declare function enrollDevice(options: {
14
16
  code: string;
15
17
  url?: string;
package/dist/enroll.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { generateKeyPairSync } from "node:crypto";
2
2
  import { hostname } from "node:os";
3
- import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { dirname } from "node:path";
5
5
  import { getApiUrl, getIdentityPath } from "./config.js";
6
6
  const CODE_RE = /^BEAM-[A-Z2-9]{4}-[A-Z2-9]{4}-[A-Z2-9]{4}$/;
@@ -12,6 +12,19 @@ export async function readIdentity() {
12
12
  return null;
13
13
  }
14
14
  }
15
+ // Shared by every enrollment path (code-based 'beam enroll' and browser-based 'beam connect')
16
+ // so the on-disk identity file always has the same shape regardless of how it was obtained.
17
+ export async function writeIdentity(identity) {
18
+ const path = getIdentityPath();
19
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
20
+ await writeFile(path, `${JSON.stringify(identity, null, 2)}\n`, { mode: 0o600 });
21
+ }
22
+ // Local half of `beam logout` -- removing the identity file is what actually makes this device
23
+ // "not enrolled" to every other command (readIdentity() returning null). Safe to call even when
24
+ // nothing is enrolled.
25
+ export async function clearIdentity() {
26
+ await rm(getIdentityPath(), { force: true });
27
+ }
15
28
  // Never blocks anything; enrollment just writes credentials this machine uses later.
16
29
  export async function enrollDevice(options) {
17
30
  const code = options.code.trim().toUpperCase();
@@ -60,9 +73,7 @@ export async function enrollDevice(options) {
60
73
  os,
61
74
  enrolledAt: new Date().toISOString(),
62
75
  };
63
- const path = getIdentityPath();
64
- await mkdir(dirname(path), { recursive: true, mode: 0o700 });
65
- await writeFile(path, `${JSON.stringify(identity, null, 2)}\n`, { mode: 0o600 });
76
+ await writeIdentity(identity);
66
77
  return identity;
67
78
  }
68
79
  //# sourceMappingURL=enroll.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"enroll.js","sourceRoot":"","sources":["../src/enroll.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"enroll.js","sourceRoot":"","sources":["../src/enroll.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Identity } from "./enroll.js";
2
+ export type EnterpriseInstallResult = {
3
+ status: "installed";
4
+ } | {
5
+ status: "not-entitled";
6
+ } | {
7
+ status: "error";
8
+ message: string;
9
+ };
10
+ export declare function installEnterprisePackage(identity: Identity): Promise<EnterpriseInstallResult>;
@@ -0,0 +1,55 @@
1
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { runWithSudoFallback } from "./elevate.js";
5
+ // Called right after 'beam connect' succeeds. Fetches a short-lived presigned S3 URL for the
6
+ // private beam-enterprise package (see apps/dashboard's /v1/enterprise/package), downloads the
7
+ // tarball ourselves, and installs it from a local temp path -- never from the URL directly, so
8
+ // the presigned URL (a bearer credential in itself) never appears in argv/ps output or any log.
9
+ export async function installEnterprisePackage(identity) {
10
+ let response;
11
+ try {
12
+ response = await fetch(`${identity.apiBase}/v1/enterprise/package`, {
13
+ headers: { Authorization: `Bearer ${identity.deviceSecret}` },
14
+ signal: AbortSignal.timeout(10_000),
15
+ });
16
+ }
17
+ catch {
18
+ return { status: "error", message: `Could not reach ${identity.apiBase}.` };
19
+ }
20
+ if (response.status === 403)
21
+ return { status: "not-entitled" };
22
+ if (!response.ok)
23
+ return { status: "error", message: `Could not fetch beam-enterprise (${response.status}).` };
24
+ const { url } = (await response.json());
25
+ if (!url)
26
+ return { status: "error", message: "Enterprise package response was missing a download URL." };
27
+ const tmpDir = await mkdtemp(join(tmpdir(), "beam-enterprise-"));
28
+ const tarballPath = join(tmpDir, "package.tgz");
29
+ try {
30
+ let download;
31
+ try {
32
+ download = await fetch(url, { signal: AbortSignal.timeout(30_000) });
33
+ }
34
+ catch {
35
+ return { status: "error", message: "Could not download beam-enterprise (network error)." };
36
+ }
37
+ if (!download.ok)
38
+ return { status: "error", message: `Could not download beam-enterprise (${download.status}).` };
39
+ await writeFile(tarballPath, Buffer.from(await download.arrayBuffer()));
40
+ // -g so it lands in the same global node_modules as a globally-installed `beam`, where
41
+ // os-monitor.ts's bare `import("beam-enterprise")` can resolve it. --no-save: this is a
42
+ // local tarball path, not something meaningful to persist in any package.json. Falls back
43
+ // to sudo if the global node_modules isn't user-writable (e.g. a system Node install).
44
+ await runWithSudoFallback("npm", ["install", "-g", "--no-save", tarballPath], { timeout: 120_000 });
45
+ return { status: "installed" };
46
+ }
47
+ catch (err) {
48
+ const message = err instanceof Error ? err.message : String(err);
49
+ return { status: "error", message: `beam-enterprise install failed: ${message}` };
50
+ }
51
+ finally {
52
+ await rm(tmpDir, { recursive: true, force: true });
53
+ }
54
+ }
55
+ //# sourceMappingURL=enterprise-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterprise-install.js","sourceRoot":"","sources":["../src/enterprise-install.ts"],"names":[],"mappings":"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"}
package/dist/forward.d.ts CHANGED
@@ -1,5 +1,17 @@
1
- import type { Event } from "./core.js";
1
+ import type { Event, Scan } from "./core.js";
2
2
  export declare function forwardEvents(events: Event | Event[]): Promise<void>;
3
+ export declare const FORWARD_BATCH_SIZE = 15;
4
+ export declare const FORWARD_FLUSH_MS = 10000;
5
+ export declare class ForwardQueue {
6
+ private pending;
7
+ private flushTimer;
8
+ push(events: Event[]): void;
9
+ private scheduleFlush;
10
+ /** Force out whatever is pending right now (e.g. on collector shutdown). */
11
+ flush(): void;
12
+ }
13
+ export declare function forwardScan(scan: Scan): Promise<void>;
14
+ export declare function forwardReview(id: string, reviewed: boolean): Promise<void>;
3
15
  export interface PolicySyncResult {
4
16
  status: "updated" | "unchanged" | "not-enrolled" | "unreachable";
5
17
  version?: number;
package/dist/forward.js CHANGED
@@ -25,6 +25,93 @@ export async function forwardEvents(events) {
25
25
  /* offline / unreachable — the local collector still has the record */
26
26
  }
27
27
  }
28
+ export const FORWARD_BATCH_SIZE = 15;
29
+ export const FORWARD_FLUSH_MS = 10_000;
30
+ // Batches events in memory (per collector process) and forwards them to the workspace in
31
+ // groups of FORWARD_BATCH_SIZE, instead of one HTTP request per captured action. Lives on the
32
+ // long-running collector (see serve.ts) since that's the only process with state that persists
33
+ // across the many short-lived `beam hook` invocations. A leftover partial batch (below
34
+ // FORWARD_BATCH_SIZE) is flushed after FORWARD_FLUSH_MS of inactivity so a quiet machine still
35
+ // reaches the dashboard instead of waiting indefinitely for a 15th event.
36
+ export class ForwardQueue {
37
+ pending = [];
38
+ flushTimer;
39
+ push(events) {
40
+ if (!events.length)
41
+ return;
42
+ this.pending.push(...events);
43
+ while (this.pending.length >= FORWARD_BATCH_SIZE) {
44
+ const batch = this.pending.splice(0, FORWARD_BATCH_SIZE);
45
+ void forwardEvents(batch);
46
+ }
47
+ this.scheduleFlush();
48
+ }
49
+ scheduleFlush() {
50
+ if (this.flushTimer)
51
+ clearTimeout(this.flushTimer);
52
+ if (!this.pending.length)
53
+ return;
54
+ this.flushTimer = setTimeout(() => {
55
+ this.flushTimer = undefined;
56
+ if (!this.pending.length)
57
+ return;
58
+ const batch = this.pending.splice(0, this.pending.length);
59
+ void forwardEvents(batch);
60
+ }, FORWARD_FLUSH_MS);
61
+ this.flushTimer.unref?.();
62
+ }
63
+ /** Force out whatever is pending right now (e.g. on collector shutdown). */
64
+ flush() {
65
+ if (this.flushTimer) {
66
+ clearTimeout(this.flushTimer);
67
+ this.flushTimer = undefined;
68
+ }
69
+ if (!this.pending.length)
70
+ return;
71
+ const batch = this.pending.splice(0, this.pending.length);
72
+ void forwardEvents(batch);
73
+ }
74
+ }
75
+ // Fire-and-forget: forwarding a local skill/MCP scan must never block or fail the caller.
76
+ export async function forwardScan(scan) {
77
+ const identity = await readIdentity();
78
+ if (!identity)
79
+ return;
80
+ try {
81
+ await fetch(`${identity.apiBase}/v1/scans`, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ Authorization: `Bearer ${identity.deviceSecret}`,
86
+ },
87
+ body: JSON.stringify(scan),
88
+ signal: AbortSignal.timeout(5000),
89
+ });
90
+ }
91
+ catch {
92
+ /* offline / unreachable — the local collector still has the record */
93
+ }
94
+ }
95
+ // Fire-and-forget: forwarding a review toggle must never block or fail the caller.
96
+ export async function forwardReview(id, reviewed) {
97
+ const identity = await readIdentity();
98
+ if (!identity)
99
+ return;
100
+ try {
101
+ await fetch(`${identity.apiBase}/v1/ingest`, {
102
+ method: "PATCH",
103
+ headers: {
104
+ "Content-Type": "application/json",
105
+ Authorization: `Bearer ${identity.deviceSecret}`,
106
+ },
107
+ body: JSON.stringify({ id, reviewed }),
108
+ signal: AbortSignal.timeout(5000),
109
+ });
110
+ }
111
+ catch {
112
+ /* offline / unreachable — the local collector still has the record */
113
+ }
114
+ }
28
115
  // Pull the current policy bundle and cache it locally for the hook to enforce.
29
116
  export async function syncPolicy() {
30
117
  const identity = await readIdentity();
@@ -1 +1 @@
1
- {"version":3,"file":"forward.js","sourceRoot":"","sources":["../src/forward.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,gBAAgB,EAAE,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAuB;IACzD,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,QAAQ,CAAC,OAAO,YAAY,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,QAAQ,CAAC,YAAY,EAAE;aACjD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YAC5B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;AACH,CAAC;AAQD,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAEjD,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,CAAC,OAAO,YAAY,EAAE;YACtD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,CAAC,YAAY,EAAE,EAAE;YAC7D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACnC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC5D,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"forward.js","sourceRoot":"","sources":["../src/forward.ts"],"names":[],"mappings":"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"}
package/dist/install.d.ts CHANGED
@@ -1,9 +1,18 @@
1
+ import { type AgentDefinition } from "./agents.js";
1
2
  export interface InstallResult {
2
3
  agent: string;
3
4
  path: string;
4
5
  alreadyInstalled: boolean;
5
6
  }
6
7
  export declare function installHook(agentId: string, home?: string): Promise<InstallResult>;
8
+ export interface UninstallResult {
9
+ agent: string;
10
+ path: string;
11
+ removed: boolean;
12
+ }
13
+ export declare function uninstallHook(agentId: string, home?: string): Promise<UninstallResult>;
14
+ export declare function uninstallAllHooks(home?: string): Promise<UninstallResult[]>;
15
+ export declare function detectAgents(home?: string): Promise<AgentDefinition[]>;
7
16
  export type InstallAllStatus = "installed" | "already-installed" | "not-detected" | "not-supported" | "error";
8
17
  export interface InstallAllResult {
9
18
  agent: string;
package/dist/install.js CHANGED
@@ -31,6 +31,50 @@ export async function installHook(agentId, home = homedir()) {
31
31
  }
32
32
  return { agent: agent.id, path, alreadyInstalled };
33
33
  }
34
+ // Reverse of installHook: strips beam's hook entry back out of the agent's config file, leaving
35
+ // any other hooks untouched. A missing config file or one that never had beam installed is a
36
+ // no-op (removed: false), not an error -- 'beam uninstall' should never fail on an agent that
37
+ // was never wired up.
38
+ export async function uninstallHook(agentId, home = homedir()) {
39
+ const agent = findAgent(agentId);
40
+ if (!agent)
41
+ throw new Error(`Unknown agent '${agentId}'. Run 'beam agent list' to see supported agents.`);
42
+ if (!agent.hookConfigPath || !agent.unmergeHookConfig)
43
+ throw new Error(`${agent.name} has no supported hook install path yet; see 'beam agent list' for its status.`);
44
+ const path = hookConfigFullPath(agent, home);
45
+ const command = `beam hook ${agent.id}`;
46
+ let existing = {};
47
+ let raw = "";
48
+ try {
49
+ raw = await readFile(path, "utf8");
50
+ existing = raw.trim() ? JSON.parse(raw) : {};
51
+ }
52
+ catch (e) {
53
+ if (e.code === "ENOENT")
54
+ return { agent: agent.id, path, removed: false };
55
+ if (e instanceof SyntaxError)
56
+ throw new Error(`${path} contains invalid JSON; fix or remove it manually.`);
57
+ throw e;
58
+ }
59
+ const updated = agent.unmergeHookConfig(existing, command);
60
+ const removed = JSON.stringify(updated) !== JSON.stringify(existing);
61
+ if (removed)
62
+ await writeFile(path, `${JSON.stringify(updated, null, 2)}\n`);
63
+ return { agent: agent.id, path, removed };
64
+ }
65
+ // Attempts removal from every agent beam knows how to uninstall from, regardless of whether its
66
+ // presence-signal files still exist -- unlike installAllDetectedHooks, this errs on the side of
67
+ // trying rather than skipping, since a stale hook entry left behind after 'beam uninstall' is
68
+ // worse than one harmless extra file read.
69
+ export async function uninstallAllHooks(home = homedir()) {
70
+ const results = [];
71
+ for (const agent of AGENTS) {
72
+ if (!agent.hookConfigPath || !agent.unmergeHookConfig)
73
+ continue;
74
+ results.push(await uninstallHook(agent.id, home));
75
+ }
76
+ return results;
77
+ }
34
78
  async function isDetected(agent, home) {
35
79
  for (const relativePath of agent.configs) {
36
80
  try {
@@ -41,6 +85,16 @@ async function isDetected(agent, home) {
41
85
  }
42
86
  return false;
43
87
  }
88
+ // Detection only, no writes — lets a caller (e.g. `beam setup`) show what's on the machine
89
+ // and let the user choose before `installHook` touches anything.
90
+ export async function detectAgents(home = homedir()) {
91
+ const found = [];
92
+ for (const agent of AGENTS) {
93
+ if (await isDetected(agent, home))
94
+ found.push(agent);
95
+ }
96
+ return found;
97
+ }
44
98
  // Detects which agents are actually present on this machine (via agents.ts's real, non-circular
45
99
  // config-presence signals — never the hook file beam itself would write) and installs beam's
46
100
  // hook into every one that's both detected and supported, skipping the rest without erroring.
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,EAAkC,MAAM,aAAa,CAAC;AAIpG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,IAAI,GAAG,OAAO,EAAE;IACjE,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,OAAO,mDAAmD,CAAC,CAAC;IAC1G,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,gFAAgF,CAAC,CAAC;IAEpK,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,aAAa,KAAK,CAAC,EAAE,EAAE,CAAC;IAExC,IAAI,QAAQ,GAAQ,EAAE,CAAC;IACvB,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC;QAAC,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,CAAC;IAChG,OAAO,CAAC,EAAE,CAAC;QACT,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnD,IAAI,CAAC,YAAY,WAAW;gBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,6DAA6D,CAAC,CAAC;YACpH,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAElG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;AACrD,CAAC;AAID,gGAAgG;AAChG,6FAA6F;AAC7F,8FAA8F;AAC9F,sBAAsB;AACtB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,IAAI,GAAG,OAAO,EAAE;IACnE,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,OAAO,mDAAmD,CAAC,CAAC;IAC1G,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,iBAAiB;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,gFAAgF,CAAC,CAAC;IAEtK,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,aAAa,KAAK,CAAC,EAAE,EAAE,CAAC;IAExC,IAAI,QAAQ,GAAQ,EAAE,CAAC;IACvB,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC;QAAC,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,CAAC;IAChG,OAAO,CAAC,EAAE,CAAC;QACT,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACrG,IAAI,CAAC,YAAY,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oDAAoD,CAAC,CAAC;QAC3G,MAAM,CAAC,CAAC;IACV,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACrE,IAAI,OAAO;QAAE,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAE5E,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC;AAED,gGAAgG;AAChG,gGAAgG;AAChG,8FAA8F;AAC9F,2CAA2C;AAC3C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAI,GAAG,OAAO,EAAE;IACtD,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,iBAAiB;YAAE,SAAS;QAChE,OAAO,CAAC,IAAI,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,KAAsB,EAAE,IAAY;IAC5D,KAAK,MAAM,YAAY,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,yBAAyB,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2FAA2F;AAC3F,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAI,GAAG,OAAO,EAAE;IACjD,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAKD,gGAAgG;AAChG,6FAA6F;AAC7F,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,IAAI,GAAG,OAAO,EAAE;IAC5D,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAChI,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAChJ,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9I,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1H,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -3,6 +3,11 @@ export function openBrowser(url) {
3
3
  const platform = process.platform;
4
4
  const command = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
5
5
  const args = platform === "win32" ? ["", url] : [url];
6
- spawn(command, args, { detached: true, stdio: "ignore", shell: platform === "win32" }).unref();
6
+ const child = spawn(command, args, { detached: true, stdio: "ignore", shell: platform === "win32" });
7
+ // No display, no 'open'/'xdg-open' on PATH, sandboxed exec, etc. -- the URL is already printed
8
+ // and usable manually, so a failed auto-open should never crash the command. Without this
9
+ // listener an unhandled 'error' event here throws and kills the whole process.
10
+ child.on("error", () => { });
11
+ child.unref();
7
12
  }
8
13
  //# sourceMappingURL=open-browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../src/open-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,OAAO,GAAG,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7F,MAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;AACjG,CAAC"}
1
+ {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../src/open-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,OAAO,GAAG,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7F,MAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;IACrG,+FAA+F;IAC/F,0FAA0F;IAC1F,+EAA+E;IAC/E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface CheckboxItem {
2
+ label: string;
3
+ checked?: boolean;
4
+ }
5
+ export declare function checkbox(title: string, items: CheckboxItem[]): Promise<number[]>;
6
+ export declare function withSpinner<T>(label: string, fn: () => Promise<T>): Promise<T>;
7
+ export interface TableRow {
8
+ label: string;
9
+ value: string;
10
+ }
11
+ export declare function renderTable(rows: TableRow[]): string;