@agent-beam/beam 0.2.38 → 0.2.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -13
- package/dist/access-risk.d.ts +10 -0
- package/dist/access-risk.js +43 -0
- package/dist/access-risk.js.map +1 -0
- package/dist/action-context.d.ts +30 -0
- package/dist/action-context.js +203 -0
- package/dist/action-context.js.map +1 -0
- package/dist/activity.d.ts +22 -0
- package/dist/activity.js +132 -0
- package/dist/activity.js.map +1 -0
- package/dist/agent-hook-install.d.ts +8 -0
- package/dist/agent-hook-install.js +278 -0
- package/dist/agent-hook-install.js.map +1 -0
- package/dist/agent-installers.js +16 -3
- package/dist/agent-installers.js.map +1 -1
- package/dist/agent-plugins.d.ts +3 -0
- package/dist/agent-plugins.js +66 -0
- package/dist/agent-plugins.js.map +1 -0
- package/dist/agents.d.ts +1 -0
- package/dist/agents.js +30 -184
- package/dist/agents.js.map +1 -1
- package/dist/behavioral-anomaly.d.ts +16 -0
- package/dist/behavioral-anomaly.js +66 -0
- package/dist/behavioral-anomaly.js.map +1 -0
- package/dist/cli.js +13 -8
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +177 -78
- package/dist/client.js.map +1 -1
- package/dist/core.d.ts +50 -2
- package/dist/core.js +73 -24
- package/dist/core.js.map +1 -1
- package/dist/credential-egress.d.ts +17 -0
- package/dist/credential-egress.js +325 -0
- package/dist/credential-egress.js.map +1 -0
- package/dist/custom-rules.js +2 -1
- package/dist/custom-rules.js.map +1 -1
- package/dist/data-detectors.js +60 -4
- package/dist/data-detectors.js.map +1 -1
- package/dist/destructive-risk.d.ts +1 -0
- package/dist/destructive-risk.js +70 -0
- package/dist/destructive-risk.js.map +1 -0
- package/dist/edit-stats.js +5 -5
- package/dist/edit-stats.js.map +1 -1
- package/dist/entity-redaction.d.ts +11 -0
- package/dist/entity-redaction.js +88 -0
- package/dist/entity-redaction.js.map +1 -0
- package/dist/file-lock.d.ts +1 -0
- package/dist/file-lock.js +54 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/forward.d.ts +13 -6
- package/dist/forward.js +120 -42
- package/dist/forward.js.map +1 -1
- package/dist/hook-adapters.d.ts +2 -2
- package/dist/hook-adapters.js +59 -60
- package/dist/hook-adapters.js.map +1 -1
- package/dist/hook-catalog.d.ts +12 -0
- package/dist/hook-catalog.js +469 -0
- package/dist/hook-catalog.js.map +1 -0
- package/dist/hook-config.d.ts +8 -0
- package/dist/hook-config.js +80 -0
- package/dist/hook-config.js.map +1 -0
- package/dist/hook-spool.d.ts +3 -0
- package/dist/hook-spool.js +56 -0
- package/dist/hook-spool.js.map +1 -0
- package/dist/install.d.ts +5 -5
- package/dist/install.js +48 -199
- package/dist/install.js.map +1 -1
- package/dist/inventory.js +1 -1
- package/dist/inventory.js.map +1 -1
- package/dist/jev.js +2 -1
- package/dist/jev.js.map +1 -1
- package/dist/judge.js +2 -1
- package/dist/judge.js.map +1 -1
- package/dist/mitigation-pattern.d.ts +1 -0
- package/dist/mitigation-pattern.js +140 -0
- package/dist/mitigation-pattern.js.map +1 -0
- package/dist/package-risk-rules.js +2 -2
- package/dist/package-risk-rules.js.map +1 -1
- package/dist/policy-paths.d.ts +20 -0
- package/dist/policy-paths.js +145 -0
- package/dist/policy-paths.js.map +1 -0
- package/dist/policy.d.ts +5 -0
- package/dist/policy.js +78 -10
- package/dist/policy.js.map +1 -1
- package/dist/rule-catalog.d.ts +3 -1
- package/dist/rule-catalog.js +124 -24
- package/dist/rule-catalog.js.map +1 -1
- package/dist/rule-matches.d.ts +13 -0
- package/dist/rule-matches.js +42 -0
- package/dist/rule-matches.js.map +1 -0
- package/dist/serve.js +55 -5
- package/dist/serve.js.map +1 -1
- package/dist/server.js +7 -6
- package/dist/server.js.map +1 -1
- package/dist/setup.js +5 -3
- package/dist/setup.js.map +1 -1
- package/dist/skill-risk-rules.js +2 -2
- package/dist/skill-risk-rules.js.map +1 -1
- package/dist/skill-setup.js +4 -5
- package/dist/skill-setup.js.map +1 -1
- package/dist/skill-sync.d.ts +5 -1
- package/dist/skill-sync.js +115 -14
- package/dist/skill-sync.js.map +1 -1
- package/dist/store.js +6 -9
- package/dist/store.js.map +1 -1
- package/dist/studio.js +2 -2
- package/package.json +5 -2
- package/stress-report.json +46 -46
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Session-consistent entity redaction: the same real secret value redacted twice in one session
|
|
2
|
+
// becomes the same placeholder both times (e.g. [SECRET_001]), and a *different* value of the
|
|
3
|
+
// same kind gets its own number ([SECRET_002]) -- unlike data-detectors.ts's redactSensitive(),
|
|
4
|
+
// which always emits the same static "[SECRET_REDACTED]" regardless of which value matched, so
|
|
5
|
+
// two different leaked secrets are indistinguishable in what the agent/reviewer sees. Only a
|
|
6
|
+
// truncated SHA-256 hash of each matched value is ever written to disk; the real value is hashed
|
|
7
|
+
// in memory and discarded immediately, never persisted or logged.
|
|
8
|
+
//
|
|
9
|
+
// Node-only (uses node:crypto and node:fs) -- kept out of data-detectors.ts on purpose, which
|
|
10
|
+
// stays pure/stateless so it can keep backing the edge-runtime SDK path (see its callers:
|
|
11
|
+
// monitor-rules.ts only imports its CustomDetector *type*, never calls its functions, at
|
|
12
|
+
// runtime). This module is only ever called from the CLI hook path in client.ts.
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { getDataDirectory } from "./config.js";
|
|
17
|
+
import { detectSensitive } from "./data-detectors.js";
|
|
18
|
+
import { withFileLock } from "./file-lock.js";
|
|
19
|
+
function entityMapPath(home = getDataDirectory()) {
|
|
20
|
+
return join(home, "entity-map.json");
|
|
21
|
+
}
|
|
22
|
+
async function readMap(home) {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(await readFile(entityMapPath(home), "utf8"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function writeMap(map, home) {
|
|
31
|
+
const path = entityMapPath(home);
|
|
32
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
33
|
+
await writeFile(path, `${JSON.stringify(map, null, 2)}\n`, { mode: 0o600 });
|
|
34
|
+
}
|
|
35
|
+
// A session untouched this long is pruned so the file doesn't grow forever. Only hashes and
|
|
36
|
+
// counters live here, never a real value, but there's no reason to keep them past the session's
|
|
37
|
+
// useful life either.
|
|
38
|
+
const SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
39
|
+
function hashValue(value) {
|
|
40
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 16);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Same redaction `detectSensitive()`/`redactSensitive()` already do, except each distinct real
|
|
44
|
+
* value gets a stable, numbered placeholder ([SECRET_001], [API_KEY_002], ...) that's consistent
|
|
45
|
+
* for that exact value within `sessionId`, and distinct per different value of the same kind.
|
|
46
|
+
* `home` is the beam data directory (injectable for tests); defaults to the real one.
|
|
47
|
+
*/
|
|
48
|
+
export async function redactWithSessionEntities(text, sessionId, custom = [], home = getDataDirectory()) {
|
|
49
|
+
const findings = detectSensitive(text, custom);
|
|
50
|
+
if (findings.length === 0)
|
|
51
|
+
return { text, findings: [] };
|
|
52
|
+
// Locked end-to-end so concurrent tool calls in the same turn -- each spawning its own
|
|
53
|
+
// `beam hook` process -- can't both read the same pre-update counter and independently assign
|
|
54
|
+
// the same next id to two different values (see file-lock.ts / behavioral-anomaly.ts, which
|
|
55
|
+
// has the identical read-modify-write race).
|
|
56
|
+
return withFileLock(entityMapPath(home), async () => {
|
|
57
|
+
const map = await readMap(home);
|
|
58
|
+
const now = new Date().toISOString();
|
|
59
|
+
const cutoff = Date.now() - SESSION_TTL_MS;
|
|
60
|
+
for (const [id, session] of Object.entries(map))
|
|
61
|
+
if (Date.parse(session.updatedAt) < cutoff)
|
|
62
|
+
delete map[id];
|
|
63
|
+
const session = map[sessionId] ?? { updatedAt: now, counters: {}, entries: {} };
|
|
64
|
+
session.updatedAt = now;
|
|
65
|
+
// detectSensitive() returns findings sorted start-descending (last match first) specifically
|
|
66
|
+
// so a splice-based replace loop can apply them right-to-left without later offsets shifting
|
|
67
|
+
// -- this loop relies on that same ordering.
|
|
68
|
+
let result = text;
|
|
69
|
+
const entityFindings = [];
|
|
70
|
+
for (const finding of findings) {
|
|
71
|
+
const value = text.slice(finding.start, finding.end);
|
|
72
|
+
const hash = hashValue(value);
|
|
73
|
+
let id = session.entries[hash];
|
|
74
|
+
if (!id) {
|
|
75
|
+
session.counters[finding.kind] = (session.counters[finding.kind] ?? 0) + 1;
|
|
76
|
+
id = `${finding.kind}_${String(session.counters[finding.kind]).padStart(3, "0")}`;
|
|
77
|
+
session.entries[hash] = id;
|
|
78
|
+
}
|
|
79
|
+
const replacement = `[${id}]`;
|
|
80
|
+
result = result.slice(0, finding.start) + replacement + result.slice(finding.end);
|
|
81
|
+
entityFindings.push({ ...finding, replacement });
|
|
82
|
+
}
|
|
83
|
+
map[sessionId] = session;
|
|
84
|
+
await writeMap(map, home).catch(() => { });
|
|
85
|
+
return { text: result, findings: entityFindings };
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=entity-redaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-redaction.js","sourceRoot":"","sources":["../src/entity-redaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function withFileLock<T>(path: string, fn: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// A minimal, zero-dependency exclusive lock for a read-modify-write cycle against one JSON state
|
|
2
|
+
// file, used by behavioral-anomaly.ts and entity-redaction.ts. Without it, two `beam hook`
|
|
3
|
+
// processes racing (the common case: an agent issuing several tool calls in parallel in one turn,
|
|
4
|
+
// each spawning its own short-lived hook process) both read the same pre-update state, both
|
|
5
|
+
// compute their own "+1", and whichever writes last wins -- the other's update is silently lost.
|
|
6
|
+
// For the anomaly detector this is a real bypass: 5 genuinely concurrent high-risk actions can
|
|
7
|
+
// collapse to 1 persisted event, since each process independently sees itself as the first.
|
|
8
|
+
//
|
|
9
|
+
// Mechanism: `open(lockPath, "wx")` atomically fails with EEXIST if the lock file already exists
|
|
10
|
+
// (POSIX O_EXCL semantics, no race window), so creating it IS the acquisition. A short backoff
|
|
11
|
+
// retry loop waits for a concurrent holder to release it (by deleting the file). Fails open on a
|
|
12
|
+
// timeout or any error -- a hook must never hang or crash the agent's turn waiting on a lock; a
|
|
13
|
+
// worst-case missed increment is far better than a stuck tool call.
|
|
14
|
+
import { mkdir, open, rm, stat, unlink } from "node:fs/promises";
|
|
15
|
+
import { dirname } from "node:path";
|
|
16
|
+
const MAX_WAIT_MS = 2000;
|
|
17
|
+
const RETRY_DELAY_MS = 20;
|
|
18
|
+
// A lock older than this is assumed to belong to a process that crashed or was killed mid-update
|
|
19
|
+
// (hook processes are short-lived; nothing legitimate holds this lock for seconds) and is removed
|
|
20
|
+
// so a stuck lock file doesn't permanently block every future update.
|
|
21
|
+
const STALE_LOCK_MS = 5000;
|
|
22
|
+
export async function withFileLock(path, fn) {
|
|
23
|
+
const lockPath = `${path}.lock`;
|
|
24
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 }).catch(() => { });
|
|
25
|
+
const deadline = Date.now() + MAX_WAIT_MS;
|
|
26
|
+
let acquired = false;
|
|
27
|
+
while (Date.now() < deadline) {
|
|
28
|
+
try {
|
|
29
|
+
const handle = await open(lockPath, "wx");
|
|
30
|
+
await handle.close();
|
|
31
|
+
acquired = true;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
if (e.code !== "EEXIST")
|
|
36
|
+
break; // unexpected error: proceed unlocked rather than hang
|
|
37
|
+
try {
|
|
38
|
+
const info = await stat(lockPath);
|
|
39
|
+
if (Date.now() - info.mtimeMs > STALE_LOCK_MS)
|
|
40
|
+
await rm(lockPath, { force: true });
|
|
41
|
+
}
|
|
42
|
+
catch { /* lock vanished between the failed open and this check -- fine, loop will retry the open */ }
|
|
43
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS + Math.random() * RETRY_DELAY_MS));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
return await fn();
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
if (acquired)
|
|
51
|
+
await unlink(lockPath).catch(() => { });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=file-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,2FAA2F;AAC3F,kGAAkG;AAClG,4FAA4F;AAC5F,iGAAiG;AACjG,+FAA+F;AAC/F,4FAA4F;AAC5F,EAAE;AACF,iGAAiG;AACjG,+FAA+F;AAC/F,iGAAiG;AACjG,gGAAgG;AAChG,oEAAoE;AACpE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,iGAAiG;AACjG,kGAAkG;AAClG,sEAAsE;AACtE,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,IAAY,EAAE,EAAoB;IACtE,MAAM,QAAQ,GAAG,GAAG,IAAI,OAAO,CAAC;IAChC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAE7E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;IAC1C,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM;QACR,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,CAAC,sDAAsD;YACjH,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,aAAa;oBAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrF,CAAC;YAAC,MAAM,CAAC,CAAC,4FAA4F,CAAC,CAAC;YACxG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,IAAI,QAAQ;YAAE,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACvD,CAAC;AACH,CAAC"}
|
package/dist/forward.d.ts
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
|
+
import { type Identity } from "./enroll.js";
|
|
1
2
|
import type { Event, Scan } from "./core.js";
|
|
2
3
|
import type { McpInventory } from "./mcp-config.js";
|
|
3
4
|
import type { SkillReport } from "./skill-sync.js";
|
|
4
|
-
export declare function forwardEvents(events: Event | Event[]): Promise<
|
|
5
|
+
export declare function forwardEvents(events: Event | Event[], expected?: Pick<Identity, "deviceId" | "orgId" | "apiBase">): Promise<boolean>;
|
|
5
6
|
export interface ForwardMcpInventoryResult {
|
|
6
7
|
ok: boolean;
|
|
7
8
|
reason?: string;
|
|
8
9
|
}
|
|
9
10
|
export declare function forwardMcpInventory(servers: McpInventory[]): Promise<ForwardMcpInventoryResult>;
|
|
10
|
-
export declare function forwardSkillInventory(report: SkillReport): Promise<ForwardMcpInventoryResult>;
|
|
11
|
+
export declare function forwardSkillInventory(report: SkillReport, existingSyncId?: string): Promise<ForwardMcpInventoryResult>;
|
|
11
12
|
export declare const FORWARD_BATCH_SIZE = 6;
|
|
12
13
|
export declare const FORWARD_FLUSH_MS = 10000;
|
|
14
|
+
export declare const SKILL_INVENTORY_BATCH_SIZE = 20;
|
|
13
15
|
export declare class ForwardQueue {
|
|
14
|
-
private pending;
|
|
15
16
|
private flushTimer;
|
|
16
|
-
|
|
17
|
+
private writing;
|
|
18
|
+
private flushing;
|
|
19
|
+
private stopped;
|
|
20
|
+
private readonly directory;
|
|
21
|
+
constructor(directory?: string);
|
|
22
|
+
push(events: Event[]): Promise<void>;
|
|
17
23
|
private scheduleFlush;
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
flush(): Promise<void>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
private deliver;
|
|
20
27
|
}
|
|
21
28
|
export declare function forwardScan(scan: Scan): Promise<void>;
|
|
22
29
|
export declare function forwardReview(id: string, reviewed: boolean): Promise<void>;
|
package/dist/forward.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { mkdir, rename, writeFile } from "node:fs/promises";
|
|
1
|
+
import { mkdir, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
2
3
|
import { dirname, join } from "node:path";
|
|
3
4
|
import { getApiUrl, getDataDirectory } from "./config.js";
|
|
4
5
|
import { lastGoodPolicyPath } from "./policy.js";
|
|
@@ -7,18 +8,19 @@ import { versionHeaders } from "./version.js";
|
|
|
7
8
|
function policyPath() {
|
|
8
9
|
return join(getDataDirectory(), "policy.json");
|
|
9
10
|
}
|
|
10
|
-
//
|
|
11
|
-
// other identity-authenticated call in this file, this must hit the *enrolled* device's own
|
|
11
|
+
// Like other identity-authenticated calls, this must hit the enrolled device's own
|
|
12
12
|
// identity.apiBase -- not a separately configured URL -- otherwise a device enrolled against a
|
|
13
13
|
// non-default workspace API (self-hosted, staging, a local dev dashboard) silently forwards
|
|
14
14
|
// events to the wrong place while `beam whoami`/`beam account` and policy sync (which do use
|
|
15
15
|
// identity.apiBase) keep reporting the device as enrolled and healthy.
|
|
16
|
-
export async function forwardEvents(events) {
|
|
16
|
+
export async function forwardEvents(events, expected) {
|
|
17
17
|
const identity = await readIdentity();
|
|
18
18
|
if (!identity)
|
|
19
|
-
return;
|
|
19
|
+
return false;
|
|
20
|
+
if (expected && (identity.deviceId !== expected.deviceId || identity.orgId !== expected.orgId || identity.apiBase !== expected.apiBase))
|
|
21
|
+
return false;
|
|
20
22
|
try {
|
|
21
|
-
await fetch(`${identity.apiBase}/v1/ingest`, {
|
|
23
|
+
const response = await fetch(`${identity.apiBase}/v1/ingest`, {
|
|
22
24
|
method: "POST",
|
|
23
25
|
headers: {
|
|
24
26
|
"Content-Type": "application/json",
|
|
@@ -27,9 +29,13 @@ export async function forwardEvents(events) {
|
|
|
27
29
|
body: JSON.stringify(events),
|
|
28
30
|
signal: AbortSignal.timeout(5000),
|
|
29
31
|
});
|
|
32
|
+
if (!response.ok)
|
|
33
|
+
throw new Error(`HTTP ${response.status}`);
|
|
34
|
+
return true;
|
|
30
35
|
}
|
|
31
|
-
catch {
|
|
32
|
-
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(`Beam workspace event delivery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
38
|
+
return false;
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
41
|
// Unlike every other call in this file, this deliberately does NOT use identity.apiBase (the
|
|
@@ -65,19 +71,24 @@ export async function forwardMcpInventory(servers) {
|
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
// Same host and auth as MCP inventory: the dedicated collector, keyed by the device secret.
|
|
68
|
-
export async function forwardSkillInventory(report) {
|
|
74
|
+
export async function forwardSkillInventory(report, existingSyncId) {
|
|
69
75
|
const identity = await readIdentity();
|
|
70
76
|
if (!identity)
|
|
71
77
|
return { ok: false, reason: "This device isn't connected to a Beam workspace." };
|
|
72
78
|
const collectorBase = getApiUrl();
|
|
73
79
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
const batchCount = Math.max(1, Math.ceil(report.skills.length / SKILL_INVENTORY_BATCH_SIZE));
|
|
81
|
+
const syncId = existingSyncId ?? randomUUID();
|
|
82
|
+
for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) {
|
|
83
|
+
const skills = report.skills.slice(batchIndex * SKILL_INVENTORY_BATCH_SIZE, (batchIndex + 1) * SKILL_INVENTORY_BATCH_SIZE);
|
|
84
|
+
const response = await fetch(`${collectorBase}/v1/skills/inventory`, {
|
|
85
|
+
method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${identity.deviceSecret}` },
|
|
86
|
+
body: JSON.stringify({ ...report, skills, syncId, batchIndex, batchCount, totalSkills: report.skills.length }), signal: AbortSignal.timeout(15_000),
|
|
87
|
+
});
|
|
88
|
+
if (!response.ok)
|
|
89
|
+
return { ok: false, reason: response.status === 404 ? "This workspace's collector doesn't support skill inventory yet." : `Collector rejected skill batch ${batchIndex + 1}/${batchCount} with HTTP ${response.status}.` };
|
|
90
|
+
}
|
|
91
|
+
return { ok: true };
|
|
81
92
|
}
|
|
82
93
|
catch (error) {
|
|
83
94
|
return { ok: false, reason: `Could not reach ${collectorBase}: ${error instanceof Error ? error.message : String(error)}` };
|
|
@@ -85,49 +96,116 @@ export async function forwardSkillInventory(report) {
|
|
|
85
96
|
}
|
|
86
97
|
export const FORWARD_BATCH_SIZE = 6;
|
|
87
98
|
export const FORWARD_FLUSH_MS = 10_000;
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
// reaches the dashboard instead of waiting indefinitely for a 15th event.
|
|
99
|
+
export const SKILL_INVENTORY_BATCH_SIZE = 20;
|
|
100
|
+
// Persist before acknowledging local ingest. Delivery failures and process restarts leave
|
|
101
|
+
// events in this outbox; the remote (orgId, dedupeKey) constraint makes retries idempotent.
|
|
102
|
+
// Each envelope is bound to the enrolled device so re-enrollment cannot send old activity
|
|
103
|
+
// into a different workspace. Only already-normalized, redacted events enter this queue.
|
|
94
104
|
export class ForwardQueue {
|
|
95
|
-
pending = [];
|
|
96
105
|
flushTimer;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
void forwardEvents(batch);
|
|
104
|
-
}
|
|
106
|
+
writing = Promise.resolve();
|
|
107
|
+
flushing;
|
|
108
|
+
stopped = false;
|
|
109
|
+
directory;
|
|
110
|
+
constructor(directory = getDataDirectory()) {
|
|
111
|
+
this.directory = join(directory, "event-outbox");
|
|
105
112
|
this.scheduleFlush();
|
|
106
113
|
}
|
|
114
|
+
push(events) {
|
|
115
|
+
const write = this.writing.then(async () => {
|
|
116
|
+
if (!events.length)
|
|
117
|
+
return;
|
|
118
|
+
const identity = await readIdentity();
|
|
119
|
+
if (!identity)
|
|
120
|
+
return;
|
|
121
|
+
await mkdir(this.directory, { recursive: true, mode: 0o700 });
|
|
122
|
+
for (let i = 0; i < events.length; i += FORWARD_BATCH_SIZE) {
|
|
123
|
+
const name = `${Date.now()}-${randomUUID()}`;
|
|
124
|
+
const temp = join(this.directory, `${name}.tmp`);
|
|
125
|
+
const envelope = { deviceId: identity.deviceId, orgId: identity.orgId, apiBase: identity.apiBase, events: events.slice(i, i + FORWARD_BATCH_SIZE) };
|
|
126
|
+
try {
|
|
127
|
+
await writeFile(temp, JSON.stringify(envelope), { mode: 0o600, flag: "wx" });
|
|
128
|
+
await rename(temp, join(this.directory, `${name}.json`));
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
await rm(temp, { force: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
this.writing = write.catch(() => { });
|
|
136
|
+
return write.then(() => {
|
|
137
|
+
if (events.length >= FORWARD_BATCH_SIZE)
|
|
138
|
+
void this.flush();
|
|
139
|
+
});
|
|
140
|
+
}
|
|
107
141
|
scheduleFlush() {
|
|
108
|
-
if (this.flushTimer)
|
|
109
|
-
clearTimeout(this.flushTimer);
|
|
110
|
-
if (!this.pending.length)
|
|
142
|
+
if (this.stopped || this.flushTimer)
|
|
111
143
|
return;
|
|
112
144
|
this.flushTimer = setTimeout(() => {
|
|
113
145
|
this.flushTimer = undefined;
|
|
114
|
-
|
|
115
|
-
return;
|
|
116
|
-
const batch = this.pending.splice(0, this.pending.length);
|
|
117
|
-
void forwardEvents(batch);
|
|
146
|
+
void this.flush();
|
|
118
147
|
}, FORWARD_FLUSH_MS);
|
|
119
148
|
this.flushTimer.unref?.();
|
|
120
149
|
}
|
|
121
|
-
/** Force out whatever is pending right now (e.g. on collector shutdown). */
|
|
122
150
|
flush() {
|
|
151
|
+
if (this.flushing)
|
|
152
|
+
return this.flushing;
|
|
123
153
|
if (this.flushTimer) {
|
|
124
154
|
clearTimeout(this.flushTimer);
|
|
125
155
|
this.flushTimer = undefined;
|
|
126
156
|
}
|
|
127
|
-
|
|
157
|
+
this.flushing = this.deliver().catch(error => {
|
|
158
|
+
console.error(`Beam event outbox: ${error instanceof Error ? error.message : String(error)}`);
|
|
159
|
+
}).finally(() => { this.flushing = undefined; this.scheduleFlush(); });
|
|
160
|
+
return this.flushing;
|
|
161
|
+
}
|
|
162
|
+
close() {
|
|
163
|
+
this.stopped = true;
|
|
164
|
+
return this.flush();
|
|
165
|
+
}
|
|
166
|
+
async deliver() {
|
|
167
|
+
await this.writing;
|
|
168
|
+
const identity = await readIdentity();
|
|
169
|
+
if (!identity)
|
|
128
170
|
return;
|
|
129
|
-
|
|
130
|
-
|
|
171
|
+
let files;
|
|
172
|
+
try {
|
|
173
|
+
files = await readdir(this.directory);
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (error.code === "ENOENT")
|
|
177
|
+
return;
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
let attempted = 0;
|
|
181
|
+
let pending = [];
|
|
182
|
+
let paths = [];
|
|
183
|
+
const send = async () => {
|
|
184
|
+
if (!pending.length)
|
|
185
|
+
return true;
|
|
186
|
+
if (!await forwardEvents(pending, identity))
|
|
187
|
+
return false;
|
|
188
|
+
for (const path of paths)
|
|
189
|
+
await rm(path, { force: true });
|
|
190
|
+
pending = [];
|
|
191
|
+
paths = [];
|
|
192
|
+
return true;
|
|
193
|
+
};
|
|
194
|
+
for (const name of files.filter(n => /^\d+-[\da-f-]+\.json$/.test(n)).sort()) {
|
|
195
|
+
const path = join(this.directory, name);
|
|
196
|
+
const envelope = JSON.parse(await readFile(path, "utf8"));
|
|
197
|
+
if (envelope.deviceId !== identity.deviceId || envelope.orgId !== identity.orgId || envelope.apiBase !== identity.apiBase)
|
|
198
|
+
continue;
|
|
199
|
+
if (attempted++ >= 100)
|
|
200
|
+
break;
|
|
201
|
+
if (pending.length + envelope.events.length > FORWARD_BATCH_SIZE && !await send())
|
|
202
|
+
return;
|
|
203
|
+
pending.push(...envelope.events);
|
|
204
|
+
paths.push(path);
|
|
205
|
+
if (pending.length >= FORWARD_BATCH_SIZE && !await send())
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
await send();
|
|
131
209
|
}
|
|
132
210
|
}
|
|
133
211
|
// Fire-and-forget: forwarding a local skill/MCP scan must never block or fail the caller.
|
package/dist/forward.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forward.js","sourceRoot":"","sources":["../src/forward.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"forward.js","sourceRoot":"","sources":["../src/forward.ts"],"names":[],"mappings":"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"}
|
package/dist/hook-adapters.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function adaptHookPayload(sourceAgent: string, raw: Obj): Obj;
|
|
1
|
+
import type { Obj } from './agents.js';
|
|
2
|
+
export declare function adaptHookPayload(sourceAgent: string, raw: Obj, suppliedEvent?: string): Obj;
|
package/dist/hook-adapters.js
CHANGED
|
@@ -1,74 +1,73 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
function passthrough(raw) {
|
|
5
|
-
// Cursor names its session `conversation_id`; without this its events are all "unassigned".
|
|
6
|
-
return raw.session_id === undefined && typeof raw.conversation_id === "string" ? { ...raw, session_id: raw.conversation_id } : raw;
|
|
7
|
-
}
|
|
8
|
-
// GitHub Copilot CLI's preToolUse payload is camelCase and has no hook_event_name field —
|
|
9
|
-
// it's implied by which hooks.json array the handler is registered under.
|
|
10
|
-
// toolArgs arrives as a JSON *string* (docs.github.com Copilot hooks reference), so parse it --
|
|
11
|
-
// left as a string, everything downstream reads tool_input as empty.
|
|
1
|
+
import { hookSpec, hookKind } from './hook-catalog.js';
|
|
2
|
+
import { commandOf } from './activity.js';
|
|
3
|
+
const obj = (v) => v && typeof v === 'object' && !Array.isArray(v) ? v : {};
|
|
12
4
|
function parseArgs(value) {
|
|
13
|
-
if (typeof value !==
|
|
5
|
+
if (typeof value !== 'string')
|
|
14
6
|
return value;
|
|
15
7
|
try {
|
|
16
|
-
|
|
17
|
-
return parsed && typeof parsed === "object" ? parsed : value;
|
|
8
|
+
return JSON.parse(value);
|
|
18
9
|
}
|
|
19
10
|
catch {
|
|
20
11
|
return value;
|
|
21
12
|
}
|
|
22
13
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// userPromptSubmitted carries `prompt` and no tool; treat it like Claude's UserPromptSubmit.
|
|
31
|
-
hook_event_name: raw.hook_event_name ?? (typeof raw.prompt === "string" && !(raw.toolName ?? raw.tool_name) ? "UserPromptSubmit" : "PreToolUse"),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
// Best-effort fallback for agents whose stdin schema is not (yet) verified against vendor docs.
|
|
35
|
-
function generic(raw) {
|
|
36
|
-
return {
|
|
37
|
-
...raw,
|
|
38
|
-
session_id: raw.session_id ?? raw.sessionId ?? raw.session,
|
|
39
|
-
cwd: raw.cwd ?? raw.project_path ?? raw.workingDirectory ?? raw.working_directory,
|
|
40
|
-
tool_name: raw.tool_name ?? raw.toolName ?? raw.tool,
|
|
41
|
-
tool_input: raw.tool_input ?? raw.toolArgs ?? raw.toolInput ?? raw.input ?? raw.args,
|
|
42
|
-
hook_event_name: raw.hook_event_name ?? raw.hookEventName ?? raw.event,
|
|
43
|
-
};
|
|
14
|
+
function text(value) {
|
|
15
|
+
if (typeof value === 'string')
|
|
16
|
+
return value;
|
|
17
|
+
if (Array.isArray(value))
|
|
18
|
+
return value.map(p => text(obj(p).text ?? obj(p).content) ?? '').filter(Boolean).join('\n');
|
|
19
|
+
if (value && typeof value === 'object')
|
|
20
|
+
return text(obj(value).content ?? obj(value).text);
|
|
44
21
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
22
|
+
export function adaptHookPayload(sourceAgent, raw, suppliedEvent) {
|
|
23
|
+
let fields = raw;
|
|
24
|
+
if (sourceAgent === 'windsurf')
|
|
25
|
+
fields = Object.keys(obj(raw.tool_info)).length ? obj(raw.tool_info) : raw;
|
|
26
|
+
if (sourceAgent === 'antigravity')
|
|
27
|
+
fields = Object.keys(obj(raw.toolCall)).length ? obj(raw.toolCall) : raw;
|
|
28
|
+
if (sourceAgent === 'cline') {
|
|
29
|
+
for (const name of ['preToolUse', 'postToolUse', 'userPromptSubmit', 'taskStart', 'taskResume', 'taskCancel', 'taskComplete', 'taskError', 'sessionShutdown'])
|
|
30
|
+
if (raw[name] && typeof raw[name] === 'object') {
|
|
31
|
+
fields = obj(raw[name]);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const kindName = suppliedEvent ?? raw.hook_event_name ?? raw.hookEventName ?? raw.hookName ?? raw.event;
|
|
36
|
+
const event = String(kindName ?? (typeof raw.prompt === 'string' && !(raw.toolName ?? raw.tool_name) ? 'UserPromptSubmit' : hookSpec(sourceAgent)?.events.find(e => hookKind(e) === 'pre') ?? ''));
|
|
37
|
+
const kind = hookKind(event);
|
|
38
|
+
const nested = obj(raw.tool_call);
|
|
39
|
+
let tool = fields.tool_name ?? fields.toolName ?? fields.tool ?? fields.name ?? nested.name;
|
|
40
|
+
if (sourceAgent === 'windsurf' && !tool)
|
|
41
|
+
tool = /read_code/.test(event) ? 'Read' : /write_code/.test(event) ? 'Edit' : /run_command/.test(event) ? 'Bash' : /mcp/.test(event) ? fields.mcp_tool_name : undefined;
|
|
42
|
+
if (event === 'beforeReadFile')
|
|
43
|
+
tool = tool ?? 'Read';
|
|
44
|
+
const inputValue = fields.tool_input ?? fields.toolArgs ?? fields.toolInput ?? fields.tool_args ?? fields.mcp_tool_arguments ?? fields.parameters ?? fields.arguments ?? fields.input ?? fields.args ?? nested.args;
|
|
45
|
+
const parsed = parseArgs(inputValue);
|
|
46
|
+
const toolInput = parsed === undefined ? (['windsurf', 'antigravity', 'cline'].includes(sourceAgent) ? { ...fields } : {}) : parsed;
|
|
47
|
+
const args = obj(toolInput);
|
|
48
|
+
const workspaceRoots = raw.workspace_roots ?? raw.workspaceRoots ?? raw.workspacePaths;
|
|
49
|
+
const roots = Array.isArray(workspaceRoots) ? workspaceRoots : [];
|
|
50
|
+
const prompt = text(raw.prompt ?? raw.user_prompt ?? raw.userPrompt ?? obj(raw.extra).user_message ?? fields.prompt ?? fields.userMessage ?? fields.message ?? (kind === 'prompt' ? raw.message ?? raw.input : undefined));
|
|
51
|
+
const isVSCode = ['copilot-cli', 'vscode'].includes(sourceAgent) && ((raw.hookEventName !== undefined && /^[A-Z]/.test(String(raw.hookEventName))) || (raw.tool_name !== undefined && raw.toolName === undefined && /^[A-Z]/.test(String(raw.hook_event_name ?? ''))));
|
|
54
52
|
return {
|
|
55
53
|
...raw,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
source_agent: isVSCode ? 'vscode' : sourceAgent,
|
|
55
|
+
session_id: (sourceAgent === "codex" ? raw.agent_id : undefined) ?? raw.session_id ?? raw.sessionId ?? raw.sessionID ?? raw.conversation_id ?? raw.conversationId ?? raw.trajectory_id ?? raw.taskId ?? raw.execution_id ?? raw.session ?? raw.environment_id,
|
|
56
|
+
parent_session_id: raw.parent_session_id ?? raw.parentSessionId ?? (sourceAgent === "codex" && raw.agent_id ? raw.session_id : undefined),
|
|
57
|
+
cwd: sourceAgent === 'junie' ? raw.project_path ?? raw.cwd : raw.cwd ?? raw.project_path ?? raw.workingDirectory ?? raw.working_directory ?? raw.working_dir ?? fields.cwd ?? roots[0],
|
|
58
|
+
tool_name: tool,
|
|
59
|
+
tool_input: toolInput,
|
|
60
|
+
tool_use_id: fields.tool_use_id ?? fields.toolUseId ?? fields.tool_call_id ?? fields.toolCallId ?? fields.callID ?? raw.tool_use_id ?? raw.tool_call_id ?? raw.call_id,
|
|
61
|
+
tool_response: raw.tool_response ?? raw.tool_result ?? raw.toolResult ?? raw.tool_output ?? raw.toolOutput ?? raw.result ?? raw.output ?? raw.metadata ?? fields.result ?? fields.output,
|
|
62
|
+
hook_event_name: event,
|
|
63
|
+
timestamp: typeof raw.timestamp === 'number' && Number.isFinite(raw.timestamp) ? new Date(raw.timestamp < 100000000000 ? raw.timestamp * 1000 : raw.timestamp).toISOString() : raw.timestamp,
|
|
64
|
+
command: commandOf({ ...raw, command: raw.command ?? fields.command ?? fields.commandLine ?? fields.command_line, tool_name: tool, tool_input: toolInput }),
|
|
65
|
+
file_path: raw.file_path ?? fields.file_path ?? fields.filePath ?? fields.path ?? args.file_path ?? args.filePath ?? args.path,
|
|
66
|
+
...(prompt !== undefined ? { prompt } : {}),
|
|
67
|
+
...(kind === 'prompt' ? { event_type: 'prompt.submit', tool_name: tool ?? event } : {}),
|
|
68
|
+
...(kind === 'permission' ? { event_type: /denied/i.test(event) ? 'permission.denied' : /result|response/i.test(event) ? 'permission.result' : 'permission.requested' } : {}),
|
|
69
|
+
...(kind === 'session' ? { event_type: /stop|end|finalize|shutdown|complete|cancel|error|deleted/i.test(event) ? 'session.end' : 'session.start' } : {}),
|
|
70
|
+
...(kind === 'assistant' ? { event_type: 'message.assistant', assistant_text: text(raw.assistant_text ?? raw.last_assistant_message ?? obj(raw.extra).assistant_message ?? raw.response ?? raw.text ?? raw.message) } : {}),
|
|
60
71
|
};
|
|
61
72
|
}
|
|
62
|
-
// Hermes Agent (pre_tool_call) and OpenClaw (before_tool_call) send the Claude-style fields but
|
|
63
|
-
// name the event in their own words; core.normalize only marks an action "proposed" for PreToolUse.
|
|
64
|
-
function preToolAlias(raw) {
|
|
65
|
-
const name = typeof raw.hook_event_name === "string" ? raw.hook_event_name.toLowerCase() : "";
|
|
66
|
-
return name === "pre_tool_call" || name === "before_tool_call" ? { ...raw, hook_event_name: "PreToolUse" } : raw;
|
|
67
|
-
}
|
|
68
|
-
const adapters = { passthrough, "copilot-camel": copilotCamel, generic, gemini, "pre-tool-alias": preToolAlias };
|
|
69
|
-
export function adaptHookPayload(sourceAgent, raw) {
|
|
70
|
-
const agent = findAgent(sourceAgent);
|
|
71
|
-
const adapter = adapters[agent?.adapter ?? "generic"];
|
|
72
|
-
return adapter(raw);
|
|
73
|
-
}
|
|
74
73
|
//# sourceMappingURL=hook-adapters.js.map
|