lemura 1.4.3 → 1.5.0
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 +62 -0
- package/README.md +5 -0
- package/dist/adapters/index.d.mts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/{adapters-CVcfWf85.d.ts → adapters-DHQOGl8Y.d.ts} +1 -1
- package/dist/{adapters-BhTAnrOM.d.mts → adapters-S96Ka9wt.d.mts} +1 -1
- package/dist/{agent-DfN5nNXc.d.mts → agent-BefjpRHZ.d.mts} +109 -4
- package/dist/{agent-DTcDIKIn.d.ts → agent-CjoFQGlk.d.ts} +109 -4
- package/dist/context/index.d.mts +2 -2
- package/dist/context/index.d.ts +2 -2
- package/dist/index.d.mts +108 -74
- package/dist/index.d.ts +108 -74
- package/dist/index.js +395 -165
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +395 -165
- package/dist/index.mjs.map +1 -1
- package/dist/tools/index.d.mts +2 -2
- package/dist/tools/index.d.ts +2 -2
- package/dist/types/index.d.mts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,68 @@ 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.0] - 2026-05-27
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`SessionManager.stream()`**: New `async *stream(userMessage)` method that runs the full ReAct loop (tool calls, goal verification, corrections) and then streams the final assistant response token-by-token as an `AsyncIterable<string>`. All tool use and verification completes before the first token is yielded, so callers always receive a clean, final response.
|
|
13
|
+
|
|
14
|
+
- **`GoalVerifierResult` interface** (`src/types/agent.ts`): Return type for `goalVerifier` callbacks and the built-in LLM-based checker. Fields: `achieved: boolean`, `missing?: string` (injected as a follow-up user message when false), `reason?: string` (surfaced in trace events).
|
|
15
|
+
|
|
16
|
+
- **`SessionConfig.goalVerifier`**: Optional user-supplied async callback `(goal: Goal, turns: Turn[]) => Promise<GoalVerifierResult> | GoalVerifierResult`. Called after the ReAct loop reaches a `stop` finish reason when `enableGoalPlanning` is `true`. Returning `{ achieved: false, missing: '...' }` injects a silent correction loop (capped at one retry). When omitted and `successCriteria` is non-empty, Lemura falls back to a built-in LLM check.
|
|
17
|
+
|
|
18
|
+
- **`SessionConfig.enableGoalVerification`**: Boolean flag to opt out of post-run goal verification. Defaults to `true` when `enableGoalPlanning` is set. Set to `false` to skip the verifier step entirely without removing `enableGoalPlanning`.
|
|
19
|
+
|
|
20
|
+
- **`SessionManager._executeLoop()`**: Internal refactor — `run()` and `stream()` now share a single `_executeLoop()` core that handles tool dispatch, goal injection, step budgets, and verification. Only the final-response step differs between the two public methods.
|
|
21
|
+
|
|
22
|
+
- **`GoalVerification.test.ts`**: Unit tests covering the `goalVerifier` callback path, the built-in LLM verifier fallback, and the `enableGoalVerification: false` opt-out.
|
|
23
|
+
|
|
24
|
+
## [1.4.4] - 2026-05-21
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`StepVerifier` on `ContinuationStep`** (`verify?: StepVerifier`): Optional semantic verifier called after a tool executes to confirm the sub-goal is actually satisfied — independent of the LLM's own assessment. Returns `pass`, `fail`, or `retry`. A `retry` verdict resets the step to `pending` and re-queues it for the next iteration; `fail` triggers BFS propagation to dependant steps. Supports `maxRetries?: number` (default: `0`) before a `retry` verdict is forced to `fail`. Verifier exceptions are caught and treated as `fail`.
|
|
29
|
+
|
|
30
|
+
- **`StepVerifierResult` interface**: `{ status: 'pass' | 'fail' | 'retry'; reason?: string }` — the return type of `StepVerifier.check()`.
|
|
31
|
+
|
|
32
|
+
- **`ContinuationPlanner.markStepPending(stepId)`**: Resets a step to `pending` for a retry attempt and increments its internal retry counter.
|
|
33
|
+
|
|
34
|
+
- **`ContinuationPlanner.getRetryCount(stepId)`**: Returns how many times a step has been retried.
|
|
35
|
+
|
|
36
|
+
- **`SessionManager.getPlan()`**: New public method returning a snapshot of the current `ContinuationPlan` (or `null` if no plan is active). Use this after `run()` for post-mortem inspection of step statuses without relying on `onTrace`.
|
|
37
|
+
|
|
38
|
+
- **`TraceEvent.type: 'verification'`**: New trace type. Emitted as `step_retry` when a verifier returns `retry`, and supplements the existing `step_failed` / `step_skipped` events now emitted by the planner.
|
|
39
|
+
|
|
40
|
+
- **`onStepFailed` / `onStepSkipped` callbacks on `ContinuationPlanner`**: Internal callbacks wired at `setPlan()` time to emit `planning/step_failed` and `planning/step_skipped` trace events — including BFS-propagated skips, which were previously invisible to `onTrace`.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- **`maxCompletionTokens` default raised from `2_000` to `4_000`**: The previous default was too low for complex reasoning chains, causing silent mid-thought truncations. Fully backward-compatible — any explicit `maxCompletionTokens` in existing configs is unchanged.
|
|
45
|
+
|
|
46
|
+
- **`ContinuationPlanner.markStepFailed(stepId, reason?)`** and **`markStepSkipped(stepId, reason?)`**: Both methods now accept an optional `reason` string surfaced in trace events and BFS-propagated skip messages.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- **BFS-propagated step skips were invisible to `onTrace`**: When a step failed and its dependants were automatically skipped, no trace events were emitted for the skipped steps. The new `onStepSkipped` callback fires for every BFS-propagated skip, making silent plan collapses visible.
|
|
51
|
+
|
|
52
|
+
- **No way to inspect plan state after `run()`**: `continuationPlanner` was private with no public accessor. The new `getPlan()` method exposes a safe snapshot for post-run debugging.
|
|
53
|
+
|
|
54
|
+
### Other
|
|
55
|
+
|
|
56
|
+
- **Config coherence warning** (`maxSteps` vs `maxIterations`): The `SessionManager` constructor now logs a `warn`-level message when `maxSteps` is explicitly set without a matching `maxIterations`, or when `maxSteps` is so large relative to `maxIterations` that it can never be reached. No behavior change — purely diagnostic, fully backward-compatible.
|
|
57
|
+
|
|
58
|
+
## [1.4.3] - 2026-05-14
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- **npm package metadata**: Added `repository`, `bugs`, `homepage`, `keywords`, `author`, `license`, `engines`, `sideEffects`, and `files` fields to `package.json` to meet npm publishing standards.
|
|
63
|
+
|
|
64
|
+
## [1.4.2] - 2026-05-14
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- **OpenAI wire format for tool calls**: `OpenAICompatibleAdapter.toOpenAIMessages()` now converts lemura's internal camelCase `toolCalls` (assistant turns) and `name`-keyed tool results (tool turns) to the proper OpenAI wire format (`tool_calls` / `tool_call_id`). Previously, providers enforcing strict OpenAI compatibility (e.g. Cerebras) would reject these messages with a 400/422 error.
|
|
69
|
+
|
|
8
70
|
## [1.4.1] - 2026-05-07
|
|
9
71
|
|
|
10
72
|
### Added
|
package/README.md
CHANGED
|
@@ -86,6 +86,11 @@ async function main() {
|
|
|
86
86
|
|
|
87
87
|
const response = await session.run('What is lemura?');
|
|
88
88
|
console.log(response);
|
|
89
|
+
|
|
90
|
+
// Or stream the final response token-by-token
|
|
91
|
+
for await (const token of session.stream('What is lemura?')) {
|
|
92
|
+
process.stdout.write(token);
|
|
93
|
+
}
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
main();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as IProviderAdapter, l as CompletionRequest, m as CompletionResponse, k as CompletionChunk, M as ModelInfo,
|
|
1
|
+
import { a as IProviderAdapter, l as CompletionRequest, m as CompletionResponse, k as CompletionChunk, M as ModelInfo, d as TranscriptionRequest, e as TranscriptionResponse, f as SynthesisRequest, A as AudioChunk, V as VisionRequest, g as VisionResponse, h as ImageGenRequest, i as ImageGenResponse } from '../adapters-S96Ka9wt.mjs';
|
|
2
2
|
import '../rag-La_Bo-J8.mjs';
|
|
3
3
|
import '../logger-DxvKliuk.mjs';
|
|
4
4
|
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as IProviderAdapter, l as CompletionRequest, m as CompletionResponse, k as CompletionChunk, M as ModelInfo,
|
|
1
|
+
import { a as IProviderAdapter, l as CompletionRequest, m as CompletionResponse, k as CompletionChunk, M as ModelInfo, d as TranscriptionRequest, e as TranscriptionResponse, f as SynthesisRequest, A as AudioChunk, V as VisionRequest, g as VisionResponse, h as ImageGenRequest, i as ImageGenResponse } from '../adapters-DHQOGl8Y.js';
|
|
2
2
|
import '../rag-La_Bo-J8.js';
|
|
3
3
|
import '../logger-DxvKliuk.js';
|
|
4
4
|
|
|
@@ -363,4 +363,4 @@ interface IProviderAdapter {
|
|
|
363
363
|
healthCheck(): Promise<boolean>;
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
export { type AudioChunk as A, type ContextWindow as C, type IToolDefinition as I, type ModelInfo as M, type NormalizedMessage as N, ShortTermMemoryRegistry as S, type
|
|
366
|
+
export { type AudioChunk as A, type ContextWindow as C, type IToolDefinition as I, type ModelInfo as M, type NormalizedMessage as N, ShortTermMemoryRegistry as S, type Turn as T, type VisionRequest as V, type IProviderAdapter as a, type IContextStrategy as b, type IScratchpadAdapter as c, type TranscriptionRequest as d, type TranscriptionResponse as e, type SynthesisRequest as f, type VisionResponse as g, type ImageGenRequest as h, type ImageGenResponse as i, type ContentBlock as j, type CompletionChunk as k, type CompletionRequest as l, type CompletionResponse as m, type IStorageAdapter as n, type STMItem as o, type STMRegistryConfig as p, type TokenUsage as q, type ToolCall as r, type ToolContext as s, type ToolResult as t };
|
|
@@ -363,4 +363,4 @@ interface IProviderAdapter {
|
|
|
363
363
|
healthCheck(): Promise<boolean>;
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
export { type AudioChunk as A, type ContextWindow as C, type IToolDefinition as I, type ModelInfo as M, type NormalizedMessage as N, ShortTermMemoryRegistry as S, type
|
|
366
|
+
export { type AudioChunk as A, type ContextWindow as C, type IToolDefinition as I, type ModelInfo as M, type NormalizedMessage as N, ShortTermMemoryRegistry as S, type Turn as T, type VisionRequest as V, type IProviderAdapter as a, type IContextStrategy as b, type IScratchpadAdapter as c, type TranscriptionRequest as d, type TranscriptionResponse as e, type SynthesisRequest as f, type VisionResponse as g, type ImageGenRequest as h, type ImageGenResponse as i, type ContentBlock as j, type CompletionChunk as k, type CompletionRequest as l, type CompletionResponse as m, type IStorageAdapter as n, type STMItem as o, type STMRegistryConfig as p, type TokenUsage as q, type ToolCall as r, type ToolContext as s, type ToolResult as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as IToolDefinition, a as IProviderAdapter, b as IContextStrategy, S as ShortTermMemoryRegistry, c as IScratchpadAdapter } from './adapters-
|
|
1
|
+
import { I as IToolDefinition, a as IProviderAdapter, b as IContextStrategy, S as ShortTermMemoryRegistry, c as IScratchpadAdapter, T as Turn } from './adapters-S96Ka9wt.mjs';
|
|
2
2
|
import { I as ILogger } from './logger-DxvKliuk.mjs';
|
|
3
3
|
import { I as ISkill } from './skills-Y6D7zSSw.mjs';
|
|
4
4
|
import { I as IRAGAdapter } from './rag-La_Bo-J8.mjs';
|
|
@@ -102,6 +102,67 @@ interface MCPJsonRpcResponse {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
interface Goal {
|
|
106
|
+
id: string;
|
|
107
|
+
statement: string;
|
|
108
|
+
/** High-level sub-goals decomposed from the main statement */
|
|
109
|
+
decomposition: string[];
|
|
110
|
+
successCriteria: string[];
|
|
111
|
+
injectionFrequency: 'always' | 'every_N_turns' | 'on_compression';
|
|
112
|
+
injectionPosition: 'system_prompt' | 'pre_turn';
|
|
113
|
+
/** Sub-goals already completed — updated via `markSubGoalDone()` */
|
|
114
|
+
completedSubGoals?: string[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* GoalInjector keeps the original task objective visible throughout the ReAct loop,
|
|
118
|
+
* preventing goal drift after many tool calls and context compressions.
|
|
119
|
+
*
|
|
120
|
+
* Usage in SessionManager:
|
|
121
|
+
* - For `system_prompt` position: call `injectInto(prompt)` which appends the goal block.
|
|
122
|
+
* - For `pre_turn` position: call `getFormattedBlock()` and push as a system message.
|
|
123
|
+
*/
|
|
124
|
+
declare class GoalInjector {
|
|
125
|
+
private goal;
|
|
126
|
+
private turnsSinceInjection;
|
|
127
|
+
constructor(goal: Goal);
|
|
128
|
+
/**
|
|
129
|
+
* Returns the formatted `[CURRENT GOAL]` block string — without caring about
|
|
130
|
+
* where it will be placed. Callers decide whether to append to a system prompt
|
|
131
|
+
* or push as a separate message.
|
|
132
|
+
*/
|
|
133
|
+
getFormattedBlock(): string;
|
|
134
|
+
/**
|
|
135
|
+
* Appends the goal block to the given prompt string (for `system_prompt` position).
|
|
136
|
+
* For `pre_turn` position, use `getFormattedBlock()` directly.
|
|
137
|
+
*
|
|
138
|
+
* @param prompt - The existing system prompt to append to.
|
|
139
|
+
*/
|
|
140
|
+
injectInto(prompt: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* Returns true when the goal should be re-injected this turn,
|
|
143
|
+
* based on `injectionFrequency`.
|
|
144
|
+
*
|
|
145
|
+
* @param turnIndex - The current turn index in the ReAct loop (0-based)
|
|
146
|
+
* @param compressionOccurred - Whether context was compressed this iteration
|
|
147
|
+
* @param injectionN - The N for 'every_N_turns' frequency (default: 3)
|
|
148
|
+
*/
|
|
149
|
+
shouldInjectThisTurn(turnIndex: number, compressionOccurred?: boolean, injectionN?: number): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Updates the goal with new sub-goal decomposition and success criteria,
|
|
152
|
+
* typically populated by the mini-planning LLM call.
|
|
153
|
+
*/
|
|
154
|
+
updateDecomposition(decomposition: string[], successCriteria?: string[]): void;
|
|
155
|
+
/**
|
|
156
|
+
* Marks a sub-goal as completed so it moves to the "completed" section
|
|
157
|
+
* in subsequent injections.
|
|
158
|
+
*/
|
|
159
|
+
markSubGoalDone(subGoal: string): void;
|
|
160
|
+
/** Returns a snapshot of the current goal state (safe to store in context.metadata). */
|
|
161
|
+
getGoal(): Goal;
|
|
162
|
+
/** Increments the internal turn counter (used for `every_N_turns` frequency). */
|
|
163
|
+
incrementTurn(): void;
|
|
164
|
+
}
|
|
165
|
+
|
|
105
166
|
interface ToolResponseEvaluation {
|
|
106
167
|
relevanceScore: number;
|
|
107
168
|
sizeClass: 'small' | 'medium' | 'large' | 'oversized';
|
|
@@ -160,6 +221,22 @@ interface ToolExecutionBudget {
|
|
|
160
221
|
/** Maximum simultaneous parallel tool executions (default: unlimited) */
|
|
161
222
|
maxConcurrentCalls?: number;
|
|
162
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Result returned by a `goalVerifier` callback or the built-in `successCriteria` checker.
|
|
226
|
+
*
|
|
227
|
+
* @since 1.5.0
|
|
228
|
+
*/
|
|
229
|
+
interface GoalVerifierResult {
|
|
230
|
+
/** Whether the original goal was fully achieved */
|
|
231
|
+
achieved: boolean;
|
|
232
|
+
/**
|
|
233
|
+
* When `achieved` is false, describes what is still missing.
|
|
234
|
+
* This text is injected as a follow-up user message to continue the loop.
|
|
235
|
+
*/
|
|
236
|
+
missing?: string;
|
|
237
|
+
/** Short human-readable reason for the verdict — surfaced in trace events */
|
|
238
|
+
reason?: string;
|
|
239
|
+
}
|
|
163
240
|
/** Configuration for a lemura Session */
|
|
164
241
|
interface SessionConfig {
|
|
165
242
|
/** The provider adapter to use */
|
|
@@ -215,13 +292,20 @@ interface SessionConfig {
|
|
|
215
292
|
continuationStrategy?: 'sequential' | 'parallel' | 'conditional';
|
|
216
293
|
/** Enable goal planning */
|
|
217
294
|
enableGoalPlanning?: boolean;
|
|
295
|
+
/**
|
|
296
|
+
* Enable post-run goal verification (Option A + C).
|
|
297
|
+
* When true, Lemura checks whether the goal was actually achieved after each stop.
|
|
298
|
+
* Requires `enableGoalPlanning` to also be true. Defaults to true.
|
|
299
|
+
* @since 1.5.0
|
|
300
|
+
*/
|
|
301
|
+
enableGoalVerification?: boolean;
|
|
218
302
|
goalInjectionFrequency?: 'always' | 'every_N_turns' | 'on_compression';
|
|
219
303
|
goalInjectionPosition?: 'system_prompt' | 'pre_turn';
|
|
220
304
|
/** Skill budget — max tokens the skill injection block may consume */
|
|
221
305
|
skillTokenBudget?: number;
|
|
222
306
|
/**
|
|
223
307
|
* Maximum tokens the provider may generate per completion call.
|
|
224
|
-
* Defaults to
|
|
308
|
+
* Defaults to 4 000 when not set. This is separate from `maxTokens`
|
|
225
309
|
* which controls the total context window size.
|
|
226
310
|
*/
|
|
227
311
|
maxCompletionTokens?: number;
|
|
@@ -255,6 +339,27 @@ interface SessionConfig {
|
|
|
255
339
|
toolRegistryTimeoutMs?: number;
|
|
256
340
|
/** Callback for granular trace events (planning, budgets, tools, etc.) */
|
|
257
341
|
onTrace?: (event: TraceEvent) => void;
|
|
342
|
+
/**
|
|
343
|
+
* Optional callback invoked after the ReAct loop reaches a `stop` finish reason.
|
|
344
|
+
*
|
|
345
|
+
* Return `{ achieved: false, missing: '...' }` to continue the loop with the
|
|
346
|
+
* missing work injected as a follow-up user message (capped at one retry).
|
|
347
|
+
* Return `{ achieved: true }` to stop normally.
|
|
348
|
+
*
|
|
349
|
+
* Only called when `enableGoalPlanning` is `true` and a goal statement exists.
|
|
350
|
+
* When omitted and `successCriteria` is non-empty, Lemura falls back to a
|
|
351
|
+
* built-in LLM-based check against those criteria.
|
|
352
|
+
*
|
|
353
|
+
* @since 1.5.0
|
|
354
|
+
* @example
|
|
355
|
+
* goalVerifier: async (goal, turns) => {
|
|
356
|
+
* const last = turns.at(-1)?.content ?? '';
|
|
357
|
+
* return last.includes('DONE')
|
|
358
|
+
* ? { achieved: true }
|
|
359
|
+
* : { achieved: false, missing: 'Final DONE marker not found in output' };
|
|
360
|
+
* }
|
|
361
|
+
*/
|
|
362
|
+
goalVerifier?: (goal: Goal, turns: Turn[]) => Promise<GoalVerifierResult> | GoalVerifierResult;
|
|
258
363
|
/**
|
|
259
364
|
* MCP (Model Context Protocol) server configurations.
|
|
260
365
|
* Each server is connected at session construction, its tools are discovered
|
|
@@ -271,7 +376,7 @@ interface SessionConfig {
|
|
|
271
376
|
/** Rich trace event for observability */
|
|
272
377
|
interface TraceEvent {
|
|
273
378
|
sessionId?: string;
|
|
274
|
-
type: 'planning' | 'budget' | 'tool_call' | 'tool_result' | 'thinking' | 'system' | 'compression' | 'error' | 'skill';
|
|
379
|
+
type: 'planning' | 'budget' | 'tool_call' | 'tool_result' | 'thinking' | 'system' | 'compression' | 'error' | 'skill' | 'verification';
|
|
275
380
|
name: string;
|
|
276
381
|
input?: any;
|
|
277
382
|
output?: any;
|
|
@@ -281,4 +386,4 @@ interface TraceEvent {
|
|
|
281
386
|
metadata?: Record<string, any>;
|
|
282
387
|
}
|
|
283
388
|
|
|
284
|
-
export type
|
|
389
|
+
export { type Goal as G, type IToolResponseProcessor as I, type MCPServerConfig as M, type SessionConfig as S, type ToolResponseEvaluation as T, type MCPToolDefinition as a, GoalInjector as b, type GoalVerifierResult as c, type MCPJsonRpcRequest as d, type MCPJsonRpcResponse as e, type MCPTransportType as f, type MediaConfig as g, type ToolDecision as h, type ToolExecutionBudget as i, type ToolFirewallConfig as j, type ToolFirewallRule as k, type TraceEvent as l };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as IToolDefinition, a as IProviderAdapter, b as IContextStrategy, S as ShortTermMemoryRegistry, c as IScratchpadAdapter } from './adapters-
|
|
1
|
+
import { I as IToolDefinition, a as IProviderAdapter, b as IContextStrategy, S as ShortTermMemoryRegistry, c as IScratchpadAdapter, T as Turn } from './adapters-DHQOGl8Y.js';
|
|
2
2
|
import { I as ILogger } from './logger-DxvKliuk.js';
|
|
3
3
|
import { I as ISkill } from './skills-Y6D7zSSw.js';
|
|
4
4
|
import { I as IRAGAdapter } from './rag-La_Bo-J8.js';
|
|
@@ -102,6 +102,67 @@ interface MCPJsonRpcResponse {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
interface Goal {
|
|
106
|
+
id: string;
|
|
107
|
+
statement: string;
|
|
108
|
+
/** High-level sub-goals decomposed from the main statement */
|
|
109
|
+
decomposition: string[];
|
|
110
|
+
successCriteria: string[];
|
|
111
|
+
injectionFrequency: 'always' | 'every_N_turns' | 'on_compression';
|
|
112
|
+
injectionPosition: 'system_prompt' | 'pre_turn';
|
|
113
|
+
/** Sub-goals already completed — updated via `markSubGoalDone()` */
|
|
114
|
+
completedSubGoals?: string[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* GoalInjector keeps the original task objective visible throughout the ReAct loop,
|
|
118
|
+
* preventing goal drift after many tool calls and context compressions.
|
|
119
|
+
*
|
|
120
|
+
* Usage in SessionManager:
|
|
121
|
+
* - For `system_prompt` position: call `injectInto(prompt)` which appends the goal block.
|
|
122
|
+
* - For `pre_turn` position: call `getFormattedBlock()` and push as a system message.
|
|
123
|
+
*/
|
|
124
|
+
declare class GoalInjector {
|
|
125
|
+
private goal;
|
|
126
|
+
private turnsSinceInjection;
|
|
127
|
+
constructor(goal: Goal);
|
|
128
|
+
/**
|
|
129
|
+
* Returns the formatted `[CURRENT GOAL]` block string — without caring about
|
|
130
|
+
* where it will be placed. Callers decide whether to append to a system prompt
|
|
131
|
+
* or push as a separate message.
|
|
132
|
+
*/
|
|
133
|
+
getFormattedBlock(): string;
|
|
134
|
+
/**
|
|
135
|
+
* Appends the goal block to the given prompt string (for `system_prompt` position).
|
|
136
|
+
* For `pre_turn` position, use `getFormattedBlock()` directly.
|
|
137
|
+
*
|
|
138
|
+
* @param prompt - The existing system prompt to append to.
|
|
139
|
+
*/
|
|
140
|
+
injectInto(prompt: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* Returns true when the goal should be re-injected this turn,
|
|
143
|
+
* based on `injectionFrequency`.
|
|
144
|
+
*
|
|
145
|
+
* @param turnIndex - The current turn index in the ReAct loop (0-based)
|
|
146
|
+
* @param compressionOccurred - Whether context was compressed this iteration
|
|
147
|
+
* @param injectionN - The N for 'every_N_turns' frequency (default: 3)
|
|
148
|
+
*/
|
|
149
|
+
shouldInjectThisTurn(turnIndex: number, compressionOccurred?: boolean, injectionN?: number): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Updates the goal with new sub-goal decomposition and success criteria,
|
|
152
|
+
* typically populated by the mini-planning LLM call.
|
|
153
|
+
*/
|
|
154
|
+
updateDecomposition(decomposition: string[], successCriteria?: string[]): void;
|
|
155
|
+
/**
|
|
156
|
+
* Marks a sub-goal as completed so it moves to the "completed" section
|
|
157
|
+
* in subsequent injections.
|
|
158
|
+
*/
|
|
159
|
+
markSubGoalDone(subGoal: string): void;
|
|
160
|
+
/** Returns a snapshot of the current goal state (safe to store in context.metadata). */
|
|
161
|
+
getGoal(): Goal;
|
|
162
|
+
/** Increments the internal turn counter (used for `every_N_turns` frequency). */
|
|
163
|
+
incrementTurn(): void;
|
|
164
|
+
}
|
|
165
|
+
|
|
105
166
|
interface ToolResponseEvaluation {
|
|
106
167
|
relevanceScore: number;
|
|
107
168
|
sizeClass: 'small' | 'medium' | 'large' | 'oversized';
|
|
@@ -160,6 +221,22 @@ interface ToolExecutionBudget {
|
|
|
160
221
|
/** Maximum simultaneous parallel tool executions (default: unlimited) */
|
|
161
222
|
maxConcurrentCalls?: number;
|
|
162
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Result returned by a `goalVerifier` callback or the built-in `successCriteria` checker.
|
|
226
|
+
*
|
|
227
|
+
* @since 1.5.0
|
|
228
|
+
*/
|
|
229
|
+
interface GoalVerifierResult {
|
|
230
|
+
/** Whether the original goal was fully achieved */
|
|
231
|
+
achieved: boolean;
|
|
232
|
+
/**
|
|
233
|
+
* When `achieved` is false, describes what is still missing.
|
|
234
|
+
* This text is injected as a follow-up user message to continue the loop.
|
|
235
|
+
*/
|
|
236
|
+
missing?: string;
|
|
237
|
+
/** Short human-readable reason for the verdict — surfaced in trace events */
|
|
238
|
+
reason?: string;
|
|
239
|
+
}
|
|
163
240
|
/** Configuration for a lemura Session */
|
|
164
241
|
interface SessionConfig {
|
|
165
242
|
/** The provider adapter to use */
|
|
@@ -215,13 +292,20 @@ interface SessionConfig {
|
|
|
215
292
|
continuationStrategy?: 'sequential' | 'parallel' | 'conditional';
|
|
216
293
|
/** Enable goal planning */
|
|
217
294
|
enableGoalPlanning?: boolean;
|
|
295
|
+
/**
|
|
296
|
+
* Enable post-run goal verification (Option A + C).
|
|
297
|
+
* When true, Lemura checks whether the goal was actually achieved after each stop.
|
|
298
|
+
* Requires `enableGoalPlanning` to also be true. Defaults to true.
|
|
299
|
+
* @since 1.5.0
|
|
300
|
+
*/
|
|
301
|
+
enableGoalVerification?: boolean;
|
|
218
302
|
goalInjectionFrequency?: 'always' | 'every_N_turns' | 'on_compression';
|
|
219
303
|
goalInjectionPosition?: 'system_prompt' | 'pre_turn';
|
|
220
304
|
/** Skill budget — max tokens the skill injection block may consume */
|
|
221
305
|
skillTokenBudget?: number;
|
|
222
306
|
/**
|
|
223
307
|
* Maximum tokens the provider may generate per completion call.
|
|
224
|
-
* Defaults to
|
|
308
|
+
* Defaults to 4 000 when not set. This is separate from `maxTokens`
|
|
225
309
|
* which controls the total context window size.
|
|
226
310
|
*/
|
|
227
311
|
maxCompletionTokens?: number;
|
|
@@ -255,6 +339,27 @@ interface SessionConfig {
|
|
|
255
339
|
toolRegistryTimeoutMs?: number;
|
|
256
340
|
/** Callback for granular trace events (planning, budgets, tools, etc.) */
|
|
257
341
|
onTrace?: (event: TraceEvent) => void;
|
|
342
|
+
/**
|
|
343
|
+
* Optional callback invoked after the ReAct loop reaches a `stop` finish reason.
|
|
344
|
+
*
|
|
345
|
+
* Return `{ achieved: false, missing: '...' }` to continue the loop with the
|
|
346
|
+
* missing work injected as a follow-up user message (capped at one retry).
|
|
347
|
+
* Return `{ achieved: true }` to stop normally.
|
|
348
|
+
*
|
|
349
|
+
* Only called when `enableGoalPlanning` is `true` and a goal statement exists.
|
|
350
|
+
* When omitted and `successCriteria` is non-empty, Lemura falls back to a
|
|
351
|
+
* built-in LLM-based check against those criteria.
|
|
352
|
+
*
|
|
353
|
+
* @since 1.5.0
|
|
354
|
+
* @example
|
|
355
|
+
* goalVerifier: async (goal, turns) => {
|
|
356
|
+
* const last = turns.at(-1)?.content ?? '';
|
|
357
|
+
* return last.includes('DONE')
|
|
358
|
+
* ? { achieved: true }
|
|
359
|
+
* : { achieved: false, missing: 'Final DONE marker not found in output' };
|
|
360
|
+
* }
|
|
361
|
+
*/
|
|
362
|
+
goalVerifier?: (goal: Goal, turns: Turn[]) => Promise<GoalVerifierResult> | GoalVerifierResult;
|
|
258
363
|
/**
|
|
259
364
|
* MCP (Model Context Protocol) server configurations.
|
|
260
365
|
* Each server is connected at session construction, its tools are discovered
|
|
@@ -271,7 +376,7 @@ interface SessionConfig {
|
|
|
271
376
|
/** Rich trace event for observability */
|
|
272
377
|
interface TraceEvent {
|
|
273
378
|
sessionId?: string;
|
|
274
|
-
type: 'planning' | 'budget' | 'tool_call' | 'tool_result' | 'thinking' | 'system' | 'compression' | 'error' | 'skill';
|
|
379
|
+
type: 'planning' | 'budget' | 'tool_call' | 'tool_result' | 'thinking' | 'system' | 'compression' | 'error' | 'skill' | 'verification';
|
|
275
380
|
name: string;
|
|
276
381
|
input?: any;
|
|
277
382
|
output?: any;
|
|
@@ -281,4 +386,4 @@ interface TraceEvent {
|
|
|
281
386
|
metadata?: Record<string, any>;
|
|
282
387
|
}
|
|
283
388
|
|
|
284
|
-
export type
|
|
389
|
+
export { type Goal as G, type IToolResponseProcessor as I, type MCPServerConfig as M, type SessionConfig as S, type ToolResponseEvaluation as T, type MCPToolDefinition as a, GoalInjector as b, type GoalVerifierResult as c, type MCPJsonRpcRequest as d, type MCPJsonRpcResponse as e, type MCPTransportType as f, type MediaConfig as g, type ToolDecision as h, type ToolExecutionBudget as i, type ToolFirewallConfig as j, type ToolFirewallRule as k, type TraceEvent as l };
|
package/dist/context/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as IContextStrategy, C as ContextWindow, a as IProviderAdapter, n as IStorageAdapter, c as IScratchpadAdapter } from '../adapters-
|
|
2
|
-
export { p as STMRegistryConfig, S as ShortTermMemoryRegistry } from '../adapters-
|
|
1
|
+
import { b as IContextStrategy, C as ContextWindow, a as IProviderAdapter, n as IStorageAdapter, c as IScratchpadAdapter } from '../adapters-S96Ka9wt.mjs';
|
|
2
|
+
export { p as STMRegistryConfig, S as ShortTermMemoryRegistry } from '../adapters-S96Ka9wt.mjs';
|
|
3
3
|
import '../rag-La_Bo-J8.mjs';
|
|
4
4
|
import '../logger-DxvKliuk.mjs';
|
|
5
5
|
|
package/dist/context/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as IContextStrategy, C as ContextWindow, a as IProviderAdapter, n as IStorageAdapter, c as IScratchpadAdapter } from '../adapters-
|
|
2
|
-
export { p as STMRegistryConfig, S as ShortTermMemoryRegistry } from '../adapters-
|
|
1
|
+
import { b as IContextStrategy, C as ContextWindow, a as IProviderAdapter, n as IStorageAdapter, c as IScratchpadAdapter } from '../adapters-DHQOGl8Y.js';
|
|
2
|
+
export { p as STMRegistryConfig, S as ShortTermMemoryRegistry } from '../adapters-DHQOGl8Y.js';
|
|
3
3
|
import '../rag-La_Bo-J8.js';
|
|
4
4
|
import '../logger-DxvKliuk.js';
|
|
5
5
|
|