@agent-beam/beam 0.2.38 → 0.2.40

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 (121) hide show
  1. package/README.md +7 -13
  2. package/dist/access-risk.d.ts +10 -0
  3. package/dist/access-risk.js +43 -0
  4. package/dist/access-risk.js.map +1 -0
  5. package/dist/action-context.d.ts +30 -0
  6. package/dist/action-context.js +203 -0
  7. package/dist/action-context.js.map +1 -0
  8. package/dist/activity.d.ts +22 -0
  9. package/dist/activity.js +132 -0
  10. package/dist/activity.js.map +1 -0
  11. package/dist/agent-hook-install.d.ts +8 -0
  12. package/dist/agent-hook-install.js +278 -0
  13. package/dist/agent-hook-install.js.map +1 -0
  14. package/dist/agent-installers.js +16 -3
  15. package/dist/agent-installers.js.map +1 -1
  16. package/dist/agent-plugins.d.ts +3 -0
  17. package/dist/agent-plugins.js +66 -0
  18. package/dist/agent-plugins.js.map +1 -0
  19. package/dist/agents.d.ts +1 -0
  20. package/dist/agents.js +30 -184
  21. package/dist/agents.js.map +1 -1
  22. package/dist/approvals.d.ts +13 -1
  23. package/dist/approvals.js +14 -3
  24. package/dist/approvals.js.map +1 -1
  25. package/dist/approved-actions.d.ts +11 -0
  26. package/dist/approved-actions.js +53 -0
  27. package/dist/approved-actions.js.map +1 -0
  28. package/dist/behavioral-anomaly.d.ts +16 -0
  29. package/dist/behavioral-anomaly.js +66 -0
  30. package/dist/behavioral-anomaly.js.map +1 -0
  31. package/dist/cli.js +77 -9
  32. package/dist/cli.js.map +1 -1
  33. package/dist/client.d.ts +18 -1
  34. package/dist/client.js +359 -80
  35. package/dist/client.js.map +1 -1
  36. package/dist/core.d.ts +55 -2
  37. package/dist/core.js +85 -26
  38. package/dist/core.js.map +1 -1
  39. package/dist/credential-egress.d.ts +17 -0
  40. package/dist/credential-egress.js +325 -0
  41. package/dist/credential-egress.js.map +1 -0
  42. package/dist/custom-rules.js +3 -2
  43. package/dist/custom-rules.js.map +1 -1
  44. package/dist/data-detectors.js +60 -4
  45. package/dist/data-detectors.js.map +1 -1
  46. package/dist/destructive-risk.d.ts +1 -0
  47. package/dist/destructive-risk.js +70 -0
  48. package/dist/destructive-risk.js.map +1 -0
  49. package/dist/edit-stats.js +5 -5
  50. package/dist/edit-stats.js.map +1 -1
  51. package/dist/entity-redaction.d.ts +11 -0
  52. package/dist/entity-redaction.js +88 -0
  53. package/dist/entity-redaction.js.map +1 -0
  54. package/dist/file-lock.d.ts +1 -0
  55. package/dist/file-lock.js +54 -0
  56. package/dist/file-lock.js.map +1 -0
  57. package/dist/forward.d.ts +13 -6
  58. package/dist/forward.js +120 -42
  59. package/dist/forward.js.map +1 -1
  60. package/dist/hook-adapters.d.ts +2 -2
  61. package/dist/hook-adapters.js +59 -60
  62. package/dist/hook-adapters.js.map +1 -1
  63. package/dist/hook-catalog.d.ts +12 -0
  64. package/dist/hook-catalog.js +469 -0
  65. package/dist/hook-catalog.js.map +1 -0
  66. package/dist/hook-config.d.ts +8 -0
  67. package/dist/hook-config.js +80 -0
  68. package/dist/hook-config.js.map +1 -0
  69. package/dist/hook-spool.d.ts +3 -0
  70. package/dist/hook-spool.js +56 -0
  71. package/dist/hook-spool.js.map +1 -0
  72. package/dist/install.d.ts +5 -5
  73. package/dist/install.js +48 -199
  74. package/dist/install.js.map +1 -1
  75. package/dist/inventory.js +1 -1
  76. package/dist/inventory.js.map +1 -1
  77. package/dist/jev.js +2 -1
  78. package/dist/jev.js.map +1 -1
  79. package/dist/judge.js +2 -1
  80. package/dist/judge.js.map +1 -1
  81. package/dist/mitigation-pattern.d.ts +1 -0
  82. package/dist/mitigation-pattern.js +140 -0
  83. package/dist/mitigation-pattern.js.map +1 -0
  84. package/dist/package-risk-rules.js +2 -2
  85. package/dist/package-risk-rules.js.map +1 -1
  86. package/dist/package-scan.js +1 -1
  87. package/dist/package-scan.js.map +1 -1
  88. package/dist/packages.js +1 -1
  89. package/dist/packages.js.map +1 -1
  90. package/dist/policy-paths.d.ts +20 -0
  91. package/dist/policy-paths.js +145 -0
  92. package/dist/policy-paths.js.map +1 -0
  93. package/dist/policy.d.ts +10 -0
  94. package/dist/policy.js +99 -11
  95. package/dist/policy.js.map +1 -1
  96. package/dist/rule-catalog.d.ts +4 -2
  97. package/dist/rule-catalog.js +124 -24
  98. package/dist/rule-catalog.js.map +1 -1
  99. package/dist/rule-matches.d.ts +13 -0
  100. package/dist/rule-matches.js +42 -0
  101. package/dist/rule-matches.js.map +1 -0
  102. package/dist/serve.js +55 -5
  103. package/dist/serve.js.map +1 -1
  104. package/dist/server.js +34 -7
  105. package/dist/server.js.map +1 -1
  106. package/dist/setup.js +5 -3
  107. package/dist/setup.js.map +1 -1
  108. package/dist/skill-risk-rules.js +2 -2
  109. package/dist/skill-risk-rules.js.map +1 -1
  110. package/dist/skill-scan.js +1 -1
  111. package/dist/skill-scan.js.map +1 -1
  112. package/dist/skill-setup.js +4 -5
  113. package/dist/skill-setup.js.map +1 -1
  114. package/dist/skill-sync.d.ts +5 -1
  115. package/dist/skill-sync.js +115 -14
  116. package/dist/skill-sync.js.map +1 -1
  117. package/dist/store.js +6 -9
  118. package/dist/store.js.map +1 -1
  119. package/dist/studio.js +4 -4
  120. package/package.json +5 -2
  121. package/stress-report.json +45 -45
package/dist/agents.js CHANGED
@@ -1,188 +1,34 @@
1
+ import { HOOK_CATALOG, hookKind } from "./hook-catalog.js";
2
+ import { mergeHookSpec, unmergeHookSpec } from "./hook-config.js";
1
3
  import { join } from "node:path";
2
- function obj(v) { return v && typeof v === "object" && !Array.isArray(v) ? v : {}; }
3
- function arr(v) { return Array.isArray(v) ? v : []; }
4
- // Claude Code, Codex, Cursor, and Gemini CLI all install into a `hooks.<Event>` array of
5
- // `{ matcher, hooks: [{ type: "command", command }] }` entries (Claude Code's own shape, which
6
- // Gemini CLI's settings.json also uses verbatim per geminicli.com/docs/hooks/reference).
7
- // A handful of events -- UserPromptSubmit (Claude/Codex) and BeforeAgent (Gemini) among them --
8
- // have no matcher concept at all (they always fire); the docs' own examples omit the field there
9
- // entirely rather than sending an empty string, so this does the same to avoid relying on an
10
- // "ignored" field being tolerated rather than rejected.
11
- const CLAUDE_STYLE_EVENTS_WITHOUT_MATCHER = new Set(["UserPromptSubmit", "BeforeAgent"]);
12
- function mergeClaudeStyleHooks(event) {
13
- const supportsMatcher = !CLAUDE_STYLE_EVENTS_WITHOUT_MATCHER.has(event);
14
- return (existing, command) => {
15
- const hooks = obj(existing.hooks);
16
- const list = arr(hooks[event]).map(obj);
17
- const alreadyInstalled = list.some(entry => arr(entry.hooks).map(obj).some(h => h.command === command));
18
- if (!alreadyInstalled)
19
- list.push({ ...(supportsMatcher ? { matcher: "" } : {}), hooks: [{ type: "command", command }] });
20
- return { ...existing, hooks: { ...hooks, [event]: list } };
21
- };
22
- }
23
- // Cursor's own hooks.json instead nests `{ command, matcher }` directly under the event array.
24
- function mergeCursorHooks(event) {
25
- return (existing, command) => {
26
- const hooks = obj(existing.hooks);
27
- const list = arr(hooks[event]).map(obj);
28
- if (!list.some(entry => entry.command === command))
29
- list.push({ command, matcher: ".*" });
30
- return { version: existing.version ?? 1, ...existing, hooks: { ...hooks, [event]: list } };
31
- };
32
- }
33
- // Copilot CLI's dedicated hook file uses `{ type: "command", bash, timeoutSec }` entries.
34
- function mergeCopilotHooks(event) {
35
- return (existing, command) => {
36
- const hooks = obj(existing.hooks);
37
- const list = arr(hooks[event]).map(obj);
38
- if (!list.some(entry => entry.bash === command))
39
- list.push({ type: "command", bash: command, timeoutSec: 30 });
40
- return { version: existing.version ?? 1, ...existing, hooks: { ...hooks, [event]: list } };
41
- };
42
- }
43
- // Reverse of mergeClaudeStyleHooks: drops beam's command out of each entry's inner hooks array
44
- // (rather than the whole entry), so a user-added hook sharing the same matcher is left alone.
45
- function unmergeClaudeStyleHooks(event) {
46
- return (existing, isOwnCommand) => {
47
- const hooks = obj(existing.hooks);
48
- if (!(event in hooks))
49
- return existing;
50
- const list = arr(hooks[event]).map(obj)
51
- .map(entry => ({ ...entry, hooks: arr(entry.hooks).map(obj).filter(h => !isOwnCommand(String(h.command ?? ""))) }))
52
- .filter(entry => arr(entry.hooks).length > 0);
53
- return { ...existing, hooks: { ...hooks, [event]: list } };
54
- };
55
- }
56
- // Reverse of mergeCursorHooks.
57
- function unmergeCursorHooks(event) {
58
- return (existing, isOwnCommand) => {
59
- const hooks = obj(existing.hooks);
60
- if (!(event in hooks))
61
- return existing;
62
- const list = arr(hooks[event]).map(obj).filter(entry => !isOwnCommand(String(entry.command ?? "")));
63
- return { ...existing, hooks: { ...hooks, [event]: list } };
64
- };
65
- }
66
- // Reverse of mergeCopilotHooks.
67
- function unmergeCopilotHooks(event) {
68
- return (existing, isOwnCommand) => {
69
- const hooks = obj(existing.hooks);
70
- if (!(event in hooks))
71
- return existing;
72
- const list = arr(hooks[event]).map(obj).filter(entry => !isOwnCommand(String(entry.bash ?? "")));
73
- return { ...existing, hooks: { ...hooks, [event]: list } };
74
- };
75
- }
76
- // Installs beam into more than one hook event (e.g. the tool-call gate *and* the prompt-submit
77
- // gate) by folding each single-event merger over the config in turn. A disabled agent only ever
78
- // reliably stops at the pre-action gate if that agent never calls a tool in a turn (pure chat) --
79
- // registering the prompt-submit event too means a disabled agent's policy.disabledAgents block
80
- // (see policy.ts's evaluate()) fires before the prompt is even processed, not just before a tool
81
- // call that may never come.
82
- function mergeAll(mergers) {
83
- return (existing, command) => mergers.reduce((acc, merge) => merge(acc, command), existing);
84
- }
85
- function unmergeAll(unmergers) {
86
- return (existing, isOwnCommand) => unmergers.reduce((acc, unmerge) => unmerge(acc, isOwnCommand), existing);
87
- }
88
- export const AGENTS = [
89
- {
90
- id: "claude-code", name: "Claude Code",
91
- configs: [".claude/settings.json"], artifacts: [".claude/projects"],
92
- hookConfigPath: ".claude/settings.json", hookEventName: "PreToolUse",
93
- mergeHookConfig: mergeAll([mergeClaudeStyleHooks("PreToolUse"), mergeClaudeStyleHooks("UserPromptSubmit")]),
94
- unmergeHookConfig: unmergeAll([unmergeClaudeStyleHooks("PreToolUse"), unmergeClaudeStyleHooks("UserPromptSubmit")]),
95
- adapter: "passthrough", verifiedPayload: true,
96
- notes: "Payload verified against code.claude.com/docs/en/hooks. Also installs UserPromptSubmit (same hookSpecificOutput.permissionDecision contract, just hookEventName: \"UserPromptSubmit\") so a disabled agent is stopped before the prompt is processed, not only at its first tool call."
97
- },
98
- {
99
- id: "codex", name: "Codex",
100
- configs: [".codex/config.toml"], artifacts: [".codex/sessions", ".codex/archived_sessions"],
101
- hookConfigPath: ".codex/hooks.json", hookEventName: "PreToolUse",
102
- mergeHookConfig: mergeAll([mergeClaudeStyleHooks("PreToolUse"), mergeClaudeStyleHooks("UserPromptSubmit")]),
103
- unmergeHookConfig: unmergeAll([unmergeClaudeStyleHooks("PreToolUse"), unmergeClaudeStyleHooks("UserPromptSubmit")]),
104
- adapter: "passthrough", verifiedPayload: true,
105
- notes: "Same hooks.json shape and stdin payload fields as Claude Code (session_id, cwd, hook_event_name, tool_name, tool_input, tool_use_id). Also installs UserPromptSubmit for the same disabled-agent-at-prompt-time reason."
106
- },
107
- {
108
- id: "cursor", name: "Cursor",
109
- // ".cursor/hooks.json" is the file beam itself writes on install, so it can never be used to
110
- // detect a pre-existing Cursor install (circular). The bare ".cursor" directory is what
111
- // Cursor itself creates just from being used, so it's a real presence signal.
112
- configs: [".cursor"], artifacts: [".cursor/projects"],
113
- hookConfigPath: ".cursor/hooks.json", hookEventName: "preToolUse",
114
- mergeHookConfig: mergeAll([mergeCursorHooks("preToolUse"), mergeCursorHooks("beforeSubmitPrompt")]),
115
- unmergeHookConfig: unmergeAll([unmergeCursorHooks("preToolUse"), unmergeCursorHooks("beforeSubmitPrompt")]),
116
- adapter: "passthrough", verifiedPayload: true,
117
- notes: "Payload verified against cursor.com/docs/hooks; extra fields (model, conversation_id, ...) are ignored, not misread. Also installs beforeSubmitPrompt -- unlike preToolUse's permission field, that event's block contract is {continue: false, user_message} (see client.ts emitDeny)."
118
- },
119
- {
120
- id: "copilot-cli", name: "GitHub Copilot CLI",
121
- // Same circularity as Cursor above: ".copilot/hooks/beam.json" is our own output.
122
- // ".copilot/config.json" is what the real Copilot CLI writes on its own first run.
123
- configs: [".copilot/config.json"], artifacts: [".copilot/session-state"],
124
- hookConfigPath: ".copilot/hooks/beam.json", hookEventName: "preToolUse",
125
- mergeHookConfig: mergeAll([mergeCopilotHooks("preToolUse"), mergeCopilotHooks("userPromptSubmitted")]),
126
- unmergeHookConfig: unmergeAll([unmergeCopilotHooks("preToolUse"), unmergeCopilotHooks("userPromptSubmitted")]),
127
- adapter: "copilot-camel", verifiedPayload: true,
128
- notes: "Payload verified against docs.github.com Copilot hooks reference (camelCase: sessionId, cwd, toolName, toolArgs). userPromptSubmitted is also installed for observation/audit only -- GitHub's docs state its stdout is ignored (no blocking contract), so a disabled agent is only actually stopped at its first preToolUse call."
129
- },
130
- {
131
- id: "gemini", name: "Gemini CLI",
132
- // ".gemini/settings.json" is our own write target (circular, like Cursor/Copilot above); the
133
- // bare ".gemini" directory (created by any use of the Gemini CLI, e.g. mcp_config.json,
134
- // projects/) is the reliable presence signal instead.
135
- configs: [".gemini"], artifacts: [".gemini/tmp"],
136
- hookConfigPath: ".gemini/settings.json", hookEventName: "BeforeTool",
137
- // BeforeTool/BeforeAgent use the exact same {matcher, hooks: [{type, command}]} array shape
138
- // as Claude Code's PreToolUse/UserPromptSubmit (geminicli.com/docs/hooks/reference) --
139
- // beam previously targeted ".agents/hooks.json" with a "pre_tool_execution" event and a
140
- // "beam-security" wrapper, which is actually the unrelated Gemini API "Managed Agents"
141
- // sandbox hook contract (ai.google.dev/gemini-api/docs/agent-hooks), not Gemini CLI's own.
142
- mergeHookConfig: mergeAll([mergeClaudeStyleHooks("BeforeTool"), mergeClaudeStyleHooks("BeforeAgent")]),
143
- unmergeHookConfig: unmergeAll([unmergeClaudeStyleHooks("BeforeTool"), unmergeClaudeStyleHooks("BeforeAgent")]),
144
- adapter: "gemini", verifiedPayload: true,
145
- notes: "Payload verified against geminicli.com/docs/hooks/reference: stdin is flat (session_id, cwd, hook_event_name, tool_name, tool_input, prompt), not the nested tool_call shape the \"gemini\" adapter also tolerates as a defensive fallback. Also installs BeforeAgent so a disabled agent is stopped before the prompt reaches the model, not only at its first tool call; both events accept {decision: \"deny\", reason} and both also honor exit code 2 (see client.ts's EXIT_2_FAILS_CLOSED)."
146
- },
147
- {
148
- id: "opencode", name: "OpenCode",
149
- configs: [".config/opencode/opencode.json", ".config/opencode/opencode.jsonc"], artifacts: [".local/share/opencode"],
150
- hookConfigPath: null, pluginPath: ".opencode/plugins/beam.ts", hookEventName: "tool.execute.before",
151
- mergeHookConfig: null, unmergeHookConfig: null, adapter: "passthrough", verifiedPayload: true,
152
- notes: "Uses OpenCode's native tool.execute.before plugin hook."
153
- },
154
- {
155
- id: "hermes", name: "Hermes Agent",
156
- configs: [".hermes"], artifacts: [],
157
- hookConfigPath: ".hermes/config.yaml", hookEventName: "pre_tool_call",
158
- mergeHookConfig: null, unmergeHookConfig: null, customInstall: true,
159
- adapter: "pre-tool-alias", verifiedPayload: true,
160
- notes: "Installs a shell hook under hooks.pre_tool_call in ~/.hermes/config.yaml (default profile), between beam:begin/beam:end comments. Stdin fields (hook_event_name, tool_name, tool_input, session_id, cwd) and the block contract ({decision: \"block\", reason} or exit 2) verified against hermes-agent.nousresearch.com/docs/user-guide/features/hooks; tool_input shapes per Hermes tool are not. Hermes asks you to approve the hook on first use, and a hook that errors or times out fails open unless fail_closed is set."
161
- },
162
- {
163
- id: "openclaw", name: "OpenClaw",
164
- configs: [".openclaw"], artifacts: [],
165
- hookConfigPath: null, hookEventName: "before_tool_call",
166
- mergeHookConfig: null, unmergeHookConfig: null, customInstall: true,
167
- adapter: "pre-tool-alias", verifiedPayload: false,
168
- notes: "OpenClaw has no hook config file: beam writes a small plugin that registers api.on(\"before_tool_call\") and links it with 'openclaw plugins install --link' and 'openclaw plugins enable'. Registration and the { block, blockReason } return follow docs.openclaw.ai/plugins/hooks and published plugins, but the event field names are not printed in a reference, so the plugin reads them defensively; treat enforcement as unverified until you see a real event."
169
- },
170
- {
171
- id: "jev", name: "Jev (TypeSafe AI)",
172
- // TypeSafe's own Jev tooling and at least half a dozen independent third-party CLIs
173
- // (jev-cli, jev-axi, jev-guard, ...) each pick their own config layout, so unlike the
174
- // agents above there's no single vendor-documented directory or hook contract to target.
175
- // These are the paths seen across that ecosystem as of Sept 2026; treat as best-effort.
176
- configs: [".config/jev", ".config/jev-axi", ".jev"], artifacts: [".config/jev-axi/stats"],
177
- hookConfigPath: null, hookEventName: null,
178
- mergeHookConfig: null, unmergeHookConfig: null,
179
- adapter: "generic", verifiedPayload: false, unverifiedEcosystem: true,
180
- notes: "Jev is TypeSafe AI's non-generative 'System One' judgment model (launched 2026-09-15), " +
181
- "increasingly wired into other agents' tool-call gating (e.g. jev-guard) rather than run as " +
182
- "a coding agent itself. No single vendor hook contract exists yet across the many third-party " +
183
- "CLIs wrapping it, so this entry is discovery-only (config/artifact presence), not installable."
184
- },
185
- ];
4
+ export const AGENTS = HOOK_CATALOG.map(spec => ({
5
+ id: spec.id, name: spec.name, configs: spec.id === "copilot-cli" ? [".copilot/config.json"] : [spec.detect], artifacts: { "claude-code": [".claude/projects"], codex: [".codex/sessions", ".codex/archived_sessions"], cursor: [".cursor/projects"], "copilot-cli": [".copilot/session-state"], gemini: [".gemini/tmp"], opencode: [".local/share/opencode"] }[spec.id] ?? [],
6
+ hookConfigPath: spec.format === "plugin" ? null : spec.path,
7
+ pluginPath: spec.format === "plugin" ? spec.path : null,
8
+ hookEventName: spec.events.find(e => hookKind(e) === "pre") ?? null,
9
+ hookEvents: spec.events,
10
+ customInstall: true,
11
+ mergeHookConfig: (existing, command) => mergeHookSpec(spec, existing, command),
12
+ unmergeHookConfig: (existing, own) => unmergeHookSpec(spec, existing, own),
13
+ adapter: ["claude-code", "codex", "cursor"].includes(spec.id) ? "passthrough" : spec.id === "hermes" ? "pre-tool-alias" : spec.id === "copilot-cli" || spec.id === "vscode" ? "copilot-camel" : spec.id === "gemini" ? "gemini" : "generic",
14
+ verifiedPayload: ["claude-code", "codex", "cursor", "copilot-cli", "gemini", "hermes"].includes(spec.id),
15
+ notes: "Configuration and payload mapping based on Numbat's host contracts; validate with a live session on your agent version. See docs/agent-hooks.md.",
16
+ }));
17
+ AGENTS.push({
18
+ id: "jev", name: "Jev (TypeSafe AI)",
19
+ // TypeSafe's own Jev tooling and at least half a dozen independent third-party CLIs
20
+ // (jev-cli, jev-axi, jev-guard, ...) each pick their own config layout, so unlike the
21
+ // agents above there's no single vendor-documented directory or hook contract to target.
22
+ // These are the paths seen across that ecosystem as of Sept 2026; treat as best-effort.
23
+ configs: [".config/jev", ".config/jev-axi", ".jev"], artifacts: [".config/jev-axi/stats"],
24
+ hookConfigPath: null, hookEventName: null,
25
+ mergeHookConfig: null, unmergeHookConfig: null,
26
+ adapter: "generic", verifiedPayload: false, unverifiedEcosystem: true,
27
+ notes: "Jev is TypeSafe AI's non-generative 'System One' judgment model (launched 2026-09-15), " +
28
+ "increasingly wired into other agents' tool-call gating (e.g. jev-guard) rather than run as " +
29
+ "a coding agent itself. No single vendor hook contract exists yet across the many third-party " +
30
+ "CLIs wrapping it, so this entry is discovery-only (config/artifact presence), not installable."
31
+ });
186
32
  export function findAgent(id) {
187
33
  return AGENTS.find(a => a.id === id);
188
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,14 @@ export interface ApprovalRequest {
33
33
  status: ApprovalStatus;
34
34
  decision?: ApprovalDecision;
35
35
  fingerprint: string;
36
+ /** Why the requester says it needs this access. Shown to the approver; not itself a grant. */
37
+ reason?: string;
38
+ /** The approver's own explanation, set when the decision is applied (see applyApproval()). */
39
+ decision_reason?: string;
40
+ /** How long an APPROVED decision grants: the approver's choice, 10-60 minutes. Only meaningful
41
+ * alongside status "APPROVED"; unset on every other status. Drives the local TTL on the
42
+ * requesting device's approved-actions.json (see beam-cli's approved-actions.ts). */
43
+ grant_minutes?: number;
36
44
  }
37
45
  export interface ApprovalPolicy {
38
46
  level: ApprovalLevel;
@@ -61,5 +69,9 @@ export declare function createApprovalRequest(input: Omit<ApprovalRequest, "requ
61
69
  export declare function validateApprovalRequest(request: ApprovalRequest): boolean;
62
70
  export declare function approvalAuditEvent(previous: ApprovalRequest, next: ApprovalRequest, approver: string): string;
63
71
  export declare function formatApprovalRequest(request: ApprovalRequest): string;
64
- export declare function applyApproval(request: ApprovalRequest, decision: ApprovalDecision, approver: string, now?: number): ApprovalRequest;
72
+ export declare const MIN_GRANT_MINUTES = 10;
73
+ export declare const MAX_GRANT_MINUTES = 60;
74
+ export declare const DEFAULT_GRANT_MINUTES = 15;
75
+ export declare function clampGrantMinutes(minutes: number | undefined): number;
76
+ export declare function applyApproval(request: ApprovalRequest, decision: ApprovalDecision, approver: string, now?: number, decisionReason?: string, grantMinutes?: number): ApprovalRequest;
65
77
  export declare function approvalStillValid(request: ApprovalRequest, current: Omit<ApprovalRequest, "request_id" | "created_at" | "expires_at" | "status" | "fingerprint">, now?: number): boolean;
package/dist/approvals.js CHANGED
@@ -65,7 +65,15 @@ export function formatApprovalRequest(request) {
65
65
  const resource = request.path || request.url || request.command || request.tool;
66
66
  return `[${request.level}] ${request.agent} ${request.tool}: ${resource} (risk ${request.risk_score}/100 ${request.risk_level})`;
67
67
  }
68
- export function applyApproval(request, decision, approver, now = Date.now()) {
68
+ export const MIN_GRANT_MINUTES = 10;
69
+ export const MAX_GRANT_MINUTES = 60;
70
+ export const DEFAULT_GRANT_MINUTES = 15;
71
+ export function clampGrantMinutes(minutes) {
72
+ if (!Number.isFinite(minutes))
73
+ return DEFAULT_GRANT_MINUTES;
74
+ return Math.min(MAX_GRANT_MINUTES, Math.max(MIN_GRANT_MINUTES, Math.round(minutes)));
75
+ }
76
+ export function applyApproval(request, decision, approver, now = Date.now(), decisionReason, grantMinutes) {
69
77
  if (!validateApprovalRequest(request))
70
78
  return { ...request, status: "DENIED", decision: "DENY" };
71
79
  if (Date.parse(request.expires_at) <= now || decision === "EXPIRE")
@@ -74,11 +82,14 @@ export function applyApproval(request, decision, approver, now = Date.now()) {
74
82
  return { ...request, status: "DENIED", decision: "DENY" };
75
83
  if (!request.approver.includes(approver))
76
84
  return { ...request, status: "DENIED", decision: "DENY" };
85
+ // decisionReason/grantMinutes only ever reflect a genuine decision made below by an authorized
86
+ // approver on a still-pending request -- never attached to the fail-closed guard rejections
87
+ // above, which aren't a real person's explanation and shouldn't be presented as one.
77
88
  if (decision === "DENY")
78
- return { ...request, status: "DENIED", decision };
89
+ return { ...request, status: "DENIED", decision, decision_reason: decisionReason };
79
90
  if (request.status !== "PENDING")
80
91
  return request;
81
- return { ...request, status: "APPROVED", decision };
92
+ return { ...request, status: "APPROVED", decision, decision_reason: decisionReason, grant_minutes: clampGrantMinutes(grantMinutes) };
82
93
  }
83
94
  export function approvalStillValid(request, current, now = Date.now()) {
84
95
  return request.status === "APPROVED" && Date.parse(request.expires_at) > now && request.fingerprint === approvalFingerprint(current);
@@ -1 +1 @@
1
- {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ApprovedActionTarget {
2
+ agent: string;
3
+ tool: string;
4
+ command?: string;
5
+ path?: string;
6
+ url?: string;
7
+ }
8
+ export declare function approvedActionsFile(): string;
9
+ export declare function approvedActionFingerprint(target: ApprovedActionTarget): string;
10
+ export declare function recordApprovedAction(target: ApprovedActionTarget, ttlMs?: number): Promise<void>;
11
+ export declare function consumeApprovedAction(target: ApprovedActionTarget): Promise<boolean>;
@@ -0,0 +1,53 @@
1
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import { getDataDirectory } from "./config.js";
5
+ export function approvedActionsFile() { return join(getDataDirectory(), "approved-actions.json"); }
6
+ export function approvedActionFingerprint(target) {
7
+ return createHash("sha256").update(JSON.stringify({
8
+ agent: target.agent.toLowerCase(),
9
+ tool: target.tool.toLowerCase(),
10
+ command: target.command || "",
11
+ path: target.path || "",
12
+ url: target.url || "",
13
+ })).digest("hex");
14
+ }
15
+ async function readApprovedActions() {
16
+ try {
17
+ const parsed = JSON.parse(await readFile(approvedActionsFile(), "utf8"));
18
+ return Array.isArray(parsed)
19
+ ? parsed.filter((e) => Boolean(e) && typeof e === "object" && typeof e.fingerprint === "string" && typeof e.expiresAt === "string")
20
+ : [];
21
+ }
22
+ catch {
23
+ return [];
24
+ }
25
+ }
26
+ async function writeApprovedActions(entries) {
27
+ const dir = getDataDirectory();
28
+ await mkdir(dir, { recursive: true, mode: 0o700 });
29
+ const file = approvedActionsFile();
30
+ const temp = `${file}.tmp`;
31
+ await writeFile(temp, JSON.stringify(entries) + "\n", { mode: 0o600 });
32
+ await rename(temp, file);
33
+ }
34
+ // Bounded (default 15 minutes) -- an approval is permission to proceed now, not a standing
35
+ // exception. Capped at 200 entries so a burst of asks can't grow this file unbounded.
36
+ export async function recordApprovedAction(target, ttlMs = 15 * 60_000) {
37
+ const live = (await readApprovedActions()).filter(e => Date.parse(e.expiresAt) > Date.now());
38
+ live.push({ fingerprint: approvedActionFingerprint(target), expiresAt: new Date(Date.now() + ttlMs).toISOString() });
39
+ await writeApprovedActions(live.slice(-200));
40
+ }
41
+ // Single-use: APPROVE_ONCE semantics (see approvals.ts) -- a match is removed on read so it can't
42
+ // silently re-authorize a later, unrelated repeat of the same command without asking again.
43
+ export async function consumeApprovedAction(target) {
44
+ const fingerprint = approvedActionFingerprint(target);
45
+ const now = Date.now();
46
+ const entries = await readApprovedActions();
47
+ const match = entries.find(e => e.fingerprint === fingerprint && Date.parse(e.expiresAt) > now);
48
+ if (!match)
49
+ return false;
50
+ await writeApprovedActions(entries.filter(e => e !== match && Date.parse(e.expiresAt) > now));
51
+ return true;
52
+ }
53
+ //# sourceMappingURL=approved-actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approved-actions.js","sourceRoot":"","sources":["../src/approved-actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /** The rolling window an action burst is measured over. */
2
+ export declare const ANOMALY_WINDOW_MS: number;
3
+ /** High/critical-severity actions within the window that count as a burst. */
4
+ export declare const ANOMALY_THRESHOLD = 5;
5
+ export interface AnomalyResult {
6
+ triggered: boolean;
7
+ count: number;
8
+ windowMinutes: number;
9
+ }
10
+ /**
11
+ * Records one HIGH/CRITICAL-severity action for `sessionId` (a LOW/MEDIUM `riskLevel` is a
12
+ * no-op: it still prunes/persists housekeeping but never adds an event or can trigger), and
13
+ * reports whether this session has hit `ANOMALY_THRESHOLD` such actions within
14
+ * `ANOMALY_WINDOW_MS`. `home` is the beam data directory (injectable for tests).
15
+ */
16
+ export declare function recordAndCheckAnomaly(sessionId: string, riskLevel: string, home?: string): Promise<AnomalyResult>;
@@ -0,0 +1,66 @@
1
+ // Behavioral anomaly detection: flags a burst of high/critical-severity actions from one agent
2
+ // session within a short window, independent of whether any single action was individually
3
+ // blocked. An agent that's been talked into a chain of risky actions (prompt injection, a
4
+ // compromised skill, a confused multi-step plan) often shows this shape even when each step
5
+ // individually only rates "ask" rather than "deny" -- worth a human's attention as a pattern,
6
+ // not just as isolated findings. Node-only (fs-backed session state), called from the CLI hook
7
+ // path in client.ts only -- same separation from data-detectors.ts/rule-catalog.ts as
8
+ // entity-redaction.ts, which stay pure so they can keep backing the edge-runtime SDK path.
9
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
10
+ import { dirname, join } from "node:path";
11
+ import { getDataDirectory } from "./config.js";
12
+ import { withFileLock } from "./file-lock.js";
13
+ function activityPath(home) {
14
+ return join(home, "behavioral-activity.json");
15
+ }
16
+ async function readActivity(home) {
17
+ try {
18
+ return JSON.parse(await readFile(activityPath(home), "utf8"));
19
+ }
20
+ catch {
21
+ return {};
22
+ }
23
+ }
24
+ async function writeActivity(map, home) {
25
+ const path = activityPath(home);
26
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
27
+ await writeFile(path, `${JSON.stringify(map, null, 2)}\n`, { mode: 0o600 });
28
+ }
29
+ /** The rolling window an action burst is measured over. */
30
+ export const ANOMALY_WINDOW_MS = 10 * 60 * 1000; // 10 minutes
31
+ /** High/critical-severity actions within the window that count as a burst. */
32
+ export const ANOMALY_THRESHOLD = 5;
33
+ // A session with no new high/critical event in this long is dropped entirely, so the file
34
+ // doesn't grow forever -- only timestamps live here, nothing sensitive either way.
35
+ const SESSION_TTL_MS = 24 * 60 * 60 * 1000;
36
+ /**
37
+ * Records one HIGH/CRITICAL-severity action for `sessionId` (a LOW/MEDIUM `riskLevel` is a
38
+ * no-op: it still prunes/persists housekeeping but never adds an event or can trigger), and
39
+ * reports whether this session has hit `ANOMALY_THRESHOLD` such actions within
40
+ * `ANOMALY_WINDOW_MS`. `home` is the beam data directory (injectable for tests).
41
+ */
42
+ export async function recordAndCheckAnomaly(sessionId, riskLevel, home = getDataDirectory()) {
43
+ if (!sessionId)
44
+ return { triggered: false, count: 0, windowMinutes: ANOMALY_WINDOW_MS / 60_000 };
45
+ // Locked end-to-end (read, mutate, write) so concurrent tool calls in the same turn -- each
46
+ // spawning its own `beam hook` process -- don't lose each other's increments to a read-write
47
+ // race (see file-lock.ts). Without this, a genuine 5-action parallel burst could collapse to
48
+ // a single persisted event, since every process would independently read "0 prior events".
49
+ return withFileLock(activityPath(home), async () => {
50
+ const map = await readActivity(home);
51
+ const now = Date.now();
52
+ for (const [id, session] of Object.entries(map)) {
53
+ const last = session.events.at(-1) ?? 0;
54
+ if (now - last > SESSION_TTL_MS)
55
+ delete map[id];
56
+ }
57
+ const session = map[sessionId] ?? { events: [] };
58
+ if (riskLevel === "HIGH" || riskLevel === "CRITICAL")
59
+ session.events.push(now);
60
+ session.events = session.events.filter(at => now - at <= ANOMALY_WINDOW_MS);
61
+ map[sessionId] = session;
62
+ await writeActivity(map, home).catch(() => { });
63
+ return { triggered: session.events.length >= ANOMALY_THRESHOLD, count: session.events.length, windowMinutes: ANOMALY_WINDOW_MS / 60_000 };
64
+ });
65
+ }
66
+ //# sourceMappingURL=behavioral-anomaly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"behavioral-anomaly.js","sourceRoot":"","sources":["../src/behavioral-anomaly.ts"],"names":[],"mappings":"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"}