agent.libx.js 0.86.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.
@@ -0,0 +1,621 @@
1
+ import { a as AgentOptions, H as Hooks, g as RunResult } from './Agent-WTkHB8RY.js';
2
+ export { A as Agent, D as DEFAULT_MUTATING, b as Decision, P as PermissionOptions, c as PermissionPolicy, d as PermissionRule, e as PreToolUseDecision, R as RecordingHooks, f as RecordingLifecycle, T as ToolUse, h as ToolUseMeta, i as composeHooks, p as planMode } from './Agent-WTkHB8RY.js';
3
+ import { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';
4
+ export { CommandExecutor, FileMetadata, IFilesystem, IndexedDbFilesystem, MemFilesystem, registerHeadlessCommands } from '@livx.cc/wcli/core';
5
+ import { BodDB } from '@bod.ee/db';
6
+ import { A as AgentTool, C as ChatLike, a as ChatOptions, b as ChatResponse, h as ToolCall, H as HostBridge, U as UserQuestion } from './tools-Ch-OzOU8.js';
7
+ export { c as ContentPart, d as HostEvent, M as Message, e as MessageContent, R as Role, S as SandboxJobRegistry, f as StreamChunk, T as TodoItem, g as Tool, i as ToolContext, j as bashTool, k as contentText, l as defaultTools, m as editTool, n as imagePart, o as makeContext, p as makeJobTools, r as readTool, t as toWireTools, q as todoWriteTool, s as toolRegistry, u as toolsByName } from './tools-Ch-OzOU8.js';
8
+ export { M as McpCall, a as McpToolSearchOptions, b as McpToolSpec, m as makeMcpToolSearch, c as mcpToolToAgentTool, d as mcpToolsToAgentTools } from './mcp-Dg3vA1Uj.js';
9
+ import * as libx_js_src_modules_log from 'libx.js/src/modules/log';
10
+ export { log } from 'libx.js/src/modules/log';
11
+
12
+ /**
13
+ * Real-disk backend implementing wcli's IFilesystem, rooted at `baseDir`.
14
+ * The VFS path space ('/...') maps under baseDir, so the same agent/tools/commands
15
+ * run unchanged against disk or memory — complete mem↔disk interchangeability.
16
+ * Semantics mirror MemFilesystem (throws on missing parent / existing dir / etc.).
17
+ */
18
+ declare class NodeDiskFilesystem implements IFilesystem {
19
+ private baseDir;
20
+ private cwd;
21
+ private opts;
22
+ constructor(baseDir: string, opts?: {
23
+ denySymlinks?: boolean;
24
+ });
25
+ /** Ensure the root dir exists. */
26
+ init(): Promise<void>;
27
+ private real;
28
+ /** Throw if any existing component of `real` is a symlink (escape vector). */
29
+ private assertNoSymlink;
30
+ resolvePath(path: string, cwd?: string): string;
31
+ getCwd(): string;
32
+ setCwd(path: string): void;
33
+ readFile(path: string): Promise<string>;
34
+ /** Read raw bytes (for binary files like images). Not on the base IFilesystem (which is utf8-only) — an
35
+ * optional capability the Read tool duck-types to return image blocks. Same symlink/jail guards as readFile. */
36
+ readFileBytes(path: string): Promise<Uint8Array>;
37
+ writeFile(path: string, content: string): Promise<void>;
38
+ deleteFile(path: string): Promise<void>;
39
+ readDir(path: string): Promise<string[]>;
40
+ createDir(path: string): Promise<void>;
41
+ exists(path: string): Promise<boolean>;
42
+ stat(path: string): Promise<FileMetadata>;
43
+ isDirectory(path: string): Promise<boolean>;
44
+ isFile(path: string): Promise<boolean>;
45
+ }
46
+
47
+ /**
48
+ * Database-backed `IFilesystem` over bod-db's VFS — the normalization thesis realized: the agent
49
+ * operates on a file tree that lives in a database, yet the same tools/commands run unchanged
50
+ * (semantics mirror MemFilesystem/NodeDiskFilesystem: throw on missing parent / existing dir /
51
+ * non-empty dir / missing file). bod-db's VFS is path-based and async, so the adapter is thin.
52
+ *
53
+ * Construct with no args for an in-memory DB (great for tests), or pass a configured `BodDB`
54
+ * (with VFS enabled) backed by real/cloud storage for persistence. Call `close()` when done to
55
+ * release the DB's timers (the in-memory default uses `sweepInterval: 0`, so there's nothing to sweep).
56
+ */
57
+ declare class BodDbFilesystem implements IFilesystem {
58
+ private cwd;
59
+ private db;
60
+ private vfs;
61
+ private owns;
62
+ constructor(db?: BodDB);
63
+ /** Release the underlying DB's timers/handles. Closes only a DB we created (a passed-in DB is the caller's). */
64
+ close(): void;
65
+ resolvePath(path: string, cwd?: string): string;
66
+ getCwd(): string;
67
+ setCwd(path: string): void;
68
+ /** Parent dir of an absolute VFS path ('/a/b.txt' -> '/a'; '/a' -> '/'). */
69
+ private parentOf;
70
+ /** Throw (matching the other backends) unless the parent directory exists. Root is always a dir. */
71
+ private assertParentDir;
72
+ readFile(path: string): Promise<string>;
73
+ writeFile(path: string, content: string): Promise<void>;
74
+ deleteFile(path: string): Promise<void>;
75
+ readDir(path: string): Promise<string[]>;
76
+ createDir(path: string): Promise<void>;
77
+ exists(path: string): Promise<boolean>;
78
+ stat(path: string): Promise<FileMetadata>;
79
+ isDirectory(path: string): Promise<boolean>;
80
+ isFile(path: string): Promise<boolean>;
81
+ }
82
+
83
+ /**
84
+ * Containment boundary A — a policy decorator over ANY IFilesystem.
85
+ *
86
+ * The agent only ever sees an IFilesystem, so what it can touch is exactly what we
87
+ * mount. This jail:
88
+ * - hides + blocks `deny` paths entirely (secrets: .env, keys, .git, …) — invisible
89
+ * to read/stat/exists/readDir, unwritable;
90
+ * - makes `readonly` paths readable but unwritable (the "constitution": pinned
91
+ * grader/suite/criteria the self-evolve agent must never edit);
92
+ * - optionally `confineTo` a set of subtrees (anything outside is denied);
93
+ * - normalizes paths first, so `..` traversal (`/src/../.env`) is caught after resolution;
94
+ * - reports every violation via `onViolation` (audit trail / circuit-breaker hook).
95
+ *
96
+ * Crucial limitation: this guards what the AGENT'S TOOLS touch. It does NOT contain
97
+ * code executed against the real disk at eval time (the grader imports agent-written
98
+ * code) — that is boundary B (a sandboxed subprocess). See mind/08-self-evolve.md.
99
+ */
100
+ declare class JailedFilesystem implements IFilesystem {
101
+ private inner;
102
+ options: JailOptions;
103
+ private denyRe;
104
+ private roRe;
105
+ private confineRe?;
106
+ constructor(inner: IFilesystem, options?: Partial<JailOptions>);
107
+ private abs;
108
+ /** Throw if reading `path` is not permitted (denied or out of confinement). */
109
+ private guardRead;
110
+ /** Throw if writing/deleting `path` is not permitted (denied, readonly, or out of confinement). */
111
+ private guardWrite;
112
+ private violate;
113
+ /** Fire the audit hook without throwing (for boolean probes that must still return false). */
114
+ private note;
115
+ /** Is `abs` (already-resolved) visible? If not, fire the audit hook (op given) and return false. */
116
+ private visible;
117
+ readFile(path: string): Promise<string>;
118
+ /** Forward the optional binary-read capability (if the inner fs has it), jailed like readFile. */
119
+ readFileBytes(path: string): Promise<Uint8Array>;
120
+ writeFile(path: string, content: string): Promise<void>;
121
+ deleteFile(path: string): Promise<void>;
122
+ createDir(path: string): Promise<void>;
123
+ stat(path: string): Promise<FileMetadata>;
124
+ exists(path: string): Promise<boolean>;
125
+ isDirectory(path: string): Promise<boolean>;
126
+ isFile(path: string): Promise<boolean>;
127
+ /** List a directory, filtering out entries the policy hides. */
128
+ readDir(path: string): Promise<string[]>;
129
+ resolvePath(path: string, cwd?: string): string;
130
+ getCwd(): string;
131
+ /** Guard cwd too: the jail must never be able to "stand" on a denied/out-of-confine dir. */
132
+ setCwd(path: string): void;
133
+ }
134
+ /** Default denylist: secrets and VCS internals that must never be read or written.
135
+ * Patterns are matched case-insensitively (so /.ENV is covered too). */
136
+ declare const DEFAULT_DENY: string[];
137
+ declare class JailOptions {
138
+ /** Globs that are invisible and unwritable (secrets). */
139
+ deny: string[];
140
+ /** Globs readable but not writable/deletable (the pinned constitution). */
141
+ readonly: string[];
142
+ /** If set, only paths matching these globs are accessible at all. */
143
+ confineTo?: string[];
144
+ /** Audit hook fired on every blocked operation (drives the circuit breaker). */
145
+ onViolation?: (v: {
146
+ op: string;
147
+ path: string;
148
+ rule: string;
149
+ }) => void;
150
+ }
151
+
152
+ declare class OverlayFilesystem implements IFilesystem {
153
+ private base;
154
+ private st;
155
+ private snapshots;
156
+ private seq;
157
+ constructor(base: IFilesystem);
158
+ resolvePath(path: string, cwd?: string): string;
159
+ getCwd(): string;
160
+ setCwd(path: string): void;
161
+ private abs;
162
+ private parent;
163
+ private name;
164
+ readFile(path: string): Promise<string>;
165
+ exists(path: string): Promise<boolean>;
166
+ isFile(path: string): Promise<boolean>;
167
+ isDirectory(path: string): Promise<boolean>;
168
+ stat(path: string): Promise<FileMetadata>;
169
+ /** Merge base entries (minus tombstones) with overlay-created children of `path`. */
170
+ readDir(path: string): Promise<string[]>;
171
+ writeFile(path: string, content: string): Promise<void>;
172
+ createDir(path: string): Promise<void>;
173
+ deleteFile(path: string): Promise<void>;
174
+ private clone;
175
+ /** Capture the current overlay; returns a token to `rollback(token)` to. */
176
+ snapshot(label?: string): string;
177
+ /** Discard all changes since the named snapshot (or the most recent if omitted). */
178
+ rollback(token?: string): void;
179
+ /** Paths changed vs the base since this overlay was created (added = not in base, modified = was). */
180
+ diff(): Promise<{
181
+ added: string[];
182
+ modified: string[];
183
+ deleted: string[];
184
+ }>;
185
+ /** Flush the overlay into the base (writes, mkdirs, deletes), then clear the overlay. */
186
+ commit(): Promise<void>;
187
+ }
188
+ /** `Checkpoint` tool — snapshot the VFS before a risky multi-step change. */
189
+ declare const checkpointTool: AgentTool;
190
+ /** `Rollback` tool — undo all VFS changes since a Checkpoint. */
191
+ declare const rollbackTool: AgentTool;
192
+ declare const checkpointTools: () => AgentTool[];
193
+
194
+ interface Mount {
195
+ prefix: string;
196
+ fs: IFilesystem;
197
+ }
198
+ declare class MountFilesystem implements IFilesystem {
199
+ private root;
200
+ private mounts;
201
+ constructor(root: IFilesystem, mounts?: Mount[]);
202
+ resolvePath(path: string, cwd?: string): string;
203
+ getCwd(): string;
204
+ setCwd(path: string): void;
205
+ private abs;
206
+ /** Route an absolute VFS path to a backend + its path within that backend. */
207
+ private route;
208
+ /** Is `abs` strictly ABOVE a mount point (a synthesized dir the root may not have)? */
209
+ private isMountAncestor;
210
+ /** Immediate child segment names of `abs` that come from mounts (for readDir merge). */
211
+ private mountChildrenOf;
212
+ readFile(path: string): Promise<string>;
213
+ writeFile(path: string, content: string): Promise<void>;
214
+ deleteFile(path: string): Promise<void>;
215
+ createDir(path: string): Promise<void>;
216
+ exists(path: string): Promise<boolean>;
217
+ isDirectory(path: string): Promise<boolean>;
218
+ isFile(path: string): Promise<boolean>;
219
+ stat(path: string): Promise<FileMetadata>;
220
+ readDir(path: string): Promise<string[]>;
221
+ }
222
+
223
+ /**
224
+ * Speculative parallel attempts — a primitive uniquely cheap on a SWAPPABLE VFS.
225
+ *
226
+ * Fork the workspace into N copy-on-write overlays of the same `base`, run an attempt in
227
+ * each (independently — writes stay in each overlay, the base is untouched), score them,
228
+ * then COMMIT the best overlay into the base and DISCARD the losers (they leave no trace).
229
+ * Use it to race several approaches/seeds for a flaky or multi-path task and keep only the
230
+ * winner — something agents on a real, non-forkable filesystem can't do without copying the
231
+ * whole tree. Pairs naturally with subagents (each attempt is a child Agent over its overlay).
232
+ *
233
+ * `score` returns a higher-is-better number, or null to disqualify (e.g. failed grading).
234
+ */
235
+ interface Attempt<R> {
236
+ index: number;
237
+ fs: OverlayFilesystem;
238
+ result: R;
239
+ score: number | null;
240
+ }
241
+ declare function raceAttempts<R>(base: IFilesystem, n: number, run: (fs: IFilesystem, index: number) => Promise<R>, score: (a: {
242
+ fs: OverlayFilesystem;
243
+ result: R;
244
+ index: number;
245
+ }) => Promise<number | null> | number | null): Promise<{
246
+ winner: Attempt<R> | null;
247
+ attempts: Attempt<R>[];
248
+ }>;
249
+
250
+ /**
251
+ * Tool synthesis — compile a NEW agent tool from a spec the model authored. The unbounded
252
+ * frontier of self-evolution: the agent invents its own capabilities.
253
+ *
254
+ * SAFETY (this is the load-bearing part). A synthesized tool's `code` is arbitrary JS that
255
+ * runs IN-PROCESS over the agent's filesystem, so before compiling we statically REJECT a
256
+ * denylist of escape vectors (process/require/import/eval/Function/constructor/__proto__/
257
+ * globalThis/Bun/fetch/network/timers/WebAssembly/infinite-loops/…). A compiled tool sees
258
+ * ONLY its `args` and `ctx` (whose fs is the JailedFilesystem — boundary A); combined with
259
+ * the Agent's timeout/tool-call kill-switches this is defensible. Residual risk remains for
260
+ * a determined denylist bypass, so synthesized tools are OPT-IN and should additionally be
261
+ * self-tested in the sandbox (boundary B) before being trusted in a live loop. See mind/08.
262
+ */
263
+ interface ToolSpec {
264
+ name: string;
265
+ description: string;
266
+ parameters: object;
267
+ /** body of `async (args, ctx) => { … return <string> }` — may use args + ctx.fs ONLY. */
268
+ code: string;
269
+ }
270
+ /** Static safety gate. Returns the matched escape vectors (empty = code is allowed). */
271
+ declare function validateToolCode(code: string): {
272
+ ok: boolean;
273
+ violations: string[];
274
+ };
275
+ /**
276
+ * Compile a spec into an AgentTool — THROWS if the code fails the static safety gate.
277
+ * The body runs as `async (args, ctx) => { <code> }`; only `args` and `ctx` are in scope.
278
+ */
279
+ declare function compileSynthesizedTool(spec: ToolSpec): AgentTool;
280
+
281
+ /**
282
+ * Deterministic test/dev double for an ai.libx.js AIClient. Plays a scripted
283
+ * queue of ChatResponses (tool_calls then a final answer). Records each
284
+ * ChatOptions it saw so tests can assert tools were advertised and tool
285
+ * results were threaded back. No network, no API key.
286
+ */
287
+ declare class FakeAIClient implements ChatLike {
288
+ seen: ChatOptions[];
289
+ private script;
290
+ constructor(script: ChatResponse[]);
291
+ chat(options: ChatOptions): Promise<ChatResponse>;
292
+ }
293
+ /** Build a tool_call block (arguments JSON-stringified, matching the wire format). */
294
+ declare const toolCall: (id: string, name: string, args: object) => ToolCall;
295
+
296
+ /** Sandbox mode: an in-memory VFS — the real disk is never read or written. Edge/browser/test/dry-run. */
297
+ declare function sandboxAgentOptions(opts?: Partial<AgentOptions>): Partial<AgentOptions>;
298
+ /** Disk mode (the default): operate on the real filesystem, jailed to cwd (secrets hidden by DEFAULT_DENY).
299
+ * Omitting `fs` lets the Agent lazily resolve the jailed disk — this preset just makes the intent explicit
300
+ * (and is where you'd thread overrides). Pass an explicit `fs` to use a different backend. */
301
+ declare function diskAgentOptions(opts?: Partial<AgentOptions>): Partial<AgentOptions>;
302
+ /** Full mode: disk + a real `/bin/sh` tool (run installed binaries — git, bun, node, …) plus its
303
+ * background-job companions. NODE-ONLY: the real-shell module is dynamic-imported so this file stays
304
+ * edge-safe to import. `cwd` defaults to `process.cwd()`; secret env is scrubbed from spawned children. */
305
+ declare function fullAgentOptions(opts?: Partial<AgentOptions> & {
306
+ cwd?: string;
307
+ }): Promise<Partial<AgentOptions>>;
308
+
309
+ /** List paths matching a glob, sorted — the structured alternative to `find`. */
310
+ declare const globTool: AgentTool;
311
+ /** Search file contents by regex, returning typed `path:line:text` hits with optional context. */
312
+ declare const grepTool: AgentTool;
313
+ /**
314
+ * Compact map of a VFS — code signatures and/or doc outlines. Edge-safe (pure IFilesystem walk).
315
+ * `mode`: "code" (default) = top-level signatures; "docs" = heading outlines; "all" = both.
316
+ */
317
+ declare function repoIndex(fs: IFilesystem, glob?: string, mode?: 'code' | 'docs' | 'all'): Promise<string>;
318
+ /** Compact map of the codebase or document workspace — orient in ONE call, not many. */
319
+ declare const repoMapTool: AgentTool;
320
+ /** Create or overwrite a file, creating parent directories as needed (mkdir -p). */
321
+ declare const writeTool: AgentTool;
322
+ /** Apply an ordered list of exact-substring edits to one file in a single call. */
323
+ declare const multiEditTool: AgentTool;
324
+ /**
325
+ * Cross-file batch edit — the multi-file refactor primitive. One call edits MANY files:
326
+ * each entry with an `old_string` replaces that exact, UNIQUE substring (read fresh + verified,
327
+ * so NO prior Read is needed — locate the sites with Grep, whose output is the text to match);
328
+ * each entry WITHOUT `old_string` writes `new_string` as the whole file (creates it + parent dirs).
329
+ * Validate-all-before-write → atomic across files. Collapses "Grep + N×(Read+Edit)" into "Grep + ApplyEdits".
330
+ */
331
+ declare const applyEditsTool: AgentTool;
332
+ /** mkdir -p over the VFS (idempotent, top-down). */
333
+ declare function mkdirp(fs: IFilesystem, dir: string): Promise<void>;
334
+
335
+ /** Strip HTML to readable text — dependency-free: drop script/style/comments, block tags → newlines, decode common entities. */
336
+ declare function htmlToText(html: string): string;
337
+ interface WebFetchOptions {
338
+ /** Override the global fetch (tests inject a mock; edge runtimes can supply their own). */
339
+ fetch?: typeof globalThis.fetch;
340
+ maxBytes?: number;
341
+ maxChars?: number;
342
+ timeoutMs?: number;
343
+ /** Allow fetching private/loopback/link-local hosts (default false — blocks basic SSRF). */
344
+ allowPrivateHosts?: boolean;
345
+ }
346
+ /** Build a WebFetch tool. */
347
+ declare function makeWebFetchTool(options?: WebFetchOptions): AgentTool;
348
+ interface WebSearchOptions {
349
+ fetch?: typeof globalThis.fetch;
350
+ /** API key for the search provider (default: process.env.TAVILY_API_KEY). */
351
+ apiKey?: string;
352
+ /** Provider endpoint (default: Tavily, an agent-oriented search API). */
353
+ endpoint?: string;
354
+ maxResults?: number;
355
+ timeoutMs?: number;
356
+ }
357
+ /** Build a WebSearch tool backed by a configured provider (Tavily by default). */
358
+ declare function makeWebSearchTool(options?: WebSearchOptions): AgentTool;
359
+ /** Default instances (registered in the tool registry; opt-in by name). */
360
+ declare const webFetchTool: AgentTool;
361
+ declare const webSearchTool: AgentTool;
362
+
363
+ /**
364
+ * `AskUserQuestion` tool — lets the model pose a structured choice to a human.
365
+ * Delegates to `ctx.host.ask`. Registered only when a HostBridge is provided
366
+ * (autonomous runs don't see it), so it never dead-ends a headless agent.
367
+ */
368
+ declare const askUserQuestionTool: AgentTool;
369
+ /** Deterministic HostBridge for tests/dev: scripts answers + records what was asked. */
370
+ declare class ScriptedHostBridge implements HostBridge {
371
+ private answers;
372
+ private confirmDefault;
373
+ asked: UserQuestion[];
374
+ confirms: string[];
375
+ events: Array<{
376
+ kind: string;
377
+ message: string;
378
+ data?: unknown;
379
+ }>;
380
+ constructor(answers?: string[], confirmDefault?: boolean);
381
+ ask(q: UserQuestion): Promise<string>;
382
+ confirm(prompt: string): Promise<boolean>;
383
+ notify(event: {
384
+ kind: string;
385
+ message: string;
386
+ data?: unknown;
387
+ }): void;
388
+ }
389
+ /** Node CLI HostBridge: prompts on stdin. (node-only host adapter; not edge-safe by design.) */
390
+ declare class ConsoleHostBridge implements HostBridge {
391
+ ask(q: UserQuestion): Promise<string>;
392
+ confirm(prompt: string): Promise<boolean>;
393
+ notify(event: {
394
+ kind: string;
395
+ message: string;
396
+ }): void;
397
+ }
398
+
399
+ interface SkillInfo {
400
+ name: string;
401
+ description: string;
402
+ path: string;
403
+ }
404
+ /**
405
+ * Discover skills under `dir` (each `<dir>/<id>/SKILL.md`) and produce:
406
+ * - `catalog`: a names+descriptions block for the system prompt,
407
+ * - `tool`: a `Skill` tool that returns a skill's full SKILL.md (progressive disclosure).
408
+ *
409
+ * Skills are just VFS files — the Read tool already gives progressive disclosure; this
410
+ * adds the catalog + a convenience tool. (Executable skills can be `bash`-exec'd: wcli
411
+ * runs JS files from the VFS as commands.)
412
+ */
413
+ declare function loadSkills(fs: IFilesystem, dir: string | string[], opts?: {
414
+ relevanceHint?: string;
415
+ max?: number;
416
+ }): Promise<{
417
+ skills: SkillInfo[];
418
+ catalog: string;
419
+ tool?: AgentTool;
420
+ }>;
421
+
422
+ /**
423
+ * Lexical relevance — no deps, deterministic, edge-safe. Ranks catalog entries (skills,
424
+ * commands, memories, docs) by a task hint so a LARGE catalog doesn't dump every entry into
425
+ * the prompt. TF-IDF weighted: rare terms in the corpus score higher than common ones.
426
+ */
427
+ /** Lowercased alphanumeric tokens of length ≥ 3, minus a few stopwords. */
428
+ declare function tokenize(s: string): Set<string>;
429
+ /** Build IDF weights from a corpus of texts. Rare terms get higher weight. */
430
+ declare function idfWeights(corpus: string[]): Map<string, number>;
431
+ /** TF-IDF weighted relevance score. Without IDF, falls back to flat token overlap (backward-compatible). */
432
+ declare function relevanceScore(text: string, queryTokens: Set<string>, idf?: Map<string, number>): number;
433
+ /**
434
+ * Split `items` into the `k` most relevant to `query` (by TF-IDF overlap with `text(item)`)
435
+ * and the rest, preserving each item's original order within its group. Returns everything in
436
+ * `kept` (empty `rest`) when `items.length <= k` or `query` is blank — so it's a no-op for
437
+ * small lists. When `corpus` is provided, builds IDF weights for better ranking.
438
+ */
439
+ declare function topByRelevance<T>(items: T[], query: string, text: (x: T) => string, k: number, corpus?: string[]): {
440
+ kept: T[];
441
+ rest: T[];
442
+ };
443
+
444
+ interface CommandInfo {
445
+ name: string;
446
+ description: string;
447
+ path: string;
448
+ }
449
+ /**
450
+ * Expand a command template's argument placeholders:
451
+ * - `$ARGUMENTS` → all args (every occurrence)
452
+ * - `$1`…`$9` → positional args (whitespace-split; missing → empty)
453
+ * If the body has neither placeholder, `args` is appended as a trailing block (back-compat).
454
+ */
455
+ declare function expandTemplate(body: string, args: string): string;
456
+ /** Read a command file and return its expanded body: arg placeholders filled, then `@file` refs embedded. */
457
+ declare function expandCommand(fs: IFilesystem, cmd: CommandInfo, args: string): Promise<string>;
458
+ /**
459
+ * Discover slash commands under `dir` (each `<dir>/<name>.md`) and produce:
460
+ * - `catalog`: a names+descriptions block for the system prompt,
461
+ * - `tool`: a `SlashCommand` tool that returns a command's expanded template body.
462
+ *
463
+ * Commands are reusable prompt templates (like Claude Code slash commands) — just
464
+ * VFS files. The template body is returned (user args appended, and `$ARGUMENTS`
465
+ * substituted if present) so the model can act on it. Mirrors loadSkills.
466
+ */
467
+ declare function loadCommands(fs: IFilesystem, dir: string | string[], opts?: {
468
+ relevanceHint?: string;
469
+ max?: number;
470
+ }): Promise<{
471
+ commands: CommandInfo[];
472
+ catalog: string;
473
+ tool?: AgentTool;
474
+ }>;
475
+
476
+ /**
477
+ * Load memory for injection at run start (the recall step), with progressive disclosure:
478
+ * - `index`: the compact `<dir>/MEMORY.md` index, injected into the system prompt — cheap,
479
+ * always-hot. Each line points at a fact file the agent can pull on demand.
480
+ * - `tools`: `Recall` (load one fact body on demand — keeps facts COLD until needed) and
481
+ * `Remember` (persist a durable fact + index pointer mid-run — the WRITE half that closes
482
+ * the learning loop: what the agent learns now steers future sessions).
483
+ *
484
+ * Persistence is the BACKEND's job, for free: NodeDiskFilesystem → disk,
485
+ * IndexedDbFilesystem → browser, (planned) BodDbFilesystem → database. The same
486
+ * memory mechanism therefore works in node, a browser tab, or on edge.
487
+ */
488
+ declare function loadMemory(fs: IFilesystem, dir: string, opts?: {
489
+ relevanceHint?: string;
490
+ max?: number;
491
+ }): Promise<{
492
+ index: string;
493
+ tools: AgentTool[];
494
+ }>;
495
+ /** Slugify free text into a safe kebab filename stem (no separators, bounded). */
496
+ declare function slugify(s: string, fallback?: string): string;
497
+ /**
498
+ * Persist a durable fact: write `<dir>/<slug>.md` and ensure a one-line pointer exists in
499
+ * `<dir>/MEMORY.md` (created if missing). Idempotent on the index (won't duplicate a pointer).
500
+ * This is the shared write path behind the `Remember` tool and automatic lesson capture.
501
+ */
502
+ declare function writeFact(fs: IFilesystem, dir: string, slug: string, body: string): Promise<void>;
503
+
504
+ /**
505
+ * Automatic mistake → lesson → steer loop. Closes the within-run learning gap: the agent
506
+ * reacting to an error string is transient, but a RECURRING failure is a signal worth keeping.
507
+ * This hook watches tool results for known failure patterns; once the SAME pattern recurs
508
+ * `minRepeats` times in a run, it persists a corrective lesson to memory (deduped) — so the
509
+ * NEXT session's `loadMemory` injects it as steering. Deterministic, edge-safe, no LLM call.
510
+ *
511
+ * Writes immediately on crossing the threshold (not on a clean stop), so a loop/budget kill —
512
+ * exactly the runs that wasted effort — still leaves a lesson behind.
513
+ */
514
+ interface LessonOptions {
515
+ fs: IFilesystem;
516
+ /** Memory dir to persist lessons into (same dir loadMemory reads). */
517
+ dir: string;
518
+ /** How many times a pattern must recur before it's worth remembering. */
519
+ minRepeats: number;
520
+ }
521
+ declare class LessonOptionsDefaults implements Partial<LessonOptions> {
522
+ minRepeats: number;
523
+ }
524
+ /**
525
+ * Build a Hooks object that auto-captures recurring failures as memory lessons.
526
+ * Compose it with the host's own hooks via `composeHooks`.
527
+ */
528
+ declare function lessonCapture(options: LessonOptions): Hooks;
529
+
530
+ /**
531
+ * One-shot LLM reflection on a finished run. The deterministic `lessonCapture` hook only
532
+ * knows OUR pre-mapped failure patterns; reflection catches NOVEL mistakes — it reads a digest
533
+ * of what the run actually did and, if there's a durable lesson, persists it to memory so the
534
+ * next session is steered. Costs exactly ONE model call, so it's meant for runs that went badly
535
+ * (loop / budget / max_steps), not every run. Opt-in. Returns the slug written, or null.
536
+ */
537
+ interface ReflectOptions {
538
+ ai: ChatLike;
539
+ model: string;
540
+ /** Filesystem + memory dir to persist the lesson into (same dir loadMemory reads). */
541
+ fs: IFilesystem;
542
+ dir: string;
543
+ /** The finished run to reflect on. */
544
+ result: RunResult;
545
+ /** Bound the reflection prompt (chars of run digest). */
546
+ maxDigestChars?: number;
547
+ }
548
+ declare function reflectOnRun(o: ReflectOptions): Promise<string | null>;
549
+
550
+ /**
551
+ * Walk the VFS directory tree from `/` down, collecting instruction files
552
+ * (AGENT.md, AGENTS.md, CLAUDE.md, .claude/<name>) at each level.
553
+ * Merges all found files general-first → specific-last (mirrors Claude Code's
554
+ * hierarchical CLAUDE.md discovery). First matching filename per directory wins
555
+ * (no duplicates from the same level). Edge-portable: works over any IFilesystem.
556
+ */
557
+ declare function loadInstructions(fs: IFilesystem, names?: string[]): Promise<string>;
558
+
559
+ /**
560
+ * Typed subagents — named child-agent definitions from `<dir>/<name>.md`, each with a
561
+ * description, an optional model + tool allowlist (frontmatter), and a system prompt (the
562
+ * body). The `Task` tool's `agentType` selects one, so a delegated sub-task runs with its
563
+ * own persona, model, and scoped tools — the Claude-Code `.claude/agents` model.
564
+ * VFS-backed (edge-portable), mirroring loadSkills / loadCommands.
565
+ */
566
+ interface AgentDef {
567
+ name: string;
568
+ description: string;
569
+ /** The .md body — used as the child's system prompt (overrides the default). */
570
+ systemPrompt?: string;
571
+ /** Optional model override for this subagent type. */
572
+ model?: string;
573
+ /** Optional tool-name allowlist (scopes the child's tools). */
574
+ tools?: string[];
575
+ }
576
+ /** Discover subagent definitions under `dir` and a catalog block for the system prompt. */
577
+ declare function loadAgents(fs: IFilesystem, dir: string): Promise<{
578
+ agents: AgentDef[];
579
+ catalog: string;
580
+ }>;
581
+
582
+ interface TaskToolOptions {
583
+ /** The same ai.libx.js client the parent uses — the child shares it. */
584
+ ai: ChatLike;
585
+ model: string;
586
+ /** The filesystem the child operates over (jail/scope it before passing, if desired). */
587
+ fs: IFilesystem;
588
+ /** Step budget for the child run (independent of the parent's). */
589
+ maxSteps?: number;
590
+ /** Recursion depth of the child this tool would spawn (0 = first level). */
591
+ depth?: number;
592
+ /** Hard ceiling on nesting — beyond this the tool refuses to spawn. */
593
+ maxDepth?: number;
594
+ /** Named subagent types selectable via the `agentType` param (persona + model + scoped tools). */
595
+ agents?: AgentDef[];
596
+ /** Max children running concurrently in a `TaskBatch` (default 4). */
597
+ maxParallel?: number;
598
+ /** Parent hooks — `onSubagentStop` fires with each child's summary when it finishes. */
599
+ hooks?: Hooks;
600
+ }
601
+ /**
602
+ * `Task` tool — spawn a CHILD agent over the same VFS with its own step budget,
603
+ * returning only its final summary to the parent. Use to fan out a self-contained
604
+ * sub-task (search, refactor a subtree) without polluting the parent's context.
605
+ * @returns the child's final text, or an error string if the depth limit is reached.
606
+ */
607
+ declare function makeTaskTool(opts: TaskToolOptions): AgentTool;
608
+ /**
609
+ * `TaskBatch` tool — fan out several self-contained sub-tasks to child agents that run
610
+ * **concurrently** (bounded pool), returning all their summaries together. Each child runs over its
611
+ * OWN `OverlayFilesystem` (write-isolated from siblings), and successful children's edits are
612
+ * committed **in array order** afterward — so concurrent writes resolve deterministically
613
+ * (last index wins) instead of racing. Use to parallelize independent work (review N files, search M
614
+ * subtrees, scoped refactors). For a single sub-task, use `Task`.
615
+ */
616
+ declare function makeTaskBatchTool(opts: TaskToolOptions): AgentTool;
617
+
618
+ /** Component-scoped logger (libx.js). debug/verbose gated via DEBUG env/localStorage. */
619
+ declare const forComponent: (name: string) => libx_js_src_modules_log.ComponentLogger;
620
+
621
+ export { type AgentDef, AgentOptions, AgentTool, type Attempt, BodDbFilesystem, ChatLike, ChatOptions, ChatResponse, type CommandInfo, ConsoleHostBridge, DEFAULT_DENY, FakeAIClient, Hooks, HostBridge, JailOptions, JailedFilesystem, type LessonOptions, LessonOptionsDefaults, type Mount, MountFilesystem, NodeDiskFilesystem, OverlayFilesystem, type ReflectOptions, RunResult, ScriptedHostBridge, type SkillInfo, type TaskToolOptions, ToolCall, type ToolSpec, UserQuestion, type WebFetchOptions, type WebSearchOptions, applyEditsTool, askUserQuestionTool, checkpointTool, checkpointTools, compileSynthesizedTool, diskAgentOptions, expandCommand, expandTemplate, forComponent, fullAgentOptions, globTool, grepTool, htmlToText, idfWeights, lessonCapture, loadAgents, loadCommands, loadInstructions, loadMemory, loadSkills, makeTaskBatchTool, makeTaskTool, makeWebFetchTool, makeWebSearchTool, mkdirp, multiEditTool, raceAttempts, reflectOnRun, relevanceScore, repoIndex, repoMapTool, rollbackTool, sandboxAgentOptions, slugify, tokenize, toolCall, topByRelevance, validateToolCode, webFetchTool, webSearchTool, writeFact, writeTool };