@sschepis/oboto-agent 0.1.5 → 0.2.2

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/dist/index.d.ts CHANGED
@@ -1,14 +1,22 @@
1
- import { Session, ConversationMessage } from '@sschepis/as-agent';
2
- import { BaseProvider } from '@sschepis/llm-wrapper';
3
- import { Router, BranchNode } from '@sschepis/swiss-army-tool';
1
+ import * as _sschepis_as_agent from '@sschepis/as-agent';
2
+ import { Session, PermissionPolicy, PermissionPrompter, CompactionConfig, HookRunner, AgentRuntime, ConversationMessage, UsageTracker, TokenUsage, HookRunResult, SlashCommandSpec, PermissionOutcome, PermissionMode, CompactionResult, UsageCostEstimate, ModelPricing as ModelPricing$1 } from '@sschepis/as-agent';
3
+ import * as _sschepis_llm_wrapper from '@sschepis/llm-wrapper';
4
+ import { BaseProvider, LLMRouter, HealthState, StandardChatParams } from '@sschepis/llm-wrapper';
5
+ import { Router, Middleware, BranchNode, DynamicBranchNode, SessionManager } from '@sschepis/swiss-army-tool';
6
+ import { MiddlewareHooks, ModelPricing, BudgetConfig, RateLimitConfig, EmbeddingProvider, VectorStore, VectorSearchResult, LScriptRuntime, LScriptFunction, ExecutionResult, RAGPipeline, CostTracker, ToolDefinition, ChatMessage, LLMProvider, Pipeline, PipelineResult } from '@sschepis/lmscript';
7
+ import * as zod from 'zod';
4
8
  import { z } from 'zod';
5
- import { ToolDefinition, ChatMessage, LLMProvider, LScriptRuntime, LScriptFunction } from '@sschepis/lmscript';
6
9
 
10
+ /**
11
+ * A provider-like object that has `chat()` and `stream()` methods.
12
+ * Accepts both llm-wrapper `BaseProvider` and `LLMRouter`.
13
+ */
14
+ type ProviderLike$1 = BaseProvider | LLMRouter;
7
15
  interface ObotoAgentConfig {
8
16
  /** Small, fast model for triage and summarization (e.g. Ollama, LMStudio) */
9
- localModel: BaseProvider;
17
+ localModel: ProviderLike$1;
10
18
  /** Powerful model for complex reasoning (e.g. Anthropic, OpenAI, Gemini) */
11
- remoteModel: BaseProvider;
19
+ remoteModel: ProviderLike$1;
12
20
  /** Model identifier for the local provider (e.g. "llama3:8b") */
13
21
  localModelName: string;
14
22
  /** Model identifier for the remote provider (e.g. "claude-sonnet-4-20250514") */
@@ -25,8 +33,48 @@ interface ObotoAgentConfig {
25
33
  systemPrompt?: string;
26
34
  /** Called with each token chunk during LLM streaming. Enables real-time output. */
27
35
  onToken?: (token: string) => void;
36
+ /** Middleware hooks for the lmscript execution lifecycle */
37
+ middleware?: MiddlewareHooks[];
38
+ /** Model pricing map for cost tracking (model name -> per-1k-token costs) */
39
+ modelPricing?: ModelPricing;
40
+ /** Budget limits for the remote runtime */
41
+ budget?: BudgetConfig;
42
+ /** Rate limiting configuration for remote API calls */
43
+ rateLimit?: RateLimitConfig;
44
+ /** TTL in ms for execution cache. 0 or undefined disables caching. Default: 0 */
45
+ cacheTtlMs?: number;
46
+ /** TTL in ms for triage cache. Separate from main cache. Default: 60000 */
47
+ triageCacheTtlMs?: number;
48
+ /** Middleware to apply to the swiss-army-tool Router */
49
+ toolMiddleware?: Middleware[];
50
+ /** Embedding provider for RAG-augmented conversation retrieval */
51
+ embeddingProvider?: EmbeddingProvider;
52
+ /** Custom vector store for RAG. Defaults to MemoryVectorStore. */
53
+ vectorStore?: VectorStore;
54
+ /** Number of past context chunks to retrieve via RAG. Default: 5 */
55
+ ragTopK?: number;
56
+ /** Minimum similarity score for RAG retrieval (0-1). Default: 0.3 */
57
+ ragMinScore?: number;
58
+ /** Embedding model identifier for RAG. Default: provider's default */
59
+ ragEmbeddingModel?: string;
60
+ /** Whether to automatically index conversation messages for RAG. Default: true */
61
+ ragAutoIndex?: boolean;
62
+ /** Whether to index tool execution results for RAG. Default: true */
63
+ ragIndexToolResults?: boolean;
64
+ /** Custom formatter for RAG-retrieved context */
65
+ ragFormatContext?: (results: VectorSearchResult[]) => string;
66
+ /** Permission policy for tool authorization (from @sschepis/as-agent) */
67
+ permissionPolicy?: PermissionPolicy;
68
+ /** Permission prompter for interactive permission decisions */
69
+ permissionPrompter?: PermissionPrompter;
70
+ /** Session compaction config — auto-compact when estimated tokens exceed limit */
71
+ compactionConfig?: CompactionConfig;
72
+ /** Hook runner for pre/post tool-use shell hooks */
73
+ hookRunner?: HookRunner;
74
+ /** as-agent Wasm runtime for slash commands and utilities */
75
+ agentRuntime?: AgentRuntime;
28
76
  }
29
- type AgentEventType = "user_input" | "agent_thought" | "token" | "triage_result" | "tool_execution_start" | "tool_execution_complete" | "tool_round_complete" | "state_updated" | "interruption" | "error" | "turn_complete";
77
+ type AgentEventType = "user_input" | "agent_thought" | "token" | "triage_result" | "tool_execution_start" | "tool_execution_complete" | "tool_round_complete" | "state_updated" | "interruption" | "error" | "cost_update" | "turn_complete" | "permission_denied" | "session_compacted" | "hook_denied" | "hook_message" | "router_event" | "slash_command";
30
78
  interface AgentEvent<T = unknown> {
31
79
  type: AgentEventType;
32
80
  payload: T;
@@ -48,21 +96,555 @@ interface ToolExecutionEvent {
48
96
  durationMs?: number;
49
97
  }
50
98
 
99
+ interface ConversationRAGConfig {
100
+ /** The embedding provider (e.g. OpenAI, local model) */
101
+ embeddingProvider: EmbeddingProvider;
102
+ /** Optional custom vector store. Defaults to MemoryVectorStore. */
103
+ vectorStore?: VectorStore;
104
+ /** Number of past context chunks to retrieve. Default: 5 */
105
+ topK?: number;
106
+ /** Minimum similarity score (0-1). Default: 0.3 */
107
+ minScore?: number;
108
+ /** Embedding model identifier. Default: provider's default */
109
+ embeddingModel?: string;
110
+ /**
111
+ * Whether to automatically index conversation messages as they're added.
112
+ * Default: true
113
+ */
114
+ autoIndex?: boolean;
115
+ /**
116
+ * Whether to index tool execution results.
117
+ * Default: true
118
+ */
119
+ indexToolResults?: boolean;
120
+ /** Maximum characters per indexed chunk. Longer messages are split. Default: 2000 */
121
+ maxChunkSize?: number;
122
+ /**
123
+ * Custom context formatter for retrieved documents.
124
+ * Default: numbered list with scores.
125
+ */
126
+ formatContext?: (results: VectorSearchResult[]) => string;
127
+ }
128
+ interface RAGRetrievalResult {
129
+ /** Retrieved context string ready for prompt injection */
130
+ context: string;
131
+ /** Raw search results */
132
+ results: VectorSearchResult[];
133
+ /** Number of documents in the store */
134
+ totalDocuments: number;
135
+ }
136
+ /**
137
+ * ConversationRAG bridges lmscript's RAG pipeline with the agent's
138
+ * conversation history and tool results.
139
+ *
140
+ * It maintains a vector store of conversation chunks and can retrieve
141
+ * relevant past context for new queries. This is useful for:
142
+ * - Long-running agent sessions where early context is pruned
143
+ * - Multi-topic conversations where relevant past decisions need retrieval
144
+ * - Tool result recall without re-execution
145
+ *
146
+ * ```ts
147
+ * const rag = new ConversationRAG(runtime, {
148
+ * embeddingProvider: openaiEmbeddings,
149
+ * topK: 5,
150
+ * minScore: 0.3,
151
+ * });
152
+ *
153
+ * // Index existing session history
154
+ * await rag.indexSession(session);
155
+ *
156
+ * // Retrieve relevant context for a new query
157
+ * const { context } = await rag.retrieve("What database schema did we discuss?");
158
+ *
159
+ * // Or use RAG-augmented execution directly
160
+ * const result = await rag.executeWithContext(myFn, input, "search query");
161
+ * ```
162
+ */
163
+ declare class ConversationRAG {
164
+ private vectorStore;
165
+ private embeddingProvider;
166
+ private ragPipeline;
167
+ private config;
168
+ private indexedMessageCount;
169
+ private runtime;
170
+ constructor(runtime: LScriptRuntime, config: ConversationRAGConfig);
171
+ /**
172
+ * Index an entire as-agent Session into the vector store.
173
+ * Each message becomes one or more chunks (split by maxChunkSize).
174
+ */
175
+ indexSession(session: Session): Promise<number>;
176
+ /**
177
+ * Index a single conversation message.
178
+ * Call this after adding a message to the session for real-time indexing.
179
+ */
180
+ indexMessage(msg: ConversationMessage, messageIndex?: number): Promise<void>;
181
+ /**
182
+ * Index a tool execution result for later retrieval.
183
+ */
184
+ indexToolResult(command: string, kwargs: Record<string, unknown>, result: string): Promise<void>;
185
+ /**
186
+ * Retrieve relevant past context for a query.
187
+ * Returns formatted context string and raw results.
188
+ */
189
+ retrieve(query: string): Promise<RAGRetrievalResult>;
190
+ /**
191
+ * Execute an lmscript function with RAG-augmented context from the
192
+ * conversation history.
193
+ *
194
+ * This is the primary integration point — it uses lmscript's RAGPipeline
195
+ * to inject relevant past conversation into the function's system prompt.
196
+ */
197
+ executeWithContext<I, O extends zod.ZodType>(fn: LScriptFunction<I, O>, input: I, queryText?: string): Promise<{
198
+ result: ExecutionResult<zod.infer<O>>;
199
+ retrievedDocuments: VectorSearchResult[];
200
+ context: string;
201
+ }>;
202
+ /** Get the number of indexed messages. */
203
+ get messageCount(): number;
204
+ /** Get the total number of document chunks in the vector store. */
205
+ documentCount(): Promise<number>;
206
+ /** Clear the vector store and reset counters. */
207
+ clear(): Promise<void>;
208
+ /** Get the underlying vector store (for advanced usage). */
209
+ getVectorStore(): VectorStore;
210
+ /** Get the underlying RAG pipeline (for advanced usage). */
211
+ getRagPipeline(): RAGPipeline;
212
+ private messageToChunks;
213
+ private splitChunks;
214
+ }
215
+
51
216
  type EventHandler$1 = (event: AgentEvent) => void;
217
+ /**
218
+ * Platform-agnostic typed event bus.
219
+ * Uses a plain Map instead of Node.js EventEmitter for browser/Deno/Bun compatibility.
220
+ */
221
+ declare class AgentEventBus {
222
+ private listeners;
223
+ /** Subscribe to an event type. Returns an unsubscribe function. */
224
+ on(type: AgentEventType, handler: EventHandler$1): () => void;
225
+ /** Unsubscribe a handler from an event type. */
226
+ off(type: AgentEventType, handler: EventHandler$1): void;
227
+ /** Subscribe to an event type for a single emission. */
228
+ once(type: AgentEventType, handler: EventHandler$1): () => void;
229
+ /** Emit an event to all subscribers. */
230
+ emit(type: AgentEventType, payload: unknown): void;
231
+ /** Remove all listeners for all event types. */
232
+ removeAllListeners(): void;
233
+ }
234
+
235
+ /**
236
+ * as-agent-features.ts — Deep integration of @sschepis/as-agent's advanced features.
237
+ *
238
+ * This module bridges the following as-agent subsystems into oboto-agent:
239
+ *
240
+ * 1. **Permissions** — PermissionPolicy + PermissionPrompter for tool authorization
241
+ * 2. **Session Compaction** — CompactionConfig for auto-compacting long sessions
242
+ * 3. **Hooks** — HookRunner for pre/post tool-use shell hooks
243
+ * 4. **Slash Commands** — AgentRuntime's slash command registry
244
+ * 5. **Usage Tracking** — UsageTracker bridge (detailed impl in Task 11)
245
+ */
246
+
247
+ /**
248
+ * Wraps an as-agent PermissionPolicy to provide tool-call authorization
249
+ * that integrates with the agent's event bus.
250
+ *
251
+ * Before each tool execution, `authorize()` is called. If the policy
252
+ * denies the call, a `permission_denied` event is emitted and the tool
253
+ * execution is skipped.
254
+ *
255
+ * ```ts
256
+ * const guard = new PermissionGuard(policy, prompter, bus);
257
+ * const outcome = guard.checkPermission("bash", '{"cmd":"rm -rf /"}');
258
+ * if (outcome.kind === "deny") { ... }
259
+ * ```
260
+ */
261
+ declare class PermissionGuard {
262
+ private policy;
263
+ private prompter;
264
+ private bus?;
265
+ constructor(policy: PermissionPolicy, prompter: PermissionPrompter | null, bus?: AgentEventBus | undefined);
266
+ /**
267
+ * Check whether a tool call is authorized.
268
+ * Emits `permission_denied` on the event bus if denied.
269
+ */
270
+ checkPermission(toolName: string, toolInput: string): PermissionOutcome;
271
+ /** Get the current active permission mode. */
272
+ get activeMode(): PermissionMode;
273
+ /** Get the required permission mode for a specific tool. */
274
+ requiredModeFor(toolName: string): PermissionMode;
275
+ }
276
+ /**
277
+ * Manages automatic and manual session compaction using as-agent's
278
+ * CompactionConfig. Compaction summarizes older messages to stay within
279
+ * token limits while preserving recent context.
280
+ *
281
+ * ```ts
282
+ * const compactor = new SessionCompactor(bus, {
283
+ * preserveRecentMessages: 10,
284
+ * maxEstimatedTokens: 100_000,
285
+ * });
286
+ *
287
+ * // Check and compact if needed
288
+ * const result = compactor.compactIfNeeded(session, estimatedTokens);
289
+ * ```
290
+ */
291
+ declare class SessionCompactor {
292
+ private config;
293
+ private bus?;
294
+ private compactionCount;
295
+ private totalRemovedMessages;
296
+ constructor(bus: AgentEventBus | undefined, config: CompactionConfig);
297
+ /**
298
+ * Check if the session needs compaction and perform it if so.
299
+ * Uses a simple heuristic: ~4 chars per token for estimation.
300
+ *
301
+ * Since the actual compaction logic lives in the Wasm runtime
302
+ * (ConversationRuntime.compact()), this method provides a JS-side
303
+ * implementation that creates a summary of older messages and
304
+ * preserves recent ones.
305
+ *
306
+ * Returns null if compaction is not needed.
307
+ */
308
+ compactIfNeeded(session: Session, estimatedTokens?: number): CompactionResult | null;
309
+ /**
310
+ * Force compaction of the session regardless of token count.
311
+ */
312
+ compact(session: Session): CompactionResult;
313
+ /** Get compaction statistics. */
314
+ get stats(): {
315
+ compactionCount: number;
316
+ totalRemovedMessages: number;
317
+ };
318
+ /** Update the compaction config at runtime. */
319
+ updateConfig(config: Partial<CompactionConfig>): void;
320
+ /** Estimate token count for a session (~4 chars per token). */
321
+ private estimateTokens;
322
+ }
323
+ /**
324
+ * Wraps an as-agent HookRunner and integrates it with the agent's
325
+ * event bus. Hooks are shell commands that run before and after
326
+ * tool executions, allowing external validation/transformation.
327
+ *
328
+ * ```ts
329
+ * const hooks = new HookIntegration(hookRunner, bus);
330
+ * const pre = hooks.runPreToolUse("bash", '{"cmd":"ls"}');
331
+ * if (pre.denied) { /* skip tool call *\/ }
332
+ *
333
+ * // After tool executes:
334
+ * const post = hooks.runPostToolUse("bash", '{"cmd":"ls"}', "file1\nfile2", false);
335
+ * ```
336
+ */
337
+ declare class HookIntegration {
338
+ private runner;
339
+ private bus?;
340
+ constructor(runner: HookRunner, bus?: AgentEventBus | undefined);
341
+ /**
342
+ * Run pre-tool-use hooks. If any hook denies the call,
343
+ * the tool execution should be skipped.
344
+ */
345
+ runPreToolUse(toolName: string, toolInput: string): HookRunResult;
346
+ /**
347
+ * Run post-tool-use hooks. These can log, transform, or audit
348
+ * tool results but cannot retroactively deny execution.
349
+ */
350
+ runPostToolUse(toolName: string, toolInput: string, toolOutput: string, isError: boolean): HookRunResult;
351
+ }
352
+ /**
353
+ * Bridges the as-agent Wasm runtime's slash command system with
354
+ * oboto-agent. The Wasm runtime provides 21 built-in slash commands
355
+ * (e.g. /help, /compact, /clear, /model, etc.).
356
+ *
357
+ * This class provides:
358
+ * - Access to command specs and help text from the Wasm runtime
359
+ * - An extensible registry for adding custom slash commands
360
+ * - Parsing and dispatching of slash command input
361
+ *
362
+ * ```ts
363
+ * const registry = new SlashCommandRegistry(agentRuntime);
364
+ * const specs = registry.getCommandSpecs();
365
+ * const help = registry.getHelpText();
366
+ *
367
+ * // Add custom commands
368
+ * registry.registerCommand({
369
+ * name: "status",
370
+ * summary: "Show agent status",
371
+ * argumentHint: "",
372
+ * resumeSupported: false,
373
+ * }, async (args) => "Agent is running");
374
+ * ```
375
+ */
376
+ declare class SlashCommandRegistry {
377
+ private customCommands;
378
+ private wasmRuntime?;
379
+ constructor(wasmRuntime?: AgentRuntime);
380
+ /**
381
+ * Get all slash command specs (built-in from Wasm + custom).
382
+ */
383
+ getCommandSpecs(): SlashCommandSpec[];
384
+ /**
385
+ * Get the full help text for all commands.
386
+ * Uses the Wasm runtime's formatted help if available.
387
+ */
388
+ getHelpText(): string;
389
+ /**
390
+ * Register a custom slash command.
391
+ */
392
+ registerCommand(spec: SlashCommandSpec, handler: (args: string) => string | Promise<string>): void;
393
+ /**
394
+ * Unregister a custom slash command.
395
+ */
396
+ unregisterCommand(name: string): boolean;
397
+ /**
398
+ * Parse a user input string to check if it's a slash command.
399
+ * Returns the command name and arguments, or null if not a command.
400
+ */
401
+ parseCommand(input: string): {
402
+ name: string;
403
+ args: string;
404
+ } | null;
405
+ /**
406
+ * Execute a custom slash command by name.
407
+ * Returns the command output, or null if the command is not found
408
+ * in the custom registry (it may be a built-in Wasm command).
409
+ */
410
+ executeCustomCommand(name: string, args: string): Promise<string | null>;
411
+ /**
412
+ * Check if a command name exists (either built-in or custom).
413
+ */
414
+ hasCommand(name: string): boolean;
415
+ /**
416
+ * Get only commands that support resume (useful for session restoration).
417
+ */
418
+ getResumeSupportedCommands(): SlashCommandSpec[];
419
+ }
420
+ /**
421
+ * A JS-side implementation of the as-agent UsageTracker interface.
422
+ * This adapter accumulates token usage across turns, matching the
423
+ * as-agent contract (inputTokens, outputTokens, cache tokens).
424
+ *
425
+ * The bridge to lmscript's CostTracker (which uses different field names)
426
+ * is handled in Task 11.
427
+ */
428
+ declare class AgentUsageTracker implements UsageTracker {
429
+ private turnUsages;
430
+ private currentTurn;
431
+ record(usage: TokenUsage): void;
432
+ currentTurnUsage(): TokenUsage;
433
+ cumulativeUsage(): TokenUsage;
434
+ turns(): number;
435
+ /**
436
+ * Finalize the current turn and start a new one.
437
+ * Call this at the end of each agent turn.
438
+ */
439
+ endTurn(): void;
440
+ /** Reset all usage data. */
441
+ reset(): void;
442
+ private hasTurnActivity;
443
+ }
444
+
445
+ /**
446
+ * router-events.ts — Bridge LLMRouter health/failover events into the agent event bus.
447
+ *
448
+ * The LLMRouter (from @sschepis/llm-wrapper) exposes a `RouterEventEmitter` that
449
+ * fires typed events for routing decisions, fallbacks, circuit breaker state changes,
450
+ * and request completions/errors.
451
+ *
452
+ * This module:
453
+ * 1. Subscribes to all LLMRouter events
454
+ * 2. Forwards them to the agent's AgentEventBus as `router_event` events
455
+ * 3. Provides a health snapshot method for observability
456
+ */
457
+
458
+ /**
459
+ * Bridge that forwards LLMRouter events to the agent event bus.
460
+ *
461
+ * Usage:
462
+ * ```ts
463
+ * const bridge = new RouterEventBridge(bus);
464
+ * bridge.attach(localRouter, "local");
465
+ * bridge.attach(remoteRouter, "remote");
466
+ *
467
+ * // Later, get a health snapshot
468
+ * const health = bridge.getHealthSnapshot();
469
+ * ```
470
+ */
471
+ declare class RouterEventBridge {
472
+ private bus;
473
+ private attachedRouters;
474
+ constructor(bus: AgentEventBus);
475
+ /**
476
+ * Attach an LLMRouter and forward all its events to the agent bus.
477
+ *
478
+ * @param router - The LLMRouter to monitor
479
+ * @param label - A label to identify this router in events (e.g. "local", "remote")
480
+ */
481
+ attach(router: LLMRouter, label: string): void;
482
+ /**
483
+ * Detach a previously attached router.
484
+ */
485
+ detach(label: string): void;
486
+ /**
487
+ * Detach all attached routers.
488
+ */
489
+ detachAll(): void;
490
+ /**
491
+ * Get a health snapshot from all attached routers.
492
+ * Returns a map of router label -> endpoint name -> HealthState.
493
+ */
494
+ getHealthSnapshot(): Map<string, Map<string, HealthState>>;
495
+ /**
496
+ * Check if any attached router has an endpoint in "open" (tripped) circuit state.
497
+ */
498
+ hasTrippedCircuits(): boolean;
499
+ /**
500
+ * Get the labels of all attached routers.
501
+ */
502
+ get labels(): string[];
503
+ }
504
+ /**
505
+ * Helper to check if a ProviderLike is an LLMRouter (has `events` property).
506
+ */
507
+ declare function isLLMRouter(provider: unknown): provider is LLMRouter;
508
+
509
+ /**
510
+ * usage-bridge.ts — Bidirectional bridge between as-agent's UsageTracker
511
+ * and lmscript's CostTracker.
512
+ *
513
+ * Field mapping:
514
+ * as-agent lmscript
515
+ * ───────── ────────
516
+ * inputTokens → promptTokens
517
+ * outputTokens → completionTokens
518
+ * cacheCreationInputTokens → (no equivalent, tracked separately)
519
+ * cacheReadInputTokens → (no equivalent, tracked separately)
520
+ * (sum of all) → totalTokens
521
+ *
522
+ * The bridge records every usage event into both systems, ensuring
523
+ * unified cost accounting regardless of which subsystem reports usage.
524
+ */
525
+
526
+ /**
527
+ * Convert as-agent TokenUsage to lmscript usage format.
528
+ */
529
+ declare function asTokenUsageToLmscript(usage: TokenUsage): {
530
+ promptTokens: number;
531
+ completionTokens: number;
532
+ totalTokens: number;
533
+ };
534
+ /**
535
+ * Convert lmscript usage format to as-agent TokenUsage.
536
+ * Cache tokens default to 0 since lmscript doesn't track them separately.
537
+ */
538
+ declare function lmscriptToAsTokenUsage(usage: {
539
+ promptTokens: number;
540
+ completionTokens: number;
541
+ totalTokens: number;
542
+ }): TokenUsage;
543
+ /**
544
+ * Estimate costs using as-agent's ModelPricing (per-million-token pricing).
545
+ */
546
+ declare function estimateCostFromAsAgent(usage: TokenUsage, pricing: ModelPricing$1): UsageCostEstimate;
547
+ /**
548
+ * Bidirectional bridge that keeps an as-agent UsageTracker and an
549
+ * lmscript CostTracker in sync.
550
+ *
551
+ * When usage is reported from either side, the bridge records it in
552
+ * both tracking systems.
553
+ *
554
+ * ```ts
555
+ * const bridge = new UsageBridge(usageTracker, costTracker);
556
+ *
557
+ * // Record from LLM response (lmscript format)
558
+ * bridge.recordFromLmscript("gpt-4", { promptTokens: 100, completionTokens: 50, totalTokens: 150 });
559
+ *
560
+ * // Record from API response (as-agent format)
561
+ * bridge.recordFromAsAgent({ inputTokens: 100, outputTokens: 50, cacheCreationInputTokens: 0, cacheReadInputTokens: 0 });
562
+ *
563
+ * // Get unified cost summary
564
+ * const summary = bridge.getCostSummary(lmModelPricing, asModelPricing);
565
+ * ```
566
+ */
567
+ declare class UsageBridge {
568
+ private asTracker;
569
+ private lmTracker?;
570
+ constructor(asTracker: AgentUsageTracker, lmTracker?: CostTracker | undefined);
571
+ /**
572
+ * Record usage from an lmscript-format source (e.g. from the streaming path
573
+ * or AgentLoop result).
574
+ *
575
+ * Converts to as-agent format and records in both trackers.
576
+ */
577
+ recordFromLmscript(functionName: string, usage: {
578
+ promptTokens: number;
579
+ completionTokens: number;
580
+ totalTokens: number;
581
+ }): void;
582
+ /**
583
+ * Record usage from an as-agent-format source (e.g. from ConversationRuntime
584
+ * or the Wasm runtime).
585
+ *
586
+ * Converts to lmscript format and records in both trackers.
587
+ */
588
+ recordFromAsAgent(usage: TokenUsage, functionName?: string): void;
589
+ /**
590
+ * End the current turn in the as-agent tracker.
591
+ */
592
+ endTurn(): void;
593
+ /**
594
+ * Get unified cost summary combining both tracking systems.
595
+ */
596
+ getCostSummary(lmPricing?: ModelPricing, asPricing?: ModelPricing$1): UnifiedCostSummary;
597
+ /**
598
+ * Reset both tracking systems.
599
+ */
600
+ reset(): void;
601
+ /** Get the as-agent usage tracker. */
602
+ getAsTracker(): AgentUsageTracker;
603
+ /** Get the lmscript cost tracker (if available). */
604
+ getLmTracker(): CostTracker | undefined;
605
+ }
606
+ interface UnifiedCostSummary {
607
+ /** as-agent's view: per-turn token counts and optional cost estimate. */
608
+ asAgent: {
609
+ usage: TokenUsage;
610
+ turns: number;
611
+ costEstimate?: UsageCostEstimate;
612
+ };
613
+ /** lmscript's view: total tokens, cost, and per-function breakdown. */
614
+ lmscript?: {
615
+ totalTokens: number;
616
+ totalCost: number;
617
+ byFunction: Record<string, {
618
+ calls: number;
619
+ totalTokens: number;
620
+ promptTokens: number;
621
+ completionTokens: number;
622
+ }>;
623
+ };
624
+ }
625
+
626
+ type EventHandler = (event: AgentEvent) => void;
52
627
  /**
53
628
  * ObotoAgent is the central orchestrator for dual-LLM agent execution.
54
629
  *
55
630
  * It binds together:
56
- * - llm-wrapper (LLM communication via local and remote providers)
57
- * - lmscript (structured/schema-validated calls for triage)
631
+ * - llm-wrapper (LLM communication via local and remote providers / LLMRouter)
632
+ * - lmscript (structured/schema-validated calls, agent loop, infrastructure)
58
633
  * - swiss-army-tool (tool execution via Router)
59
634
  * - as-agent (session state and conversation history)
60
635
  *
61
636
  * All interaction flows through an event-driven architecture.
637
+ *
638
+ * Key integration improvements (v0.2):
639
+ * - Accepts LLMRouter for automatic failover and health tracking
640
+ * - Uses lmscript's AgentLoop instead of a custom tool-calling loop
641
+ * - Wires lmscript infrastructure: cache, cost tracking, rate limiting, middleware
642
+ * - Bridges streaming via chatStream through the full lmscript stack
62
643
  */
63
644
  declare class ObotoAgent {
64
645
  private bus;
65
646
  private localRuntime;
647
+ private remoteRuntime;
66
648
  private localProvider;
67
649
  private remoteProvider;
68
650
  private contextManager;
@@ -75,36 +657,116 @@ declare class ObotoAgent {
75
657
  private maxIterations;
76
658
  private config;
77
659
  private onToken?;
660
+ private costTracker?;
661
+ private modelPricing?;
662
+ private rateLimiter?;
663
+ private middleware;
664
+ private budget?;
665
+ private conversationRAG?;
666
+ private permissionGuard?;
667
+ private sessionCompactor?;
668
+ private hookIntegration?;
669
+ private slashCommands;
670
+ private usageTracker;
671
+ private usageBridge;
672
+ private routerEventBridge;
78
673
  constructor(config: ObotoAgentConfig);
79
674
  /** Subscribe to agent events. Returns an unsubscribe function. */
80
- on(type: AgentEventType, handler: EventHandler$1): () => void;
675
+ on(type: AgentEventType, handler: EventHandler): () => void;
81
676
  /** Subscribe to an event for a single emission. */
82
- once(type: AgentEventType, handler: EventHandler$1): () => void;
677
+ once(type: AgentEventType, handler: EventHandler): () => void;
83
678
  /** Submit user input to the agent. Triggers the execution loop. */
84
679
  submitInput(text: string): Promise<void>;
85
680
  /**
86
681
  * Interrupt the current execution loop.
87
682
  * Optionally inject new directives into the context.
88
683
  */
89
- interrupt(newDirectives?: string): void;
684
+ interrupt(newDirectives?: string): Promise<void>;
90
685
  /** Get the current session state. */
91
686
  getSession(): Session;
92
687
  /** Whether the agent is currently processing input. */
93
688
  get processing(): boolean;
94
- /** Remove all event listeners. */
689
+ /** Get cost tracking summary (if cost tracking is enabled). */
690
+ getCostSummary(): {
691
+ totalCost: number;
692
+ totalTokens: number;
693
+ byFunction: Record<string, {
694
+ calls: number;
695
+ totalTokens: number;
696
+ promptTokens: number;
697
+ completionTokens: number;
698
+ }>;
699
+ } | undefined;
700
+ /**
701
+ * Get unified cost summary combining both as-agent and lmscript tracking.
702
+ * Uses the UsageBridge to provide a single view of all token/cost data.
703
+ */
704
+ getUnifiedCostSummary(asPricing?: _sschepis_as_agent.ModelPricing): UnifiedCostSummary;
705
+ /** Get the usage bridge for direct access to unified tracking. */
706
+ getUsageBridge(): UsageBridge;
707
+ /** Remove all event listeners and detach router event subscriptions. */
95
708
  removeAllListeners(): void;
709
+ /** Sync session and repopulate context manager (for reuse across turns). */
710
+ syncSession(session: Session): Promise<void>;
711
+ /** Update the streaming token callback between turns. */
712
+ setOnToken(callback: ((token: string) => void) | undefined): void;
713
+ /** Get the ConversationRAG instance (if RAG is enabled). */
714
+ getConversationRAG(): ConversationRAG | undefined;
715
+ /** Get the slash command registry. */
716
+ getSlashCommands(): SlashCommandRegistry;
717
+ /** Get the as-agent usage tracker. */
718
+ getUsageTracker(): AgentUsageTracker;
719
+ /** Get the permission guard (if permissions are configured). */
720
+ getPermissionGuard(): PermissionGuard | undefined;
721
+ /** Get the session compactor (if compaction is configured). */
722
+ getSessionCompactor(): SessionCompactor | undefined;
723
+ /** Get the router event bridge for observability into LLMRouter health. */
724
+ getRouterEventBridge(): RouterEventBridge;
725
+ /**
726
+ * Manually compact the session. Returns null if compaction is not configured.
727
+ */
728
+ compactSession(): _sschepis_as_agent.CompactionResult | null;
729
+ /**
730
+ * Retrieve relevant past context for a query via the RAG pipeline.
731
+ * Returns undefined if RAG is not configured.
732
+ */
733
+ retrieveContext(query: string): Promise<string | undefined>;
734
+ /**
735
+ * Record a message in the session, context manager, and optionally RAG index.
736
+ * Centralizes message recording to ensure RAG indexing stays in sync.
737
+ */
738
+ private recordMessage;
739
+ /**
740
+ * Record a tool execution result in the RAG index.
741
+ */
742
+ private recordToolResult;
96
743
  private executionLoop;
97
744
  private triage;
98
- /** Maximum characters per tool result before truncation. */
99
- private static readonly MAX_TOOL_RESULT_CHARS;
100
- /** Maximum times the same tool+args can repeat before forcing a text response. */
101
- private static readonly MAX_DUPLICATE_CALLS;
102
745
  /**
103
- * Execute the agent loop using llm-wrapper directly.
104
- * When onToken is configured, uses streaming for real-time token output.
105
- * No JSON mode, no schema enforcement — just natural chat with tool calling.
746
+ * Execute using lmscript's AgentLoop for iterative tool calling.
747
+ * This replaces the old custom tool loop with lmscript's battle-tested implementation.
748
+ *
749
+ * Benefits:
750
+ * - Schema validation on final output
751
+ * - Budget checking via CostTracker
752
+ * - Rate limiting via RateLimiter
753
+ * - Middleware lifecycle hooks
754
+ * - Automatic retry with backoff
106
755
  */
107
- private executeWithModel;
756
+ private executeWithAgentLoop;
757
+ /**
758
+ * Execute with streaming token emission.
759
+ * Uses the raw llm-wrapper provider for streaming, combined with
760
+ * manual tool calling (since streaming + structured agent loops are complex).
761
+ *
762
+ * This preserves real-time token delivery while still leveraging
763
+ * the lmscript infrastructure:
764
+ * - Rate limiting (acquire/reportTokens per call)
765
+ * - Cost tracking (trackUsage per call)
766
+ * - Budget checking (checkBudget before each call)
767
+ * - Middleware lifecycle hooks (onBeforeExecute/onComplete per turn)
768
+ */
769
+ private executeWithStreaming;
108
770
  /**
109
771
  * Stream an LLM call, emitting tokens in real-time, then aggregate into
110
772
  * a full StandardChatResponse (including accumulated tool calls).
@@ -112,25 +774,6 @@ declare class ObotoAgent {
112
774
  private streamAndAggregate;
113
775
  }
114
776
 
115
- type EventHandler = (event: AgentEvent) => void;
116
- /**
117
- * Platform-agnostic typed event bus.
118
- * Uses a plain Map instead of Node.js EventEmitter for browser/Deno/Bun compatibility.
119
- */
120
- declare class AgentEventBus {
121
- private listeners;
122
- /** Subscribe to an event type. Returns an unsubscribe function. */
123
- on(type: AgentEventType, handler: EventHandler): () => void;
124
- /** Unsubscribe a handler from an event type. */
125
- off(type: AgentEventType, handler: EventHandler): void;
126
- /** Subscribe to an event type for a single emission. */
127
- once(type: AgentEventType, handler: EventHandler): () => void;
128
- /** Emit an event to all subscribers. */
129
- emit(type: AgentEventType, payload: unknown): void;
130
- /** Remove all listeners for all event types. */
131
- removeAllListeners(): void;
132
- }
133
-
134
777
  /** Parameter schema for the omni-tool bridge. */
135
778
  declare const RouterToolParams: z.ZodObject<{
136
779
  command: z.ZodString;
@@ -160,12 +803,323 @@ declare function sessionToHistory(session: Session): ChatMessage[];
160
803
  declare function createEmptySession(): Session;
161
804
 
162
805
  /**
163
- * Adapt a llm-wrapper BaseProvider into lmscript's LLMProvider interface.
806
+ * A provider-like object that has `chat()` and `stream()` methods.
807
+ * Both `BaseProvider` and `LLMRouter` implement this interface.
808
+ */
809
+ type ProviderLike = {
810
+ chat(params: StandardChatParams): Promise<_sschepis_llm_wrapper.StandardChatResponse>;
811
+ stream(params: StandardChatParams): AsyncIterable<_sschepis_llm_wrapper.StandardChatChunk>;
812
+ readonly providerName?: string;
813
+ };
814
+ /**
815
+ * Adapt a llm-wrapper BaseProvider (or LLMRouter) into lmscript's LLMProvider interface.
164
816
  *
165
817
  * This allows lmscript's LScriptRuntime to use llm-wrapper providers for
166
818
  * structured calls (e.g. triage) that need schema validation.
819
+ *
820
+ * Bridges both `chat()` and `chatStream()` — enabling streaming through the
821
+ * full lmscript stack (including `executeStream()`).
822
+ */
823
+ declare function toLmscriptProvider(provider: ProviderLike, name?: string): LLMProvider;
824
+
825
+ /**
826
+ * tool-extensions.ts — Swiss-army-tool integration extensions for oboto-agent.
827
+ *
828
+ * This module provides:
829
+ * 1. AgentDynamicTools — A DynamicBranchNode subclass for runtime tool discovery
830
+ * 2. createToolTimingMiddleware — Swiss-army-tool Middleware that emits timing events
831
+ * 3. createAgentToolTree — Helper to build a pre-wired tool tree with memory + dynamic tools
832
+ */
833
+
834
+ interface DynamicToolProvider {
835
+ /**
836
+ * Called when the branch needs refreshing.
837
+ * Return an array of leaf node configs to populate the dynamic branch.
838
+ */
839
+ discover(): Promise<DynamicToolEntry[]> | DynamicToolEntry[];
840
+ }
841
+ interface DynamicToolEntry {
842
+ name: string;
843
+ description: string;
844
+ requiredArgs?: string[] | Record<string, {
845
+ type?: string;
846
+ description?: string;
847
+ }>;
848
+ optionalArgs?: string[] | Record<string, {
849
+ type?: string;
850
+ description?: string;
851
+ default?: unknown;
852
+ }>;
853
+ handler: (kwargs: Record<string, unknown>) => string | Promise<string>;
854
+ }
855
+ interface AgentToolTreeConfig {
856
+ /** Session manager for the swiss-army-tool Router */
857
+ session: SessionManager;
858
+ /** Whether to include the memory module (set/get/list/pin). Default: true */
859
+ includeMemory?: boolean;
860
+ /** Additional static branches to add to the tree */
861
+ staticBranches?: BranchNode[];
862
+ /** Dynamic tool providers to register. Each entry becomes a DynamicBranchNode */
863
+ dynamicProviders?: Array<{
864
+ name: string;
865
+ description: string;
866
+ provider: DynamicToolProvider;
867
+ /** TTL in ms before the provider is re-queried. Default: 60000 */
868
+ ttlMs?: number;
869
+ }>;
870
+ }
871
+ /**
872
+ * A DynamicBranchNode that discovers tools at runtime from a provider.
873
+ *
874
+ * Use this to integrate external tool sources (MCP servers, plugin systems,
875
+ * API discovery endpoints, etc.) into the swiss-army-tool command tree.
876
+ *
877
+ * The provider's `discover()` method is called when the TTL expires,
878
+ * and the returned entries are registered as LeafNode children.
879
+ *
880
+ * ```ts
881
+ * const mcpTools = new AgentDynamicTools({
882
+ * name: "mcp",
883
+ * description: "Tools discovered from MCP servers",
884
+ * provider: myMcpProvider,
885
+ * ttlMs: 30_000, // refresh every 30s
886
+ * });
887
+ * ```
888
+ */
889
+ declare class AgentDynamicTools extends DynamicBranchNode {
890
+ private provider;
891
+ constructor(config: {
892
+ name: string;
893
+ description: string;
894
+ provider: DynamicToolProvider;
895
+ ttlMs?: number;
896
+ });
897
+ protected refresh(): Promise<void>;
898
+ /** Manually register a tool entry without waiting for refresh. */
899
+ registerTool(entry: DynamicToolEntry): void;
900
+ /** Remove a dynamically registered tool by name. */
901
+ unregisterTool(name: string): boolean;
902
+ }
903
+ /**
904
+ * Creates a swiss-army-tool Middleware that emits tool execution timing
905
+ * and results through the agent's event bus.
906
+ *
907
+ * This bridges swiss-army-tool's execution context into oboto-agent's
908
+ * event-driven architecture, enabling:
909
+ * - Real-time tool execution duration monitoring
910
+ * - Tool execution logging / tracing
911
+ * - Performance analytics
912
+ *
913
+ * ```ts
914
+ * const timingMw = createToolTimingMiddleware(agent.bus);
915
+ * router.use(timingMw);
916
+ * ```
917
+ */
918
+ declare function createToolTimingMiddleware(bus: AgentEventBus): Middleware;
919
+ /**
920
+ * Creates a swiss-army-tool Middleware that enforces a maximum execution
921
+ * time for any tool call. Useful as a safety net.
922
+ */
923
+ declare function createToolTimeoutMiddleware(maxMs: number): Middleware;
924
+ /**
925
+ * Creates a swiss-army-tool Middleware that logs all tool calls to the
926
+ * session's KV store for later review. The agent can access these via
927
+ * the memory module.
928
+ */
929
+ declare function createToolAuditMiddleware(session: SessionManager): Middleware;
930
+ /**
931
+ * Build a pre-wired swiss-army-tool command tree that includes:
932
+ * - Memory module (set/get/list/search/pin/unpin/delete/tag)
933
+ * - Dynamic tool branches from providers
934
+ * - Any additional static branches
935
+ *
936
+ * Returns the root BranchNode, ready to be passed to `new Router(root, session)`.
937
+ *
938
+ * ```ts
939
+ * const root = createAgentToolTree({
940
+ * session,
941
+ * includeMemory: true,
942
+ * dynamicProviders: [
943
+ * { name: "mcp", description: "MCP tools", provider: mcpProvider },
944
+ * ],
945
+ * staticBranches: [myFilesystemBranch, myDatabaseBranch],
946
+ * });
947
+ * const router = new Router(root, session);
948
+ * ```
949
+ */
950
+ declare function createAgentToolTree(config: AgentToolTreeConfig): BranchNode;
951
+
952
+ /**
953
+ * pipeline-workflows.ts — Multi-step agent workflows using lmscript's Pipeline.
954
+ *
955
+ * This module provides pre-built and composable pipeline patterns for
956
+ * chaining LLM calls where the typed output of one step feeds into the next.
957
+ *
958
+ * Key patterns:
959
+ * 1. Triage → Execute → Summarize
960
+ * 2. Analyze → Plan → Execute
961
+ * 3. Custom pipeline builder for agent-specific workflows
962
+ */
963
+
964
+ /** Output of a triage step — determines routing and intent. */
965
+ declare const TriagePipelineSchema: z.ZodObject<{
966
+ intent: z.ZodString;
967
+ complexity: z.ZodEnum<["simple", "moderate", "complex"]>;
968
+ requiresTools: z.ZodBoolean;
969
+ suggestedApproach: z.ZodString;
970
+ escalate: z.ZodBoolean;
971
+ }, "strip", z.ZodTypeAny, {
972
+ escalate: boolean;
973
+ intent: string;
974
+ complexity: "simple" | "moderate" | "complex";
975
+ requiresTools: boolean;
976
+ suggestedApproach: string;
977
+ }, {
978
+ escalate: boolean;
979
+ intent: string;
980
+ complexity: "simple" | "moderate" | "complex";
981
+ requiresTools: boolean;
982
+ suggestedApproach: string;
983
+ }>;
984
+ type TriagePipelineOutput = z.infer<typeof TriagePipelineSchema>;
985
+ /** Output of a planning step — breaks work into steps. */
986
+ declare const PlanSchema: z.ZodObject<{
987
+ steps: z.ZodArray<z.ZodObject<{
988
+ description: z.ZodString;
989
+ toolRequired: z.ZodOptional<z.ZodString>;
990
+ expectedOutput: z.ZodOptional<z.ZodString>;
991
+ }, "strip", z.ZodTypeAny, {
992
+ description: string;
993
+ toolRequired?: string | undefined;
994
+ expectedOutput?: string | undefined;
995
+ }, {
996
+ description: string;
997
+ toolRequired?: string | undefined;
998
+ expectedOutput?: string | undefined;
999
+ }>, "many">;
1000
+ estimatedComplexity: z.ZodEnum<["low", "medium", "high"]>;
1001
+ reasoning: z.ZodString;
1002
+ }, "strip", z.ZodTypeAny, {
1003
+ reasoning: string;
1004
+ steps: {
1005
+ description: string;
1006
+ toolRequired?: string | undefined;
1007
+ expectedOutput?: string | undefined;
1008
+ }[];
1009
+ estimatedComplexity: "low" | "high" | "medium";
1010
+ }, {
1011
+ reasoning: string;
1012
+ steps: {
1013
+ description: string;
1014
+ toolRequired?: string | undefined;
1015
+ expectedOutput?: string | undefined;
1016
+ }[];
1017
+ estimatedComplexity: "low" | "high" | "medium";
1018
+ }>;
1019
+ type PlanOutput = z.infer<typeof PlanSchema>;
1020
+ /** Output of an execution step — the actual work result. */
1021
+ declare const ExecutionSchema: z.ZodObject<{
1022
+ response: z.ZodString;
1023
+ stepsCompleted: z.ZodNumber;
1024
+ toolsUsed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1025
+ confidence: z.ZodEnum<["low", "medium", "high"]>;
1026
+ }, "strip", z.ZodTypeAny, {
1027
+ response: string;
1028
+ stepsCompleted: number;
1029
+ confidence: "low" | "high" | "medium";
1030
+ toolsUsed?: string[] | undefined;
1031
+ }, {
1032
+ response: string;
1033
+ stepsCompleted: number;
1034
+ confidence: "low" | "high" | "medium";
1035
+ toolsUsed?: string[] | undefined;
1036
+ }>;
1037
+ type ExecutionOutput = z.infer<typeof ExecutionSchema>;
1038
+ /** Output of a summarization step — condenses results. */
1039
+ declare const SummarySchema: z.ZodObject<{
1040
+ summary: z.ZodString;
1041
+ keyPoints: z.ZodArray<z.ZodString, "many">;
1042
+ followUpSuggestions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1043
+ }, "strip", z.ZodTypeAny, {
1044
+ summary: string;
1045
+ keyPoints: string[];
1046
+ followUpSuggestions?: string[] | undefined;
1047
+ }, {
1048
+ summary: string;
1049
+ keyPoints: string[];
1050
+ followUpSuggestions?: string[] | undefined;
1051
+ }>;
1052
+ type SummaryOutput = z.infer<typeof SummarySchema>;
1053
+ /**
1054
+ * Create a triage step function for the pipeline.
167
1055
  */
168
- declare function toLmscriptProvider(provider: BaseProvider, name?: string): LLMProvider;
1056
+ declare function createTriageStep(modelName: string, systemPrompt?: string): LScriptFunction<string, typeof TriagePipelineSchema>;
1057
+ /**
1058
+ * Create a planning step that takes triage output and produces a plan.
1059
+ */
1060
+ declare function createPlanStep(modelName: string, systemPrompt?: string): LScriptFunction<TriagePipelineOutput, typeof PlanSchema>;
1061
+ /**
1062
+ * Create an execution step that takes a plan and produces results.
1063
+ */
1064
+ declare function createExecutionStep(modelName: string, tools?: LScriptFunction<any, any>["tools"], systemPrompt?: string): LScriptFunction<PlanOutput, typeof ExecutionSchema>;
1065
+ /**
1066
+ * Create a summarization step that condenses execution results.
1067
+ */
1068
+ declare function createSummaryStep(modelName: string, systemPrompt?: string): LScriptFunction<ExecutionOutput, typeof SummarySchema>;
1069
+ /**
1070
+ * Build a Triage → Plan → Execute pipeline.
1071
+ *
1072
+ * Takes raw user input, classifies it, plans the approach,
1073
+ * and executes the plan.
1074
+ *
1075
+ * ```ts
1076
+ * const pipeline = createTriagePlanExecutePipeline("gpt-4");
1077
+ * const result = await pipeline.execute(runtime, "Refactor the auth module");
1078
+ * console.log(result.finalData.response);
1079
+ * ```
1080
+ */
1081
+ declare function createTriagePlanExecutePipeline(modelName: string, tools?: LScriptFunction<any, any>["tools"]): Pipeline<string, ExecutionOutput>;
1082
+ /**
1083
+ * Build a Triage → Plan → Execute → Summarize pipeline.
1084
+ *
1085
+ * Full end-to-end pipeline that classifies, plans, executes,
1086
+ * and then summarizes the results.
1087
+ *
1088
+ * ```ts
1089
+ * const pipeline = createFullPipeline("gpt-4");
1090
+ * const result = await pipeline.execute(runtime, "Build a REST API");
1091
+ * console.log(result.finalData.summary);
1092
+ * console.log(`Total tokens: ${result.totalUsage.totalTokens}`);
1093
+ * ```
1094
+ */
1095
+ declare function createFullPipeline(modelName: string, tools?: LScriptFunction<any, any>["tools"]): Pipeline<string, SummaryOutput>;
1096
+ /**
1097
+ * Build a simple Analyze → Respond pipeline.
1098
+ * Good for straightforward queries that don't need planning.
1099
+ */
1100
+ declare function createAnalyzeRespondPipeline(modelName: string): Pipeline<string, ExecutionOutput>;
1101
+ /**
1102
+ * Configuration for running a pipeline within the agent context.
1103
+ */
1104
+ interface AgentPipelineConfig {
1105
+ /** The lmscript runtime to execute the pipeline on. */
1106
+ runtime: LScriptRuntime;
1107
+ /** The model name for all pipeline steps (can be overridden per-step). */
1108
+ modelName: string;
1109
+ /** Optional tools available to the execution step. */
1110
+ tools?: LScriptFunction<any, any>["tools"];
1111
+ /** Callback for each pipeline step completion. */
1112
+ onStepComplete?: (stepName: string, data: unknown, usage: {
1113
+ promptTokens: number;
1114
+ completionTokens: number;
1115
+ totalTokens: number;
1116
+ } | undefined) => void;
1117
+ }
1118
+ /**
1119
+ * Run a pipeline and emit step completion events.
1120
+ * This is a convenience wrapper that adds observability.
1121
+ */
1122
+ declare function runAgentPipeline<I, O>(pipeline: Pipeline<I, O>, input: I, config: AgentPipelineConfig): Promise<PipelineResult<O>>;
169
1123
 
170
1124
  /**
171
1125
  * Manages the sliding context window with automatic summarization.
@@ -192,7 +1146,7 @@ declare class ContextManager {
192
1146
  declare const TriageSchema: z.ZodObject<{
193
1147
  escalate: z.ZodBoolean;
194
1148
  reasoning: z.ZodString;
195
- directResponse: z.ZodOptional<z.ZodString>;
1149
+ directResponse: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodString>>, string | undefined, string | null | undefined>;
196
1150
  }, "strip", z.ZodTypeAny, {
197
1151
  escalate: boolean;
198
1152
  reasoning: string;
@@ -200,7 +1154,7 @@ declare const TriageSchema: z.ZodObject<{
200
1154
  }, {
201
1155
  escalate: boolean;
202
1156
  reasoning: string;
203
- directResponse?: string | undefined;
1157
+ directResponse?: string | null | undefined;
204
1158
  }>;
205
1159
  type TriageInput = {
206
1160
  userInput: string;
@@ -213,4 +1167,4 @@ type TriageInput = {
213
1167
  */
214
1168
  declare function createTriageFunction(modelName: string): LScriptFunction<TriageInput, typeof TriageSchema>;
215
1169
 
216
- export { type AgentEvent, AgentEventBus, type AgentEventType, ContextManager, ObotoAgent, type ObotoAgentConfig, type ToolExecutionEvent, type TriageResult, TriageSchema, createEmptySession, createRouterTool, createTriageFunction, fromChat, sessionToHistory, toChat, toLmscriptProvider };
1170
+ export { AgentDynamicTools, type AgentEvent, AgentEventBus, type AgentEventType, type AgentPipelineConfig, type AgentToolTreeConfig, AgentUsageTracker, ContextManager, ConversationRAG, type ConversationRAGConfig, type DynamicToolEntry, type DynamicToolProvider, type ExecutionOutput, ExecutionSchema, HookIntegration, ObotoAgent, type ObotoAgentConfig, PermissionGuard, type PlanOutput, PlanSchema, type ProviderLike$1 as ProviderLike, type RAGRetrievalResult, RouterEventBridge, SessionCompactor, SlashCommandRegistry, type SummaryOutput, SummarySchema, type ToolExecutionEvent, type TriagePipelineOutput, TriagePipelineSchema, type TriageResult, TriageSchema, type UnifiedCostSummary, UsageBridge, asTokenUsageToLmscript, createAgentToolTree, createAnalyzeRespondPipeline, createEmptySession, createExecutionStep, createFullPipeline, createPlanStep, createRouterTool, createSummaryStep, createToolAuditMiddleware, createToolTimeoutMiddleware, createToolTimingMiddleware, createTriageFunction, createTriagePlanExecutePipeline, createTriageStep, estimateCostFromAsAgent, fromChat, isLLMRouter, lmscriptToAsTokenUsage, runAgentPipeline, sessionToHistory, toChat, toLmscriptProvider };