@aigne/afs-agent 1.11.0-beta.13

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,754 @@
1
+ import { AFSAccessMode, AFSExecResult, AFSListResult, AFSModuleLoadParams, AFSRoot, AFSStatResult, ProviderManifest, SpaceResolver } from "@aigne/afs";
2
+ import { ToolEntry } from "@aigne/afs-ash";
3
+ import { AFSBaseProvider, RouteContext } from "@aigne/afs/provider";
4
+
5
+ //#region src/observability.d.ts
6
+ interface BaseEvent {
7
+ seq: number;
8
+ ts: number;
9
+ }
10
+ interface RunStartEvent extends BaseEvent {
11
+ type: "run.start";
12
+ runId: string;
13
+ blockletId: string | null;
14
+ userDid: string | null;
15
+ sessionId: string | null;
16
+ input: {
17
+ task: string;
18
+ model: string;
19
+ tools: Array<{
20
+ path: string;
21
+ ops: string[];
22
+ }>;
23
+ budget: Record<string, unknown>;
24
+ systemPrompt?: string;
25
+ };
26
+ /** Ownership routing telemetry (Phase 3c). Records the derived persistence
27
+ * class + resolved sink so observe-only migration can spot misrouted or
28
+ * dropped runs. Absent on legacy runtimes that don't inject the capability. */
29
+ ownership?: {
30
+ persistenceClass: "user" | "instance" | "ephemeral";
31
+ agentRunOrigin: "interactive" | "system";
32
+ ownershipRoutingMode: "observe-only" | "strict-user" | "strict-all";
33
+ instanceDid: string | null;
34
+ sinkKind: "afs" | "legacy-current-afs" | "none";
35
+ /** Why this sink was chosen — e.g. `user-direct-write`, or
36
+ * `user-missing:instanceDid …` when observe-only fell through to legacy
37
+ * probing. Lets migration spot misrouted runs without a drop (Phase 3e). */
38
+ sinkReason: string;
39
+ };
40
+ }
41
+ interface MessageEvent extends BaseEvent {
42
+ type: "message";
43
+ role: string;
44
+ content: unknown;
45
+ toolCalls?: unknown[];
46
+ callId?: string;
47
+ thoughts?: string;
48
+ }
49
+ interface TurnEvent extends BaseEvent {
50
+ type: "turn";
51
+ round: number;
52
+ model: string | null;
53
+ hub: string | null;
54
+ tokensIn: number;
55
+ tokensOut: number;
56
+ /** Prompt tokens served from the provider's cache for this round
57
+ * (Anthropic `cache_read_input_tokens`). 0 when caching wasn't hit
58
+ * or wasn't reported by the provider. */
59
+ tokensCached: number;
60
+ cost: number;
61
+ durationMs: number;
62
+ status: "ok" | "error";
63
+ errorMessage: string | null;
64
+ }
65
+ interface ToolEvent extends BaseEvent {
66
+ type: "tool";
67
+ round: number;
68
+ callId: string;
69
+ name: string;
70
+ path: string;
71
+ op: string;
72
+ args: unknown;
73
+ result: unknown;
74
+ status: "ok" | "error";
75
+ errorMessage: string | null;
76
+ durationMs: number;
77
+ }
78
+ interface CompressEvent extends BaseEvent {
79
+ type: "compress";
80
+ round: number;
81
+ compressed_messages: Array<Record<string, unknown>>;
82
+ archived_count: number;
83
+ before_tokens: number;
84
+ after_tokens: number;
85
+ }
86
+ interface RunEndEvent extends BaseEvent {
87
+ type: "run.end";
88
+ runId: string;
89
+ durationMs: number;
90
+ status: "ok" | "budget_exhausted" | "error";
91
+ result: {
92
+ data: unknown;
93
+ errorMessage: string | null;
94
+ };
95
+ totals: {
96
+ rounds: number;
97
+ totalTokensIn: number;
98
+ totalTokensOut: number;
99
+ totalCost: number;
100
+ modelsUsed: string[];
101
+ hubsUsed: string[];
102
+ toolsUsed: string[];
103
+ };
104
+ }
105
+ type LogEvent = RunStartEvent | MessageEvent | TurnEvent | ToolEvent | CompressEvent | RunEndEvent;
106
+ //#endregion
107
+ //#region src/agent-run.d.ts
108
+ interface AgentRunParams {
109
+ task: string;
110
+ model: string;
111
+ tools: ToolEntry[];
112
+ budget?: {
113
+ max_rounds?: number;
114
+ actions_per_round?: number;
115
+ total_tokens?: number; /** Model context window size (tokens). Used for compression threshold. */
116
+ context_window?: number; /** Max LLM call retry attempts on transient failures (default 3). */
117
+ max_retries?: number;
118
+ };
119
+ system?: string;
120
+ session?: string;
121
+ /** Skill directories to scan for SKILL.md files (e.g. ["/program/skills", "/data/skills"]) */
122
+ skillPaths?: string[];
123
+ /** Constrain LLM tool selection. "auto" (default) | "none" | "required" | <tool-name>.
124
+ * Mirrors aigne-framework's Router pattern; passed verbatim to the LLM. */
125
+ toolChoice?: string;
126
+ /** Extra args forwarded verbatim to every `callLLM` invocation. Used to pass
127
+ * AI Device routing hints (policy, requirements, exclusions, session, etc.)
128
+ * through to `/dev/ai/.actions/chat` without baking that vocabulary into
129
+ * agent-run itself. Keys collide-last with ash's own llmArgs (messages,
130
+ * tools, toolChoice, responseFormat, _onChunk) — those can't be overridden. */
131
+ modelArgs?: Record<string, unknown>;
132
+ /** AFS exec path (or { path, ...extraArgs }) for sending intermediate progress messages. */
133
+ onProgress?: string | {
134
+ path: string;
135
+ [key: string]: unknown;
136
+ };
137
+ /** In-process callback fired after each tool call with structured progress data. */
138
+ onToolProgress?: (event: ToolProgressEvent) => void;
139
+ /** AFS path to a JSON Schema file. When set, a `respond` tool is injected and the LLM's
140
+ * structured call to it becomes the result (as an object instead of a string). */
141
+ responseSchema?: string;
142
+ /** Shared execution context automatically merged into nested `args` of every exec tool call.
143
+ * Provides defaults for downstream actions (e.g. scheduler dispatch) without requiring
144
+ * the LLM to copy caller context manually. LLM-provided values always take priority. */
145
+ execContext?: Record<string, unknown>;
146
+ /** Parent session ID — when set, this run is a child of the given session.
147
+ * Used for session hierarchy derivation (S3). */
148
+ parentSession?: string;
149
+ /** Spawn chain — list of ancestor session IDs from root to current.
150
+ * Used for depth enforcement (S3). */
151
+ chain?: string[];
152
+ /** Parent proc ID from the calling blocklet — registers this run as a child of that proc. */
153
+ parentProcId?: string;
154
+ /** Parent agent info for template `$parent` variable (S4). */
155
+ parentAgentInfo?: {
156
+ name: string;
157
+ type: string;
158
+ session: string;
159
+ };
160
+ /** Abort signal from parent budget tracker. Checked at the start of each round;
161
+ * when aborted, the loop returns immediately preserving completed work. (S11) */
162
+ abortSignal?: AbortSignal;
163
+ /** When true, suppress the built-in AFS Discovery Protocol hint (which tells
164
+ * the LLM to "Start with `read /.knowledge`"). Use this for narrow-scope
165
+ * agents whose system prompt already specifies exact paths to read — the
166
+ * generic /.knowledge advice wastes rounds exploring the framework instead
167
+ * of following the agent's own instructions. */
168
+ skipAfsHint?: boolean;
169
+ /** Memory configuration. When set, recall is injected into the system message and
170
+ * memory tools are exposed to the LLM for active memory operations. */
171
+ memory?: {
172
+ /** AFS exec path for recall (e.g. "/modules/memory/.actions/recall"). */recallPath: string; /** Max tokens for memory injection into system message. Default: 2000. */
173
+ maxTokens?: number; /** Domain filter passed to recall. */
174
+ domain?: string;
175
+ /** AFS path pattern for memory tools (e.g. "/modules/memory/.actions/*").
176
+ * When set, memory actions (recall, remember, boost, feedback) are exposed as tools. */
177
+ toolsPath?: string;
178
+ /** AFS exec path for session archive (e.g. "/modules/memory/.actions/archive").
179
+ * When set, the conversation is archived to memory on completion. */
180
+ archivePath?: string;
181
+ };
182
+ /** Index configuration. When `scope` is set, agent-run auto-grants
183
+ * list+read on `/<mount-root>/domains/<scope>` so the agent can
184
+ * observe what's indexed (parallel to the memory.domain auto-grant).
185
+ * Mount root is derived from `queryPath` by stripping `/.actions/query`. */
186
+ index?: {
187
+ /** AFS exec path for query (e.g. "/modules/index/.actions/query"). */queryPath: string; /** Domain/scope for inspection grants. Without this, no auto-grant fires. */
188
+ scope?: string;
189
+ };
190
+ }
191
+ interface ToolProgressEvent {
192
+ type: "tool_start" | "tool_result" | "thinking" | "llm_start" | "llm_result" | "llm_delta" | "thinking_delta" | "summary" | "warning" | "compress_start" | "compress_result" | "subAgentMetadata";
193
+ round: number;
194
+ /** Nesting depth: 0 = root, 1 = child, 2 = grandchild, etc. (S9) */
195
+ depth: number;
196
+ /** Ancestor session chain from root to current run. (S9) */
197
+ chain: string[];
198
+ /** For tool_start/tool_result: array of tool calls in this batch. */
199
+ calls?: Array<{
200
+ id: string;
201
+ tool: string;
202
+ path: string;
203
+ status: "pending" | "ok" | "error";
204
+ error?: string;
205
+ args?: Record<string, unknown>;
206
+ result?: string;
207
+ }>;
208
+ /** For thinking: LLM's intermediate text. */
209
+ text?: string;
210
+ /** Resolved model name (llm_start, llm_result, summary). */
211
+ model?: string;
212
+ /** Retry attempt number, 1-based (llm_result on failure). */
213
+ attempt?: number;
214
+ /** Max retry attempts (llm_result). */
215
+ maxAttempts?: number;
216
+ /** Error message on LLM retry failure (llm_result). */
217
+ llmError?: string;
218
+ /** Delay before the next retry in milliseconds (llm_result on retryable failure). */
219
+ retryDelayMs?: number;
220
+ /** Accumulated token/cost totals (summary). */
221
+ tokens?: {
222
+ input: number;
223
+ output: number;
224
+ cached?: number;
225
+ cost?: number;
226
+ };
227
+ /** Context compression stats (compress_start, compress_result). */
228
+ compress?: {
229
+ phase: "triggered" | "summarizing" | "done" | "failed";
230
+ beforeTokens: number;
231
+ contextWindow: number;
232
+ compressedMessages: number;
233
+ keptMessages: number;
234
+ afterTokens?: number;
235
+ error?: string;
236
+ };
237
+ /** Sub-agent metadata extracted from child .actions/run result (subAgentMetadata). */
238
+ subAgentMeta?: Record<string, unknown>;
239
+ }
240
+ interface TraceEntry {
241
+ round: number;
242
+ tool_calls: Array<{
243
+ id: string;
244
+ name: string;
245
+ path: string;
246
+ status: "ok" | "error" | "circuit_breaker";
247
+ error?: string;
248
+ }>;
249
+ tokens: {
250
+ input: number;
251
+ output: number;
252
+ };
253
+ }
254
+ interface AgentRunResult {
255
+ status: "completed" | "budget_exhausted" | "error";
256
+ result?: string | Record<string, unknown>;
257
+ error?: string;
258
+ /** Detailed diagnostics when status is "error" (request summary + last response). */
259
+ detail?: {
260
+ request?: unknown;
261
+ lastResponse?: unknown;
262
+ };
263
+ rounds: number;
264
+ total_actions: number;
265
+ total_tokens: number;
266
+ /** B4 — count of successful nested .actions/run dispatches from this run. */
267
+ sub_runs: number;
268
+ trace: TraceEntry[];
269
+ /** Final accumulator snapshot (rounds, tokens, cost, models/hubs/tools used).
270
+ * Used by orchestration.ts to populate run.end event totals. */
271
+ totals?: TotalsSnapshot;
272
+ }
273
+ interface TotalsSnapshot {
274
+ rounds: number;
275
+ totalTokensIn: number;
276
+ totalTokensOut: number;
277
+ /** Sum of `usage.cacheReadInputTokens` across all rounds. Reflects how
278
+ * many prompt tokens were served from cache (Anthropic/etc. discount
279
+ * these). Surfaced in run.end totals so observability can show "X cache
280
+ * tokens reused" without re-walking turn events. */
281
+ totalCachedTokens: number;
282
+ totalCost: number;
283
+ modelsUsed: string[];
284
+ hubsUsed: string[];
285
+ toolsUsed: string[];
286
+ }
287
+ /** Message types for JSONL history (OpenAI canonical snake_case format) */
288
+ interface HistoryToolCall {
289
+ id: string;
290
+ type: "function";
291
+ function: {
292
+ name: string;
293
+ arguments: string;
294
+ };
295
+ }
296
+ type HistoryMessage = {
297
+ role: "user";
298
+ content: string;
299
+ createdAt?: string;
300
+ } | {
301
+ role: "assistant";
302
+ content: string;
303
+ tool_calls?: HistoryToolCall[];
304
+ createdAt?: string;
305
+ durationMs?: number;
306
+ } | {
307
+ role: "tool";
308
+ tool_call_id: string;
309
+ content: string | unknown[];
310
+ createdAt?: string;
311
+ durationMs?: number;
312
+ };
313
+ interface AgentRunDeps {
314
+ callLLM: (args: Record<string, unknown>) => Promise<AFSExecResult>;
315
+ runAsh: (source: string, args: Record<string, unknown>) => Promise<AFSExecResult>;
316
+ callAFS: (op: string, path: string, args?: Record<string, unknown>) => Promise<AFSExecResult>;
317
+ /** Test seam for retry backoff; production uses abort-aware setTimeout. */
318
+ sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
319
+ loadHistory?: (sessionPath: string) => Promise<HistoryMessage[]>;
320
+ /** Append new messages to working history (history.jsonl). */
321
+ appendHistory?: (sessionPath: string, messages: HistoryMessage[]) => Promise<void>;
322
+ /** Rewrite working history with compressed messages (called only on compression). */
323
+ rewriteHistory?: (sessionPath: string, messages: HistoryMessage[]) => Promise<void>;
324
+ /** Archive compressed messages to a timestamped file (called only on compression). */
325
+ archiveHistory?: (sessionPath: string, messages: HistoryMessage[]) => Promise<void>;
326
+ /** Observability: emit a single jsonl event to the run's log file.
327
+ * Provided by orchestration.ts; absent when no log destination is wired up
328
+ * (e.g. CLI direct call without `_scope_afs`). */
329
+ emit?: (event: LogEvent) => Promise<void>;
330
+ /** Observability: per-run monotonic seq counter. Owned by orchestration.ts. */
331
+ nextSeq?: () => number;
332
+ }
333
+ declare function computeLLMRetryDelayMs(error: string, failedAttempt: number): number;
334
+ declare function runAgentLoop(params: AgentRunParams, deps: AgentRunDeps): Promise<AgentRunResult>;
335
+ //#endregion
336
+ //#region src/ash-generator.d.ts
337
+ /**
338
+ * ASH source generator for agent-run.
339
+ *
340
+ * Converts validated tool_calls into a single ASH program
341
+ * with @caps scoped to the exact paths in this round's calls.
342
+ */
343
+ interface ValidatedToolCall {
344
+ id: string;
345
+ op: "read" | "list" | "exec";
346
+ path: string;
347
+ args: Record<string, unknown>;
348
+ }
349
+ /**
350
+ * Generate a complete ASH program from validated tool calls.
351
+ *
352
+ * Each call becomes a separate pipeline within a single job.
353
+ * The program is scoped with @caps derived from actual paths.
354
+ */
355
+ declare function generateAsh(calls: ValidatedToolCall[], round: number): string;
356
+ //#endregion
357
+ //#region src/context.d.ts
358
+ interface ContextMemoryOptions {
359
+ /** AFS exec path for recall (e.g. "/modules/memory/.actions/recall"). */
360
+ recallPath: string;
361
+ /** Max tokens for memory injection into system message. Default: 2000. */
362
+ maxTokens?: number;
363
+ /** Domain filter passed to recall. */
364
+ domain?: string;
365
+ }
366
+ interface ContextOptions {
367
+ /** Current user input / task. */
368
+ task: string;
369
+ /** System prompt (role, persona, instructions). */
370
+ system?: string;
371
+ /** Conversation history messages (passed through as-is). */
372
+ history?: Array<Record<string, unknown>>;
373
+ /** Memory recall configuration. Omit to disable memory. */
374
+ memory?: ContextMemoryOptions;
375
+ /** Additional directives appended to system message (e.g. STOP_DIRECTIVE, AFS_HINT). */
376
+ directives?: string[];
377
+ }
378
+ interface MemoryTraceEntry {
379
+ tokens: number;
380
+ entries: number;
381
+ sources: string[];
382
+ }
383
+ interface ContextManifest {
384
+ memory: {
385
+ selected: string[];
386
+ query?: string;
387
+ available?: number;
388
+ };
389
+ history: {
390
+ keptTurns: number;
391
+ truncatedTurns: number;
392
+ compressed: boolean;
393
+ };
394
+ tools: {
395
+ included: string[];
396
+ };
397
+ }
398
+ interface ContextTrace {
399
+ system: {
400
+ tokens: number;
401
+ };
402
+ memory: MemoryTraceEntry | null;
403
+ history: {
404
+ tokens: number;
405
+ messages: number;
406
+ };
407
+ user: {
408
+ tokens: number;
409
+ };
410
+ total: number;
411
+ manifest?: ContextManifest;
412
+ }
413
+ interface ContextResult {
414
+ messages: Array<{
415
+ role: string;
416
+ content: string;
417
+ [key: string]: unknown;
418
+ }>;
419
+ trace: ContextTrace;
420
+ }
421
+ /**
422
+ * Assemble a messages array for LLM calls.
423
+ *
424
+ * Output order: [system, ...history, user]
425
+ *
426
+ * System message = system prompt + memory recall + directives.
427
+ * Without memory, output is identical to agent-run's current hand-assembled messages.
428
+ * Memory failures silently fall back to the no-memory path.
429
+ */
430
+ declare function buildContext(afs: AFSRoot, opts: ContextOptions): Promise<ContextResult>;
431
+ //#endregion
432
+ //#region src/context-compress.d.ts
433
+ /**
434
+ * Check if messages need compression and compress if necessary.
435
+ *
436
+ * Returns the original messages array (same reference) if no compression is needed,
437
+ * or a new array with compressed messages if compression was performed.
438
+ *
439
+ * Compression is best-effort: if callLLM fails, returns original messages unchanged.
440
+ * When compression succeeds, calls `onCompressed` with the new messages for history rewrite.
441
+ *
442
+ * Note: compression LLM call token usage is NOT counted toward agent-run's total_tokens budget.
443
+ * This is intentional — compression is a meta-operation, not a user-facing LLM interaction.
444
+ */
445
+ /** Progress info emitted during compression. */
446
+ interface CompressProgress {
447
+ phase: "triggered" | "summarizing" | "done" | "skipped" | "failed";
448
+ /** Estimated tokens before compression. */
449
+ beforeTokens: number;
450
+ /** Context window size. */
451
+ contextWindow: number;
452
+ /** Number of messages being compressed (triggered/summarizing/done). */
453
+ compressedMessages?: number;
454
+ /** Number of messages kept (triggered/summarizing/done). */
455
+ keptMessages?: number;
456
+ /** Estimated tokens after compression (done only). */
457
+ afterTokens?: number;
458
+ /** Error message (failed only). */
459
+ error?: string;
460
+ }
461
+ declare function maybeCompress(messages: Array<Record<string, unknown>>, opts: {
462
+ contextWindow?: number;
463
+ /**
464
+ * Anchor message that must be preserved verbatim across compressions
465
+ * (typically the current user task). Identified by object reference.
466
+ * If the anchor falls in the compress zone, it is excluded from the
467
+ * summary and re-inserted between the system message and the summary
468
+ * so the LLM always sees a clear "what the user asked" anchor.
469
+ */
470
+ pinMessage?: Record<string, unknown>;
471
+ callLLM: (args: Record<string, unknown>) => Promise<AFSExecResult>;
472
+ onCompressed?: (compressedMessages: Array<Record<string, unknown>>, archivedMessages: Array<Record<string, unknown>>) => Promise<void>;
473
+ onProgress?: (info: CompressProgress) => void;
474
+ }): Promise<Array<Record<string, unknown>>>;
475
+ //#endregion
476
+ //#region src/messages-log.d.ts
477
+ /**
478
+ * Append-only JSONL message log for inter-agent communication (L3).
479
+ *
480
+ * Provider internal: direct fs calls are allowed here (see CLAUDE.md).
481
+ */
482
+ interface MessageEntry {
483
+ message_id: string;
484
+ from: string;
485
+ to: string;
486
+ kind: string;
487
+ ts: string;
488
+ seq: number;
489
+ body: unknown;
490
+ }
491
+ declare function appendMessage(filePath: string, from: string, to: string, body: unknown, kind?: string): MessageEntry;
492
+ declare function readMessages(filePath: string, options?: {
493
+ since?: string;
494
+ limit?: number;
495
+ }): MessageEntry[];
496
+ declare function resetSeqCounter(): void;
497
+ //#endregion
498
+ //#region src/observability-routing.d.ts
499
+ type OwnershipRoutingMode = "observe-only" | "strict-user" | "strict-all";
500
+ //#endregion
501
+ //#region src/orchestration.d.ts
502
+ /**
503
+ * Resolve a user-provided model identifier into an absolute AFS path.
504
+ *
505
+ * - `/foo/bar` → verbatim (after `..` / `.` normalization, rejected if
506
+ * any path segment is `.` or `..`).
507
+ * - `gpt-4o` → `/dev/ai/hubs/aignehub/models/gpt-4o`.
508
+ *
509
+ * The returned path may either point at a model NODE (e.g.
510
+ * `/dev/ai/hubs/aignehub/models/gpt-4o`) or directly at a chat-action
511
+ * leaf (e.g. `/dev/ai/.actions/chat`). The caller distinguishes via
512
+ * regex on `/.actions/(chat|embed|image|video)$`.
513
+ */
514
+ declare function resolveAgentModelPath(model: string): string;
515
+ /**
516
+ * Normalize tool calls to AIGNE format: { id, type: "function", function: { name, arguments } }.
517
+ *
518
+ * Accepts Vercel AI SDK ({ toolCallId, toolName, args }),
519
+ * OpenAI ({ id, type, function: { name, arguments: string } }),
520
+ * or already-normalized AIGNE format.
521
+ */
522
+ declare function normalizeToolCallsToAIGNE(toolCalls: Array<Record<string, unknown>>): Array<Record<string, unknown>>;
523
+ /**
524
+ * Runtime-supplied observability capability, injected into `AFSAgent` at
525
+ * construction by the host runtime (Node / CF) as an *object capability*.
526
+ *
527
+ * Crucially this is NEVER serialized into the JSON `AFSContext`, the agent's
528
+ * LLM-visible args, or any client-facing response. The `spaceResolver` handle
529
+ * lets the writer (Phase 3c) resolve a per-principal trace sink without the
530
+ * caller being able to name or forge a space.
531
+ */
532
+ interface ObservabilityRuntime {
533
+ /** Space selector for per-principal trace sinks (Phase 2 contract). Absent
534
+ * ⇒ user-class writes fail-closed in Phase 3c (no `/instance` fallback). */
535
+ spaceResolver?: SpaceResolver;
536
+ /** Where anonymous interactive runs persist: `"instance"` (Node — lands in
537
+ * the instance slice) or `"ephemeral"` (CF — not persisted). */
538
+ anonymousInteractivePersistence: "instance" | "ephemeral";
539
+ /** Fail-closed stage (Phase 3e). Defaults to `"observe-only"` when absent. */
540
+ ownershipRoutingMode?: OwnershipRoutingMode;
541
+ }
542
+ interface ExecuteAgentRunOptions {
543
+ /** AFS root used for stat / exec / read / write. Defaults to the
544
+ * caller-supplied `_scope_afs` arg if present, else `globalAfs`. */
545
+ globalAfs?: AFSRoot;
546
+ /** AFS path under which the ash provider is mounted. The `runAsh` dep
547
+ * uses `${ashMountPath}/.actions/run` to delegate ash DSL execution.
548
+ * Default: `/ash`. */
549
+ ashMountPath?: string;
550
+ /** Trusted caller context from RouteContext.context (AFSContext, populated
551
+ * server-side in Phase 3a — never client-forgeable). As of Phase 3c it
552
+ * DRIVES ownership routing: `caller.did` (userId = legacy mirror) →
553
+ * persistence class, `instanceDid` → the DID-Space column, `agentRunOrigin`
554
+ * → system vs interactive. `blockletId`/`sessionId` enrich the trace record
555
+ * and the legacy instance-class probing. */
556
+ callerContext?: {
557
+ userId?: string;
558
+ blockletId?: string;
559
+ sessionId?: string;
560
+ caller?: {
561
+ did?: string | null;
562
+ } | null;
563
+ instanceDid?: string;
564
+ agentRunOrigin?: "interactive" | "system";
565
+ [key: string]: unknown;
566
+ };
567
+ /** Observability runtime capability (Phase 3b). Injected by the host at
568
+ * provider construction and threaded here so the writer (Phase 3c) can
569
+ * resolve per-principal trace sinks. Object capability — never serialized
570
+ * into JSON context or LLM-visible args. Unconsumed in 3b (capability
571
+ * injection only); the writer wires it in 3c. */
572
+ observabilityRuntime?: ObservabilityRuntime;
573
+ }
574
+ /**
575
+ * The full args → result pipeline. Same contract as the legacy
576
+ * `executeAgentRunImpl` method that used to live on AFSAsh, but as a
577
+ * standalone function with explicit deps.
578
+ *
579
+ * Does NOT enqueue on a session queue — that's the caller's job (see
580
+ * AFSAgent). Throws on validation failures (bad task / bad model)
581
+ * and returns an `AFSExecResult` envelope on runtime failures.
582
+ */
583
+ declare function executeAgentRun(args: Record<string, unknown>, options?: ExecuteAgentRunOptions): Promise<AFSExecResult>;
584
+ //#endregion
585
+ //#region src/provider.d.ts
586
+ interface AFSAgentOptions {
587
+ name?: string;
588
+ description?: string;
589
+ /**
590
+ * AFS path under which the ash provider is mounted. The `runAsh` dep
591
+ * inside agent-run delegates ash DSL execution to
592
+ * `${ashMountPath}/.actions/run`. Default `/ash` matches the canonical
593
+ * system mount.
594
+ */
595
+ ashMountPath?: string;
596
+ /**
597
+ * Maximum queued agent-run calls per session. Default 20.
598
+ */
599
+ maxSessionQueueDepth?: number;
600
+ /**
601
+ * Observability runtime capability (Phase 3b). The host runtime injects a
602
+ * `SpaceResolver` + anonymous-persistence policy here at construction so the
603
+ * writer (Phase 3c) can route each run's trace to the correct owning
604
+ * principal's space. This is an *object capability*: it is never read from
605
+ * the config JSON (`load`/`manifest.schema` ignore it) and never serialized
606
+ * into any client-visible context or LLM args.
607
+ */
608
+ observabilityRuntime?: ObservabilityRuntime;
609
+ }
610
+ declare class AFSAgent extends AFSBaseProvider {
611
+ static manifest(): ProviderManifest;
612
+ static load({
613
+ config
614
+ }?: AFSModuleLoadParams): Promise<AFSAgent>;
615
+ readonly name: string;
616
+ readonly description?: string;
617
+ readonly accessMode: AFSAccessMode;
618
+ private readonly ashMountPath;
619
+ private readonly sessionQueue;
620
+ private readonly observabilityRuntime?;
621
+ private afsRoot?;
622
+ constructor(options?: AFSAgentOptions);
623
+ onMount(afs: AFSRoot): void;
624
+ destroy(): void;
625
+ statRoot(_ctx: RouteContext): Promise<AFSStatResult>;
626
+ statRunAction(_ctx: RouteContext): Promise<AFSStatResult>;
627
+ listRootActions(_ctx: RouteContext): Promise<AFSListResult>;
628
+ execRootAction(ctx: RouteContext<{
629
+ action: string;
630
+ }>, args: Record<string, unknown>): Promise<AFSExecResult>;
631
+ /**
632
+ * Handler for the test-only `__debug-runtime` action (Phase 3b). Returns a
633
+ * boolean/string projection of the injected `observabilityRuntime` so E2E
634
+ * tests can assert the capability reached `/dev/agent` — but it deliberately
635
+ * omits the `spaceResolver` handle itself (object capability must not leave
636
+ * the host). Outside `AFS_TEST_MODE` it refuses with `AFS_PERMISSION` so
637
+ * production never exposes runtime wiring.
638
+ */
639
+ private execDebugRuntime;
640
+ }
641
+ //#endregion
642
+ //#region src/scratchpad.d.ts
643
+ /**
644
+ * Scratchpad provisioning — allocates per-run scratch directories under
645
+ * a session-scoped memory path.
646
+ *
647
+ * Provider internal: direct fs calls are allowed here (see CLAUDE.md).
648
+ */
649
+ interface ScratchLayout {
650
+ basePath: string;
651
+ stateYml: string;
652
+ messagesJsonl: string;
653
+ eventsJsonl: string;
654
+ historyJsonl: string;
655
+ }
656
+ type ScratchRetention = "run" | "session" | "forever";
657
+ declare function allocateScratch(memoryBasePath: string, session: string, runId: string): ScratchLayout;
658
+ declare function getStateProxy(layout: ScratchLayout): Record<string, any>;
659
+ declare function teardownSession(memoryBasePath: string, session: string, retention?: ScratchRetention): void;
660
+ //#endregion
661
+ //#region src/session-queue.d.ts
662
+ /**
663
+ * Per-key Promise chain queue for serializing async operations.
664
+ *
665
+ * Used by ASHProvider to ensure same-session agent-run calls execute
666
+ * sequentially, preventing history file race conditions.
667
+ */
668
+ declare function deriveChildSession(parentSessionId: string): string;
669
+ declare function createSessionQueue(maxDepth?: number): {
670
+ queues: Map<string, Promise<unknown>>;
671
+ depths: Map<string, number>;
672
+ /**
673
+ * Enqueue an async function for serial execution within a session.
674
+ *
675
+ * - If session is undefined, executes directly (no queuing).
676
+ * - If the session queue is full, throws an Error with message starting with "QUEUE_FULL".
677
+ * - Otherwise, chains onto the session's Promise tail and awaits the result.
678
+ */
679
+ enqueue<T>(session: string | undefined, fn: () => Promise<T>): Promise<T>; /** Clear all queue state. Does not await in-progress executions. */
680
+ destroy(): void;
681
+ };
682
+ //#endregion
683
+ //#region src/spawn-depth.d.ts
684
+ declare function checkSpawnDepth(chain: string[], manifestMax?: number): void;
685
+ //#endregion
686
+ //#region src/token-estimator.d.ts
687
+ /**
688
+ * Lightweight token estimation based on character types.
689
+ *
690
+ * Uses empirical heuristics for CJK characters, English words, and other characters
691
+ * to approximate token counts without requiring an external tokenizer.
692
+ */
693
+ /**
694
+ * Estimate token count for a text string.
695
+ *
696
+ * Uses character-type-aware heuristics:
697
+ * - CJK characters: ~1.5 chars per token
698
+ * - English words: ~1 token per word
699
+ * - Other characters (punctuation, digits, whitespace): ~1 char per token
700
+ */
701
+ declare function estimateTokens(text: string): number;
702
+ /**
703
+ * Estimate total tokens for an array of messages (OpenAI format).
704
+ *
705
+ * Handles:
706
+ * - `content` (string) — text tokens, capped per message
707
+ * - `toolCalls` / `tool_calls` — function name + arguments + structure overhead
708
+ *
709
+ * @param singleMessageLimit - Max tokens counted per individual message content
710
+ * (prevents a single huge tool result from dominating the estimate)
711
+ */
712
+ declare function estimateMessagesTokens(messages: Array<Record<string, unknown>>, singleMessageLimit?: number): number;
713
+ //#endregion
714
+ //#region src/tool-schema.d.ts
715
+ interface OpenAITool {
716
+ type: "function";
717
+ function: {
718
+ name: string;
719
+ description: string;
720
+ parameters: {
721
+ type: "object";
722
+ properties: Record<string, Record<string, unknown>>;
723
+ required: string[];
724
+ };
725
+ };
726
+ }
727
+ /** Discovered action schema from startup discovery phase. */
728
+ interface ActionSchema {
729
+ actionName: string;
730
+ description: string;
731
+ pathPattern: string;
732
+ inputSchema?: {
733
+ type?: string;
734
+ properties?: Record<string, Record<string, unknown> & {
735
+ type: string;
736
+ description?: string;
737
+ }>;
738
+ required?: string[];
739
+ };
740
+ }
741
+ /**
742
+ * Build OpenAI function-calling tools from ToolEntry declarations.
743
+ *
744
+ * Deduplicates operations across entries — one tool per unique op.
745
+ * Each tool's path description lists all allowed patterns for that op.
746
+ *
747
+ * When actionSchemas are provided (from startup discovery), generates
748
+ * per-action tools (afs_action_{name}) with explicit typed parameters
749
+ * so LLMs know exactly what fields each action requires.
750
+ */
751
+ declare function buildToolSchema(tools: ToolEntry[], actionSchemas?: ActionSchema[]): OpenAITool[];
752
+ //#endregion
753
+ export { AFSAgent, type AFSAgentOptions, type ActionSchema, type AgentRunDeps, type AgentRunParams, type AgentRunResult, type ContextManifest, type ContextMemoryOptions, type ContextOptions, type ExecuteAgentRunOptions, type HistoryMessage, type HistoryToolCall, type MemoryTraceEntry, type MessageEntry, type ScratchLayout, type ScratchRetention, type ToolProgressEvent, type TraceEntry, type ValidatedToolCall, allocateScratch, appendMessage, buildContext, buildToolSchema, checkSpawnDepth, computeLLMRetryDelayMs, createSessionQueue, deriveChildSession, estimateMessagesTokens, estimateTokens, executeAgentRun, generateAsh, getStateProxy, maybeCompress, normalizeToolCallsToAIGNE, readMessages, resetSeqCounter, resolveAgentModelPath, runAgentLoop, teardownSession };
754
+ //# sourceMappingURL=index.d.mts.map