lemura 1.5.2 → 1.5.3
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/CHANGELOG.md +7 -0
- package/dist/{agent-Cq_oRvoc.d.ts → agent-Cd704J0J.d.ts} +7 -2
- package/dist/{agent-DPSUNlK6.d.mts → agent-DFh31XIA.d.mts} +7 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -2
- package/dist/index.mjs.map +1 -1
- package/dist/tools/index.d.mts +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/types/index.d.mts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.5.3] - 2026-05-30
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Tool firewall `ask` decision could execute denied tools** (critical): when a `ToolFirewallConfig.onAsk` handler returned anything other than the exact string `'deny'` — including the boolean `false`, `undefined`, or by throwing — the tool was executed anyway. A user pressing "Stop"/deny could not actually stop the tool call. The `ask` path is now **fail-safe**: only an explicit accept signal (`'accept'` or `true`) allows execution; `'deny'`, `false`, `undefined`, `void`, and thrown errors all block the tool and inject a `Blocked by tool firewall` observation.
|
|
13
|
+
- `ToolFirewallConfig.onAsk` now accepts `'accept' | 'deny' | boolean | void` (and the `Promise` thereof) for ergonomics. The previous `'accept' | 'deny'` return remains valid.
|
|
14
|
+
|
|
8
15
|
## [1.5.2] - 2026-05-30
|
|
9
16
|
|
|
10
17
|
### Changed
|
|
@@ -199,9 +199,14 @@ interface ToolFirewallConfig {
|
|
|
199
199
|
rules?: ToolFirewallRule[];
|
|
200
200
|
/**
|
|
201
201
|
* Called when a tool hits the 'ask' decision.
|
|
202
|
-
*
|
|
202
|
+
*
|
|
203
|
+
* Return `'accept'` (or `true`) to allow the tool to run; return `'deny'`
|
|
204
|
+
* (or `false`) to block it. The decision is **fail-safe**: only an explicit
|
|
205
|
+
* accept signal allows execution — any other value (`'deny'`, `false`,
|
|
206
|
+
* `undefined`, `null`, a thrown error) blocks the tool. If `onAsk` is
|
|
207
|
+
* omitted entirely, an `'ask'` decision behaves like `'deny'`.
|
|
203
208
|
*/
|
|
204
|
-
onAsk?: (toolName: string, argsJson: string) => Promise<'accept' | 'deny'> | 'accept' | 'deny';
|
|
209
|
+
onAsk?: (toolName: string, argsJson: string) => Promise<'accept' | 'deny' | boolean | void> | 'accept' | 'deny' | boolean | void;
|
|
205
210
|
}
|
|
206
211
|
/**
|
|
207
212
|
* Execution budget constraints for tool calls within a session.
|
|
@@ -199,9 +199,14 @@ interface ToolFirewallConfig {
|
|
|
199
199
|
rules?: ToolFirewallRule[];
|
|
200
200
|
/**
|
|
201
201
|
* Called when a tool hits the 'ask' decision.
|
|
202
|
-
*
|
|
202
|
+
*
|
|
203
|
+
* Return `'accept'` (or `true`) to allow the tool to run; return `'deny'`
|
|
204
|
+
* (or `false`) to block it. The decision is **fail-safe**: only an explicit
|
|
205
|
+
* accept signal allows execution — any other value (`'deny'`, `false`,
|
|
206
|
+
* `undefined`, `null`, a thrown error) blocks the tool. If `onAsk` is
|
|
207
|
+
* omitted entirely, an `'ask'` decision behaves like `'deny'`.
|
|
203
208
|
*/
|
|
204
|
-
onAsk?: (toolName: string, argsJson: string) => Promise<'accept' | 'deny'> | 'accept' | 'deny';
|
|
209
|
+
onAsk?: (toolName: string, argsJson: string) => Promise<'accept' | 'deny' | boolean | void> | 'accept' | 'deny' | boolean | void;
|
|
205
210
|
}
|
|
206
211
|
/**
|
|
207
212
|
* Execution budget constraints for tool calls within a session.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as IProviderAdapter, d as TranscriptionRequest, e as TranscriptionResponse, f as SynthesisRequest, A as AudioChunk, V as VisionRequest, g as VisionResponse, h as ImageGenRequest, i as ImageGenResponse, M as ModelInfo, C as ContextWindow, T as Turn, j as ContentBlock, I as IToolDefinition } from './adapters-DAzmrg4l.mjs';
|
|
2
2
|
export { k as CompletionChunk, l as CompletionRequest, m as CompletionResponse, b as IContextStrategy, c as IScratchpadAdapter, n as IStorageAdapter, N as NormalizedMessage, o as STMItem, p as STMRegistryConfig, S as ShortTermMemoryRegistry, q as TokenUsage, r as ToolCall, s as ToolContext, t as ToolResult } from './adapters-DAzmrg4l.mjs';
|
|
3
|
-
import { S as SessionConfig, G as Goal, I as IToolResponseProcessor, T as ToolResponseEvaluation, M as MCPServerConfig, a as MCPToolDefinition } from './agent-
|
|
4
|
-
export { b as GoalInjector, c as GoalVerifierResult, d as MCPJsonRpcRequest, e as MCPJsonRpcResponse, f as MCPTransportType, g as MediaConfig, h as ToolDecision, i as ToolExecutionBudget, j as ToolFirewallConfig, k as ToolFirewallRule, l as TraceEvent } from './agent-
|
|
3
|
+
import { S as SessionConfig, G as Goal, I as IToolResponseProcessor, T as ToolResponseEvaluation, M as MCPServerConfig, a as MCPToolDefinition } from './agent-DFh31XIA.mjs';
|
|
4
|
+
export { b as GoalInjector, c as GoalVerifierResult, d as MCPJsonRpcRequest, e as MCPJsonRpcResponse, f as MCPTransportType, g as MediaConfig, h as ToolDecision, i as ToolExecutionBudget, j as ToolFirewallConfig, k as ToolFirewallRule, l as TraceEvent } from './agent-DFh31XIA.mjs';
|
|
5
5
|
export { LemuraAdapterError, LemuraContextOverflowError, LemuraError, LemuraMCPConnectionError, LemuraMCPError, LemuraMCPTimeoutError, LemuraMaxIterationsError, LemuraSkillInjectionError, LemuraToolNotFoundError, LemuraToolTimeoutError, LemuraToolValidationError } from './types/index.mjs';
|
|
6
6
|
import { I as ILogger } from './logger-DxvKliuk.mjs';
|
|
7
7
|
export { L as LogLevel, a as LogMetadata, S as Severity } from './logger-DxvKliuk.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as IProviderAdapter, d as TranscriptionRequest, e as TranscriptionResponse, f as SynthesisRequest, A as AudioChunk, V as VisionRequest, g as VisionResponse, h as ImageGenRequest, i as ImageGenResponse, M as ModelInfo, C as ContextWindow, T as Turn, j as ContentBlock, I as IToolDefinition } from './adapters-CIRkrCHl.js';
|
|
2
2
|
export { k as CompletionChunk, l as CompletionRequest, m as CompletionResponse, b as IContextStrategy, c as IScratchpadAdapter, n as IStorageAdapter, N as NormalizedMessage, o as STMItem, p as STMRegistryConfig, S as ShortTermMemoryRegistry, q as TokenUsage, r as ToolCall, s as ToolContext, t as ToolResult } from './adapters-CIRkrCHl.js';
|
|
3
|
-
import { S as SessionConfig, G as Goal, I as IToolResponseProcessor, T as ToolResponseEvaluation, M as MCPServerConfig, a as MCPToolDefinition } from './agent-
|
|
4
|
-
export { b as GoalInjector, c as GoalVerifierResult, d as MCPJsonRpcRequest, e as MCPJsonRpcResponse, f as MCPTransportType, g as MediaConfig, h as ToolDecision, i as ToolExecutionBudget, j as ToolFirewallConfig, k as ToolFirewallRule, l as TraceEvent } from './agent-
|
|
3
|
+
import { S as SessionConfig, G as Goal, I as IToolResponseProcessor, T as ToolResponseEvaluation, M as MCPServerConfig, a as MCPToolDefinition } from './agent-Cd704J0J.js';
|
|
4
|
+
export { b as GoalInjector, c as GoalVerifierResult, d as MCPJsonRpcRequest, e as MCPJsonRpcResponse, f as MCPTransportType, g as MediaConfig, h as ToolDecision, i as ToolExecutionBudget, j as ToolFirewallConfig, k as ToolFirewallRule, l as TraceEvent } from './agent-Cd704J0J.js';
|
|
5
5
|
export { LemuraAdapterError, LemuraContextOverflowError, LemuraError, LemuraMCPConnectionError, LemuraMCPError, LemuraMCPTimeoutError, LemuraMaxIterationsError, LemuraSkillInjectionError, LemuraToolNotFoundError, LemuraToolTimeoutError, LemuraToolValidationError } from './types/index.js';
|
|
6
6
|
import { I as ILogger } from './logger-DxvKliuk.js';
|
|
7
7
|
export { L as LogLevel, a as LogMetadata, S as Severity } from './logger-DxvKliuk.js';
|
package/dist/index.js
CHANGED
|
@@ -3260,8 +3260,17 @@ ${blocks.join("\n\n")}
|
|
|
3260
3260
|
}
|
|
3261
3261
|
if (firewall.decision === "ask") {
|
|
3262
3262
|
if (this.config.toolFirewall?.onAsk) {
|
|
3263
|
-
|
|
3264
|
-
|
|
3263
|
+
let accepted = false;
|
|
3264
|
+
try {
|
|
3265
|
+
const userDecision = await this.config.toolFirewall.onAsk(toolName, argsJson);
|
|
3266
|
+
accepted = userDecision === "accept" || userDecision === true;
|
|
3267
|
+
} catch (e) {
|
|
3268
|
+
this.logger.warn(`Tool firewall onAsk handler threw \u2014 treating as deny: ${toolName}`, {
|
|
3269
|
+
error: e instanceof Error ? e.message : String(e)
|
|
3270
|
+
});
|
|
3271
|
+
accepted = false;
|
|
3272
|
+
}
|
|
3273
|
+
if (!accepted) {
|
|
3265
3274
|
this.logger.warn(`Tool blocked by firewall (ask \u2192 deny): ${toolName}`, { reason: firewall.reason });
|
|
3266
3275
|
toolResults.push({ toolCallId, content: `Blocked by tool firewall: ${firewall.reason}` });
|
|
3267
3276
|
return false;
|