@axlsdk/axl 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -6
- package/dist/index.cjs +2257 -569
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1191 -114
- package/dist/index.d.ts +1191 -114
- package/dist/index.js +2248 -569
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -274,26 +274,493 @@ type RaceOptions<T = unknown> = {
|
|
|
274
274
|
};
|
|
275
275
|
/** Execution status */
|
|
276
276
|
type ExecutionStatus = 'running' | 'completed' | 'failed' | 'waiting';
|
|
277
|
-
/**
|
|
278
|
-
type
|
|
277
|
+
/**
|
|
278
|
+
* Canonical list of `AxlEvent.type` discriminators. Single source of truth —
|
|
279
|
+
* derive `AxlEventType` from this tuple and use it to validate stream filters,
|
|
280
|
+
* redaction tables, and exhaustiveness assertions.
|
|
281
|
+
*/
|
|
282
|
+
declare const AXL_EVENT_TYPES: readonly ["workflow_start", "workflow_end", "ask_start", "ask_end", "agent_call_start", "agent_call_end", "token", "tool_call_start", "tool_call_end", "tool_approval", "tool_denied", "delegate", "handoff_start", "handoff_return", "pipeline", "partial_object", "verify", "log", "memory_remember", "memory_recall", "memory_forget", "checkpoint_save", "checkpoint_replay", "await_human", "await_human_resolved", "guardrail", "schema_check", "validate", "done", "error"];
|
|
283
|
+
/** Discriminator union derived from `AXL_EVENT_TYPES`. */
|
|
284
|
+
type AxlEventType = (typeof AXL_EVENT_TYPES)[number];
|
|
285
|
+
/** Resolved model parameters sent to the provider for an LLM call. */
|
|
286
|
+
type AgentCallParams = {
|
|
287
|
+
temperature?: number;
|
|
288
|
+
maxTokens?: number;
|
|
289
|
+
effort?: Effort;
|
|
290
|
+
thinkingBudget?: number;
|
|
291
|
+
includeThoughts?: boolean;
|
|
292
|
+
toolChoice?: ToolChoice;
|
|
293
|
+
stop?: string[];
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* Data shape for `agent_call_start` events — the **request** side of the call.
|
|
297
|
+
* Everything here is known at the moment the call is dispatched, before the
|
|
298
|
+
* provider responds. Consumers can render "what's being asked" without waiting
|
|
299
|
+
* for completion.
|
|
300
|
+
*/
|
|
301
|
+
type AgentCallStartData = {
|
|
302
|
+
/** Original user prompt passed to `ctx.ask()`. Does not include retry feedback or tool results. */
|
|
303
|
+
prompt: string;
|
|
304
|
+
/** Resolved system prompt (after evaluating dynamic system selectors). */
|
|
305
|
+
system?: string;
|
|
306
|
+
/** Resolved model parameters sent to the provider for this call. */
|
|
307
|
+
params?: AgentCallParams;
|
|
308
|
+
/** 1-indexed iteration of the tool-calling loop for this `ctx.ask()` call. */
|
|
309
|
+
turn: number;
|
|
310
|
+
/** When set, this call is a retry triggered by a failed gate check on the previous turn. */
|
|
311
|
+
retryReason?: 'schema' | 'validate' | 'guardrail';
|
|
312
|
+
/** Names of tools exposed to the model on this call. Empty/omitted when no tools are bound. */
|
|
313
|
+
toolNames?: string[];
|
|
314
|
+
/** Full ChatMessage[] sent to the provider this turn. Only populated when `trace.level === 'full'`. */
|
|
315
|
+
messages?: ChatMessage[];
|
|
316
|
+
};
|
|
317
|
+
/**
|
|
318
|
+
* Data shape for `agent_call_end` events — the **response** side of the call.
|
|
319
|
+
* Populated when the provider returns (success or recoverable failure). The
|
|
320
|
+
* companion request-side payload lives on the matching `agent_call_start`.
|
|
321
|
+
*
|
|
322
|
+
* Pair invariant: every `agent_call_start` is followed by exactly one
|
|
323
|
+
* `agent_call_end`, even on provider error. On the error path `response` is
|
|
324
|
+
* empty and `error` carries the provider's message; cost/tokens/duration are
|
|
325
|
+
* still emitted (top-level on the event) when partial usage is available.
|
|
326
|
+
*/
|
|
327
|
+
type AgentCallEndData = {
|
|
328
|
+
/** Final LLM response content for this turn. Empty string on error. */
|
|
329
|
+
response: string;
|
|
330
|
+
/** Reasoning/thinking content returned by the provider, when available. */
|
|
331
|
+
thinking?: string;
|
|
332
|
+
/** 1-indexed iteration of the tool-calling loop. Mirrors the matching `agent_call_start.data.turn`. */
|
|
333
|
+
turn: number;
|
|
334
|
+
/** Mirrors `agent_call_start.data.retryReason` so cost-attribution consumers
|
|
335
|
+
* reading `agent_call_end` (cost lives here) can bucket without joining. */
|
|
336
|
+
retryReason?: 'schema' | 'validate' | 'guardrail';
|
|
337
|
+
/** Provider error message when the call threw (network failure, 4xx/5xx,
|
|
338
|
+
* abort, etc). Mutually exclusive with `response` content. Subject to
|
|
339
|
+
* `config.trace.redact` (vendor errors can echo prompt text). */
|
|
340
|
+
error?: string;
|
|
341
|
+
};
|
|
342
|
+
/** Data shape for `tool_call_end` events. */
|
|
343
|
+
type ToolCallData = {
|
|
344
|
+
args: unknown;
|
|
345
|
+
result: unknown;
|
|
346
|
+
callId?: string;
|
|
347
|
+
};
|
|
348
|
+
/** Data shape for `tool_call_start` events. */
|
|
349
|
+
type ToolCallStartData = {
|
|
350
|
+
args: unknown;
|
|
351
|
+
};
|
|
352
|
+
/** Data shape for `tool_approval` events. Emitted by the approval gate on both outcomes. */
|
|
353
|
+
type ToolApprovalData = {
|
|
354
|
+
approved: boolean;
|
|
355
|
+
args: unknown;
|
|
356
|
+
reason?: string;
|
|
357
|
+
};
|
|
358
|
+
/** Data shape for `tool_denied` events. Emitted when the LLM names a tool the agent doesn't expose. */
|
|
359
|
+
type ToolDeniedData = {
|
|
360
|
+
args?: unknown;
|
|
361
|
+
reason?: string;
|
|
362
|
+
callId?: string;
|
|
363
|
+
};
|
|
364
|
+
/** Data shape for `handoff_start` events (always emitted, pre-transition). */
|
|
365
|
+
type HandoffStartData = {
|
|
366
|
+
source: string;
|
|
367
|
+
target: string;
|
|
368
|
+
mode: 'oneway' | 'roundtrip';
|
|
369
|
+
/** The `message` arg the source agent passed when invoking `handoff_to_X`
|
|
370
|
+
* (roundtrip mode only). Subject to `config.trace.redact`. */
|
|
371
|
+
message?: string;
|
|
372
|
+
};
|
|
373
|
+
/** Data shape for `handoff_return` events (roundtrip-only, post-return).
|
|
374
|
+
* The returned value itself is observable via the target ask's
|
|
375
|
+
* `ask_end.outcome`; this event marks the control transfer back to the
|
|
376
|
+
* source agent and carries the round-trip duration. */
|
|
377
|
+
type HandoffReturnData = {
|
|
378
|
+
source: string;
|
|
379
|
+
target: string;
|
|
380
|
+
/** Wall-clock ms from `handoff_start` emission to control returning. */
|
|
381
|
+
duration: number;
|
|
382
|
+
};
|
|
383
|
+
/** Data shape for `delegate` events. */
|
|
384
|
+
type DelegateData = {
|
|
385
|
+
candidates: string[];
|
|
386
|
+
/** Set when the decision is known at emission time (single-agent short-circuit). */
|
|
387
|
+
selected?: string;
|
|
388
|
+
/** Router model used for multi-agent routing. */
|
|
389
|
+
routerModel?: string;
|
|
390
|
+
/** Why this delegate was emitted: 'routed' (multi-agent) or 'single_candidate'. */
|
|
391
|
+
reason: 'routed' | 'single_candidate';
|
|
392
|
+
};
|
|
393
|
+
/** Data shape for `verify` events. */
|
|
394
|
+
type VerifyData = {
|
|
395
|
+
attempts: number;
|
|
396
|
+
passed: boolean;
|
|
397
|
+
lastError?: string;
|
|
398
|
+
};
|
|
399
|
+
/** Data shape for legacy `guardrail` events. Replaced by `pipeline` in PR 2. */
|
|
400
|
+
type GuardrailData = {
|
|
401
|
+
guardrailType: 'input' | 'output';
|
|
402
|
+
blocked: boolean;
|
|
403
|
+
reason?: string;
|
|
404
|
+
attempt?: number;
|
|
405
|
+
maxAttempts?: number;
|
|
406
|
+
feedbackMessage?: string;
|
|
407
|
+
};
|
|
408
|
+
/** Data shape for legacy `schema_check` events. Replaced by `pipeline` in PR 2. */
|
|
409
|
+
type SchemaCheckData = {
|
|
410
|
+
valid: boolean;
|
|
411
|
+
reason?: string;
|
|
412
|
+
attempt: number;
|
|
413
|
+
maxAttempts: number;
|
|
414
|
+
feedbackMessage?: string;
|
|
415
|
+
};
|
|
416
|
+
/** Data shape for legacy `validate` events. Replaced by `pipeline` in PR 2. */
|
|
417
|
+
type ValidateData = {
|
|
418
|
+
valid: boolean;
|
|
419
|
+
reason?: string;
|
|
420
|
+
attempt: number;
|
|
421
|
+
maxAttempts: number;
|
|
422
|
+
feedbackMessage?: string;
|
|
423
|
+
};
|
|
424
|
+
/** Data shape for `workflow_start` events. Emitted once per workflow execution. */
|
|
425
|
+
type WorkflowStartData = {
|
|
426
|
+
/** The validated input passed to the workflow handler. */
|
|
427
|
+
input: unknown;
|
|
428
|
+
};
|
|
429
|
+
/** Data shape for `workflow_end` events. Emitted once per workflow execution
|
|
430
|
+
* on completion, failure, or cancellation. Distinguish cancellation via `aborted`. */
|
|
431
|
+
type WorkflowEndData = {
|
|
432
|
+
status: 'completed' | 'failed';
|
|
433
|
+
duration: number;
|
|
434
|
+
/** Workflow return value. Present on `status: 'completed'`. */
|
|
435
|
+
result?: unknown;
|
|
436
|
+
/** Error message. Present on `status: 'failed'`. */
|
|
437
|
+
error?: string;
|
|
438
|
+
/** True when the failure was an `AbortError` (user cancellation, budget hard_stop,
|
|
439
|
+
* or consumer disconnect on streaming workflows). */
|
|
440
|
+
aborted?: boolean;
|
|
441
|
+
};
|
|
442
|
+
/** Data shape for `checkpoint_save` / `checkpoint_replay` events.
|
|
443
|
+
* Emitted by `ctx.checkpoint(name, fn)` — `save` on first execution,
|
|
444
|
+
* `replay` when a saved value short-circuits the function call. */
|
|
445
|
+
type CheckpointEventData = {
|
|
446
|
+
/** Stable, caller-supplied identifier under which the checkpoint is
|
|
447
|
+
* stored. Internal auto-checkpoints from ask/spawn/race/parallel/map
|
|
448
|
+
* use names prefixed with `__auto/<primitive>/`. */
|
|
449
|
+
name: string;
|
|
450
|
+
};
|
|
451
|
+
/** Data shape for `await_human` events — emitted when execution suspends
|
|
452
|
+
* for a human decision via `ctx.awaitHuman()`. The pending side of the
|
|
453
|
+
* pair; `await_human_resolved` follows when the decision arrives. */
|
|
454
|
+
type AwaitHumanData = {
|
|
455
|
+
/** Optional human-facing prompt describing the decision needed. */
|
|
456
|
+
prompt?: string;
|
|
457
|
+
/** Channel routing the decision (e.g., 'slack', 'email', custom). */
|
|
458
|
+
channel?: string;
|
|
459
|
+
};
|
|
460
|
+
/** Data shape for `await_human_resolved` events — paired terminal of an
|
|
461
|
+
* `await_human` request. Carries the `HumanDecision` returned to the workflow. */
|
|
462
|
+
type AwaitHumanResolvedData = {
|
|
463
|
+
channel?: string;
|
|
464
|
+
decision: HumanDecision;
|
|
465
|
+
};
|
|
466
|
+
/** Data shape for `memory_remember` / `memory_recall` / `memory_forget` events. */
|
|
467
|
+
type MemoryEventData = {
|
|
468
|
+
scope: string;
|
|
469
|
+
key?: string;
|
|
470
|
+
/** Result count for `recall` (number of vectors returned). */
|
|
471
|
+
count?: number;
|
|
472
|
+
/** Embedder cost for semantic recall/remember. Mirrored at the top-level
|
|
473
|
+
* `cost` on the event so cost rails (`trackExecution`) pick it up. */
|
|
474
|
+
cost?: number;
|
|
475
|
+
/** Embedder usage detail (tokens / model). */
|
|
476
|
+
usage?: {
|
|
477
|
+
tokens?: number;
|
|
478
|
+
cost?: number;
|
|
479
|
+
model?: string;
|
|
480
|
+
};
|
|
481
|
+
/** True when this memory op called the semantic recall path (vs. key-only). */
|
|
482
|
+
embed?: boolean;
|
|
483
|
+
/** True when a key-only recall returned a value / semantic call path. */
|
|
484
|
+
semantic?: boolean;
|
|
485
|
+
/** True when a key-only recall returned a value. */
|
|
486
|
+
hit?: boolean;
|
|
487
|
+
/** Result count for `recall` (alias for `count` retained for back-compat). */
|
|
488
|
+
resultCount?: number;
|
|
489
|
+
/** Error message when the operation failed on the partial-failure path. */
|
|
490
|
+
error?: string;
|
|
491
|
+
};
|
|
492
|
+
/** Common fields carried by every `AxlEvent` regardless of `type`. */
|
|
493
|
+
type AxlEventBase = {
|
|
279
494
|
executionId: string;
|
|
495
|
+
/** Monotonic per-execution step counter, shared across nested asks via ALS. */
|
|
280
496
|
step: number;
|
|
281
|
-
|
|
497
|
+
/** Wall-clock ms. */
|
|
498
|
+
timestamp: number;
|
|
499
|
+
/** Workflow this event belongs to. Auto-stamped by `emitEvent` from
|
|
500
|
+
* `this.workflowName` when defined; callers may override. */
|
|
282
501
|
workflow?: string;
|
|
502
|
+
/** Optional emitting-agent name. Variants that always have an agent
|
|
503
|
+
* (e.g., `agent_call_start/end`) redeclare it as required so consumers
|
|
504
|
+
* narrowing on those variants get a non-optional `agent`. Single-point
|
|
505
|
+
* events that may or may not have an agent (`handoff`, gate events,
|
|
506
|
+
* `log`) keep the optional. */
|
|
283
507
|
agent?: string;
|
|
284
|
-
|
|
285
|
-
promptVersion?: string;
|
|
508
|
+
/** Optional model URI — set on agent-related events; ignored on others. */
|
|
286
509
|
model?: string;
|
|
510
|
+
/** Optional prompt version stamped from `agent._config.version`. */
|
|
511
|
+
promptVersion?: string;
|
|
512
|
+
/**
|
|
513
|
+
* Cost (USD) contributed by this event.
|
|
514
|
+
*
|
|
515
|
+
* Two DIFFERENT semantics ship on this field and consumers must know
|
|
516
|
+
* which they're reading:
|
|
517
|
+
*
|
|
518
|
+
* - **Leaf cost** (`agent_call_end`, `tool_call_end`, `memory_remember`,
|
|
519
|
+
* `memory_recall`): the authoritative charge for this single
|
|
520
|
+
* provider call / tool invocation / embedder call. Summing these
|
|
521
|
+
* across an execution gives the true spend.
|
|
522
|
+
*
|
|
523
|
+
* - **Per-ask rollup** (`ask_end`): the SUM of leaf costs emitted
|
|
524
|
+
* within this ask's frame, EXCLUDING nested asks (which roll up
|
|
525
|
+
* into their own `ask_end`). Spec/16 decision 10.
|
|
526
|
+
*
|
|
527
|
+
* **If you write your own accumulator, DO NOT do `total += event.cost`
|
|
528
|
+
* across all event types — you'll double-count every ask** because the
|
|
529
|
+
* leaves AND the rollup both carry `cost`. Use the exported
|
|
530
|
+
* `eventCostContribution(event)` helper from `@axlsdk/axl` instead:
|
|
531
|
+
* it encapsulates the "skip ask_end, finite-check, leaf-only" rule in
|
|
532
|
+
* one place so your accumulator stays in lockstep with the built-in
|
|
533
|
+
* `runtime.trackExecution`, `ExecutionInfo.totalCost`, and Studio's
|
|
534
|
+
* cost aggregator.
|
|
535
|
+
*
|
|
536
|
+
* Other variants may stamp `cost` optionally to flow into cost rails
|
|
537
|
+
* (e.g., memory ops mirror `usage.cost` here). Review UX-8.
|
|
538
|
+
*/
|
|
287
539
|
cost?: number;
|
|
540
|
+
/** Token counts. Required-by-narrowing on `agent_call_end`; optional on
|
|
541
|
+
* any event that wishes to mirror an aggregate. Scope is agent prompt /
|
|
542
|
+
* completion / reasoning tokens ONLY — embedder tokens live in
|
|
543
|
+
* `memory_*.data.usage.tokens` and are deliberately NOT summed into
|
|
544
|
+
* this field (different pricing, different model, different category). */
|
|
288
545
|
tokens?: {
|
|
289
546
|
input?: number;
|
|
290
547
|
output?: number;
|
|
291
548
|
reasoning?: number;
|
|
292
549
|
};
|
|
550
|
+
/** Duration in ms (set on `_end` variants and a few single-point events). */
|
|
293
551
|
duration?: number;
|
|
294
|
-
data?: unknown;
|
|
295
|
-
timestamp: number;
|
|
296
552
|
};
|
|
553
|
+
/** Fields on every event that originates within a specific `ctx.ask()` call. */
|
|
554
|
+
type AskScoped = {
|
|
555
|
+
askId: string;
|
|
556
|
+
/** Absent on root ask. */
|
|
557
|
+
parentAskId?: string;
|
|
558
|
+
/** 0 = root ask; +1 per nested ask. */
|
|
559
|
+
depth: number;
|
|
560
|
+
/** Emitting agent's name. Absent on `ask_start` (pre-resolution) and on
|
|
561
|
+
* events that predate agent resolution. */
|
|
562
|
+
agent?: string;
|
|
563
|
+
};
|
|
564
|
+
/**
|
|
565
|
+
* Meta carried alongside callback invocations (`onToken`, `onAgentStart`,
|
|
566
|
+
* `onToolCall`) so consumers can group/route by ask.
|
|
567
|
+
*
|
|
568
|
+
* Note: `agent` is **required** here (the callback is always invoked
|
|
569
|
+
* inside an ALS frame that has the agent name already resolved). On the
|
|
570
|
+
* event side (`AskScoped.agent`) the field is optional — events emitted
|
|
571
|
+
* before agent resolution (e.g., `ask_start` is fired before the
|
|
572
|
+
* dynamic agent selector runs) can land without it.
|
|
573
|
+
*/
|
|
574
|
+
type CallbackMeta = {
|
|
575
|
+
askId: string;
|
|
576
|
+
parentAskId?: string;
|
|
577
|
+
depth: number;
|
|
578
|
+
agent: string;
|
|
579
|
+
};
|
|
580
|
+
/**
|
|
581
|
+
* Unified event union. Replaces the old `TraceEvent` (rich, persisted) and
|
|
582
|
+
* `StreamEvent` (lean, wire) by emitting a single rich event from one site
|
|
583
|
+
* and consuming the same shape on both rails.
|
|
584
|
+
*
|
|
585
|
+
* - Streaming consumers iterate `AxlStream` (an `AsyncIterable<AxlEvent>`).
|
|
586
|
+
* - Non-streaming consumers read `ExecutionInfo.events: AxlEvent[]`.
|
|
587
|
+
*
|
|
588
|
+
* Tree reconstruction: group ask-scoped events by `askId`, parent-link via
|
|
589
|
+
* `parentAskId`, sort by `step`, render by `depth`. Tokens (high-volume) and
|
|
590
|
+
* `partial_object` events are stream-only — never persisted to
|
|
591
|
+
* `ExecutionInfo.events`.
|
|
592
|
+
*
|
|
593
|
+
* When adding a new variant, extend `AXL_EVENT_TYPES` AND the emitter in
|
|
594
|
+
* `WorkflowContext.emitEvent()` together so the compiler catches drift; the
|
|
595
|
+
* exhaustiveness fixture in `__tests__/axl-event-exhaustive.test-d.ts` will
|
|
596
|
+
* also fail until the new case is handled.
|
|
597
|
+
*/
|
|
598
|
+
type AxlEvent = (AxlEventBase & {
|
|
599
|
+
type: 'workflow_start';
|
|
600
|
+
workflow: string;
|
|
601
|
+
data: WorkflowStartData;
|
|
602
|
+
}) | (AxlEventBase & {
|
|
603
|
+
type: 'workflow_end';
|
|
604
|
+
workflow: string;
|
|
605
|
+
data: WorkflowEndData;
|
|
606
|
+
}) | (AxlEventBase & AskScoped & {
|
|
607
|
+
type: 'ask_start';
|
|
608
|
+
prompt: string;
|
|
609
|
+
}) | (AxlEventBase & AskScoped & {
|
|
610
|
+
type: 'ask_end';
|
|
611
|
+
/** Discriminated outcome — narrow on `outcome.ok`. Ask-internal throws
|
|
612
|
+
* surface here, NOT via the workflow-level `error` event. */
|
|
613
|
+
outcome: {
|
|
614
|
+
ok: true;
|
|
615
|
+
result: unknown;
|
|
616
|
+
} | {
|
|
617
|
+
ok: false;
|
|
618
|
+
error: string;
|
|
619
|
+
};
|
|
620
|
+
/** Sum of `agent_call_end.cost` + `tool_call_end.cost` WITHIN THIS ASK,
|
|
621
|
+
* excluding nested asks. Nested asks contribute to their own ask_end. */
|
|
622
|
+
cost: number;
|
|
623
|
+
duration: number;
|
|
624
|
+
}) | (AxlEventBase & AskScoped & {
|
|
625
|
+
type: 'agent_call_start';
|
|
626
|
+
agent: string;
|
|
627
|
+
model: string;
|
|
628
|
+
/** 1-indexed tool-calling loop iteration within the ask. */
|
|
629
|
+
turn: number;
|
|
630
|
+
/** Request-side payload — prompt, system, params, messages, retry context. */
|
|
631
|
+
data: AgentCallStartData;
|
|
632
|
+
}) | (AxlEventBase & AskScoped & {
|
|
633
|
+
type: 'agent_call_end';
|
|
634
|
+
agent: string;
|
|
635
|
+
model: string;
|
|
636
|
+
/** Authoritative turn-level cost. */
|
|
637
|
+
cost: number;
|
|
638
|
+
duration: number;
|
|
639
|
+
tokens?: {
|
|
640
|
+
input?: number;
|
|
641
|
+
output?: number;
|
|
642
|
+
reasoning?: number;
|
|
643
|
+
};
|
|
644
|
+
/** Response-side payload — response text, thinking. */
|
|
645
|
+
data: AgentCallEndData;
|
|
646
|
+
}) | (AxlEventBase & AskScoped & {
|
|
647
|
+
type: 'token';
|
|
648
|
+
data: string;
|
|
649
|
+
}) | (AxlEventBase & AskScoped & {
|
|
650
|
+
type: 'tool_call_start';
|
|
651
|
+
tool: string;
|
|
652
|
+
callId: string;
|
|
653
|
+
data: ToolCallStartData;
|
|
654
|
+
}) | (AxlEventBase & AskScoped & {
|
|
655
|
+
type: 'tool_call_end';
|
|
656
|
+
tool: string;
|
|
657
|
+
callId: string;
|
|
658
|
+
duration: number;
|
|
659
|
+
cost?: number;
|
|
660
|
+
data: ToolCallData;
|
|
661
|
+
}) | (AxlEventBase & AskScoped & {
|
|
662
|
+
type: 'tool_approval';
|
|
663
|
+
tool: string;
|
|
664
|
+
callId?: string;
|
|
665
|
+
data: ToolApprovalData;
|
|
666
|
+
}) | (AxlEventBase & AskScoped & {
|
|
667
|
+
type: 'tool_denied';
|
|
668
|
+
tool: string;
|
|
669
|
+
callId?: string;
|
|
670
|
+
data?: ToolDeniedData;
|
|
671
|
+
}) | (AxlEventBase & AskScoped & {
|
|
672
|
+
type: 'delegate';
|
|
673
|
+
data: DelegateData;
|
|
674
|
+
}) | (AxlEventBase & {
|
|
675
|
+
type: 'handoff_start';
|
|
676
|
+
fromAskId: string;
|
|
677
|
+
toAskId: string;
|
|
678
|
+
sourceDepth: number;
|
|
679
|
+
targetDepth: number;
|
|
680
|
+
data: HandoffStartData;
|
|
681
|
+
}) | (AxlEventBase & {
|
|
682
|
+
type: 'handoff_return';
|
|
683
|
+
fromAskId: string;
|
|
684
|
+
toAskId: string;
|
|
685
|
+
sourceDepth: number;
|
|
686
|
+
targetDepth: number;
|
|
687
|
+
data: HandoffReturnData;
|
|
688
|
+
}) | (AxlEventBase & AskScoped & {
|
|
689
|
+
type: 'pipeline';
|
|
690
|
+
status: 'start';
|
|
691
|
+
stage: 'initial' | 'schema' | 'validate' | 'guardrail';
|
|
692
|
+
attempt: number;
|
|
693
|
+
maxAttempts: number;
|
|
694
|
+
}) | (AxlEventBase & AskScoped & {
|
|
695
|
+
type: 'pipeline';
|
|
696
|
+
status: 'failed';
|
|
697
|
+
stage: 'schema' | 'validate' | 'guardrail';
|
|
698
|
+
attempt: number;
|
|
699
|
+
maxAttempts: number;
|
|
700
|
+
/** Feedback message about to be injected into the conversation. */
|
|
701
|
+
reason: string;
|
|
702
|
+
}) | (AxlEventBase & AskScoped & {
|
|
703
|
+
type: 'pipeline';
|
|
704
|
+
status: 'committed';
|
|
705
|
+
/** The stage of the most recent `pipeline(start)` — `'initial'` when
|
|
706
|
+
* the ask committed on the first pass, otherwise the gate that last
|
|
707
|
+
* retried before commit. Lets consumers tell "committed cleanly"
|
|
708
|
+
* from "committed after a schema/validate/guardrail retry". */
|
|
709
|
+
stage: 'initial' | 'schema' | 'validate' | 'guardrail';
|
|
710
|
+
/** The final successful attempt. */
|
|
711
|
+
attempt: number;
|
|
712
|
+
maxAttempts: number;
|
|
713
|
+
}) | (AxlEventBase & AskScoped & {
|
|
714
|
+
type: 'partial_object';
|
|
715
|
+
attempt: number;
|
|
716
|
+
/** DeepPartial<T>; consumers cast at the render site. */
|
|
717
|
+
data: {
|
|
718
|
+
object: unknown;
|
|
719
|
+
};
|
|
720
|
+
}) | (AxlEventBase & AskScoped & {
|
|
721
|
+
type: 'verify';
|
|
722
|
+
data: VerifyData;
|
|
723
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
724
|
+
type: 'guardrail';
|
|
725
|
+
data?: GuardrailData;
|
|
726
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
727
|
+
type: 'schema_check';
|
|
728
|
+
data?: SchemaCheckData;
|
|
729
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
730
|
+
type: 'validate';
|
|
731
|
+
data?: ValidateData;
|
|
732
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
733
|
+
type: 'log';
|
|
734
|
+
data: unknown;
|
|
735
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
736
|
+
type: 'memory_remember' | 'memory_recall' | 'memory_forget';
|
|
737
|
+
data: MemoryEventData;
|
|
738
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
739
|
+
type: 'checkpoint_save' | 'checkpoint_replay';
|
|
740
|
+
data: CheckpointEventData;
|
|
741
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
742
|
+
type: 'await_human';
|
|
743
|
+
data: AwaitHumanData;
|
|
744
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
745
|
+
type: 'await_human_resolved';
|
|
746
|
+
data: AwaitHumanResolvedData;
|
|
747
|
+
}) | (AxlEventBase & {
|
|
748
|
+
type: 'done';
|
|
749
|
+
data: {
|
|
750
|
+
result: unknown;
|
|
751
|
+
};
|
|
752
|
+
}) | (AxlEventBase & Partial<AskScoped> & {
|
|
753
|
+
type: 'error';
|
|
754
|
+
data: {
|
|
755
|
+
message: string;
|
|
756
|
+
name?: string;
|
|
757
|
+
code?: string;
|
|
758
|
+
};
|
|
759
|
+
});
|
|
760
|
+
/** Convenience: extract the union member matching a given `type` discriminator. */
|
|
761
|
+
type AxlEventOf<T extends AxlEventType> = Extract<AxlEvent, {
|
|
762
|
+
type: T;
|
|
763
|
+
}>;
|
|
297
764
|
/** Result of a guardrail check. */
|
|
298
765
|
type GuardrailResult = {
|
|
299
766
|
block: boolean;
|
|
@@ -335,7 +802,10 @@ type ExecutionInfo = {
|
|
|
335
802
|
executionId: string;
|
|
336
803
|
workflow: string;
|
|
337
804
|
status: ExecutionStatus;
|
|
338
|
-
|
|
805
|
+
/** Full event timeline. Tokens and `partial_object` events are NOT persisted
|
|
806
|
+
* here (stream-only); aggregate `tokens: { input, output, reasoning? }`
|
|
807
|
+
* on `agent_call_end` is the persisted token representation. */
|
|
808
|
+
events: AxlEvent[];
|
|
339
809
|
totalCost: number;
|
|
340
810
|
startedAt: number;
|
|
341
811
|
completedAt?: number;
|
|
@@ -343,57 +813,26 @@ type ExecutionInfo = {
|
|
|
343
813
|
result?: unknown;
|
|
344
814
|
error?: string;
|
|
345
815
|
};
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
} | {
|
|
360
|
-
type: 'tool_approval';
|
|
361
|
-
name: string;
|
|
362
|
-
args: unknown;
|
|
363
|
-
approved: boolean;
|
|
364
|
-
reason?: string;
|
|
365
|
-
} | {
|
|
366
|
-
type: 'agent_start';
|
|
367
|
-
agent: string;
|
|
368
|
-
model?: string;
|
|
369
|
-
} | {
|
|
370
|
-
type: 'agent_end';
|
|
371
|
-
agent: string;
|
|
372
|
-
cost?: number;
|
|
373
|
-
duration?: number;
|
|
374
|
-
} | {
|
|
375
|
-
type: 'handoff';
|
|
376
|
-
source: string;
|
|
377
|
-
target: string;
|
|
378
|
-
mode?: 'oneway' | 'roundtrip';
|
|
379
|
-
} | {
|
|
380
|
-
type: 'step';
|
|
381
|
-
step: number;
|
|
382
|
-
data: unknown;
|
|
383
|
-
} | {
|
|
384
|
-
type: 'done';
|
|
385
|
-
data: unknown;
|
|
386
|
-
} | {
|
|
387
|
-
type: 'error';
|
|
388
|
-
message: string;
|
|
389
|
-
};
|
|
390
|
-
/** Record of an agent handoff event (persisted in session metadata). */
|
|
816
|
+
/** Record of an agent handoff event (persisted in session metadata).
|
|
817
|
+
*
|
|
818
|
+
* `duration` semantics:
|
|
819
|
+
* - `oneway`: target's full ask duration (start-to-completion).
|
|
820
|
+
* - `roundtrip`: full round-trip wall-clock (handoff_start → handoff_return),
|
|
821
|
+
* includes the time to push the result back into the source's
|
|
822
|
+
* conversation. Both measurements are populated by the
|
|
823
|
+
* runtime once the corresponding event fires; if the target
|
|
824
|
+
* never completes (workflow aborted mid-handoff), `duration`
|
|
825
|
+
* stays undefined.
|
|
826
|
+
*
|
|
827
|
+
* `toAskId` is the askId of the target frame — lets consumers correlate
|
|
828
|
+
* the record to the target's `ask_end` event in the trace stream. */
|
|
391
829
|
type HandoffRecord = {
|
|
392
830
|
source: string;
|
|
393
831
|
target: string;
|
|
394
832
|
mode: 'oneway' | 'roundtrip';
|
|
395
833
|
timestamp: number;
|
|
396
834
|
duration?: number;
|
|
835
|
+
toAskId?: string;
|
|
397
836
|
};
|
|
398
837
|
/** Information about a completed agent call, emitted via onAgentCallComplete. */
|
|
399
838
|
type AgentCallInfo = {
|
|
@@ -533,12 +972,8 @@ type ExecutionState = {
|
|
|
533
972
|
* Redis (production).
|
|
534
973
|
*/
|
|
535
974
|
interface StateStore {
|
|
536
|
-
saveCheckpoint(executionId: string,
|
|
537
|
-
getCheckpoint(executionId: string,
|
|
538
|
-
getLatestCheckpoint(executionId: string): Promise<{
|
|
539
|
-
step: number;
|
|
540
|
-
data: unknown;
|
|
541
|
-
} | null>;
|
|
975
|
+
saveCheckpoint(executionId: string, name: string, data: unknown): Promise<void>;
|
|
976
|
+
getCheckpoint(executionId: string, name: string): Promise<unknown | null>;
|
|
542
977
|
saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
|
|
543
978
|
getSession(sessionId: string): Promise<ChatMessage[]>;
|
|
544
979
|
deleteSession(sessionId: string): Promise<void>;
|
|
@@ -651,9 +1086,49 @@ interface VectorStore {
|
|
|
651
1086
|
delete(ids: string[]): Promise<void>;
|
|
652
1087
|
close?(): Promise<void>;
|
|
653
1088
|
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Usage info reported by an embedder for a single `embed()` call.
|
|
1091
|
+
*
|
|
1092
|
+
* Mirrors the provider `usage` namespace — nested rather than flat so
|
|
1093
|
+
* future additions (latency, cache-hit info, rate-limit headers) extend
|
|
1094
|
+
* this type without breaking the `Embedder` return shape.
|
|
1095
|
+
*
|
|
1096
|
+
* All fields are optional so embedders without cost/pricing knowledge
|
|
1097
|
+
* (e.g. local models, self-hosted) can still conform to the interface.
|
|
1098
|
+
*/
|
|
1099
|
+
type EmbedUsage = {
|
|
1100
|
+
/** Total input tokens consumed. */
|
|
1101
|
+
tokens?: number;
|
|
1102
|
+
/** Cost in USD, computed from tokens × per-model pricing. */
|
|
1103
|
+
cost?: number;
|
|
1104
|
+
/** The underlying model identifier (e.g. "text-embedding-3-small"). */
|
|
1105
|
+
model?: string;
|
|
1106
|
+
};
|
|
1107
|
+
/**
|
|
1108
|
+
* Result of an `Embedder.embed()` call.
|
|
1109
|
+
*
|
|
1110
|
+
* Always contains `vectors`. `usage` is optional so embedders can omit
|
|
1111
|
+
* it entirely (non-OpenAI, local, test fakes).
|
|
1112
|
+
*/
|
|
1113
|
+
type EmbedResult = {
|
|
1114
|
+
vectors: number[][];
|
|
1115
|
+
usage?: EmbedUsage;
|
|
1116
|
+
};
|
|
654
1117
|
/** Embedder interface for converting text to vectors. */
|
|
655
1118
|
interface Embedder {
|
|
656
|
-
|
|
1119
|
+
/**
|
|
1120
|
+
* Embed one or more texts into vectors.
|
|
1121
|
+
*
|
|
1122
|
+
* @param texts Input strings to embed.
|
|
1123
|
+
* @param signal Optional `AbortSignal` — when triggered, the underlying
|
|
1124
|
+
* network call should abort. Passed through from
|
|
1125
|
+
* `ctx.remember` / `ctx.recall` so user cancellation and
|
|
1126
|
+
* hard_stop budget aborts propagate to the embedder fetch.
|
|
1127
|
+
* Impls are free to ignore it (the call just runs to
|
|
1128
|
+
* completion like before), but OpenAIEmbedder honors it
|
|
1129
|
+
* via `fetchWithRetry`.
|
|
1130
|
+
*/
|
|
1131
|
+
embed(texts: string[], signal?: AbortSignal): Promise<EmbedResult>;
|
|
657
1132
|
readonly dimensions: number;
|
|
658
1133
|
}
|
|
659
1134
|
/** Memory configuration. */
|
|
@@ -691,6 +1166,27 @@ type StateConfig = {
|
|
|
691
1166
|
sqlite?: {
|
|
692
1167
|
path: string;
|
|
693
1168
|
};
|
|
1169
|
+
/**
|
|
1170
|
+
* Maximum number of events retained in `ExecutionInfo.events` per
|
|
1171
|
+
* execution. Token and partial_object events are already excluded
|
|
1172
|
+
* from the array (high-volume, stream-only); this cap bounds the
|
|
1173
|
+
* remaining structural events (`agent_call_*`, `tool_call_*`, gate
|
|
1174
|
+
* events, pipeline, etc).
|
|
1175
|
+
*
|
|
1176
|
+
* Pathological workloads (e.g., 50 nested asks × 20-turn tool loops)
|
|
1177
|
+
* can otherwise accumulate tens of thousands of events totalling
|
|
1178
|
+
* hundreds of MB before the terminal `done` event fires. When the
|
|
1179
|
+
* cap is hit, further events are dropped from the array and a single
|
|
1180
|
+
* `log` event with `data.event === 'events_truncated'` is appended
|
|
1181
|
+
* recording the truncation. The trace channel (`runtime.on('trace')`)
|
|
1182
|
+
* and WS broadcast continue to receive every event — only the
|
|
1183
|
+
* in-memory `ExecutionInfo.events` array is bounded.
|
|
1184
|
+
*
|
|
1185
|
+
* Default: 50_000. Set to `Infinity` to disable the cap (legacy
|
|
1186
|
+
* behavior; only safe for short-lived executions). Must be a positive
|
|
1187
|
+
* integer or `Infinity`.
|
|
1188
|
+
*/
|
|
1189
|
+
maxEventsPerExecution?: number;
|
|
694
1190
|
};
|
|
695
1191
|
/** Global defaults */
|
|
696
1192
|
type DefaultsConfig = {
|
|
@@ -911,6 +1407,28 @@ declare class McpManager {
|
|
|
911
1407
|
get serverCount(): number;
|
|
912
1408
|
}
|
|
913
1409
|
|
|
1410
|
+
/**
|
|
1411
|
+
* Result of a `MemoryManager.remember()` call.
|
|
1412
|
+
*
|
|
1413
|
+
* Exposes embedder `usage` so callers (WorkflowContext) can attribute
|
|
1414
|
+
* cost to the current execution scope and surface it in trace events.
|
|
1415
|
+
* `usage` is absent when no embedding happened (embed option not set,
|
|
1416
|
+
* or no vector store configured).
|
|
1417
|
+
*/
|
|
1418
|
+
type RememberResult = {
|
|
1419
|
+
usage?: EmbedUsage;
|
|
1420
|
+
};
|
|
1421
|
+
/**
|
|
1422
|
+
* Result of a `MemoryManager.recall()` call.
|
|
1423
|
+
*
|
|
1424
|
+
* Wraps the original return shape (key-value payload or vector search
|
|
1425
|
+
* results) with optional embedder `usage`. Semantic recall populates
|
|
1426
|
+
* `usage` when the embedder reported it; key-value lookups never do.
|
|
1427
|
+
*/
|
|
1428
|
+
type RecallResult = {
|
|
1429
|
+
data: unknown | VectorResult[] | null;
|
|
1430
|
+
usage?: EmbedUsage;
|
|
1431
|
+
};
|
|
914
1432
|
/**
|
|
915
1433
|
* Coordinates key-value memory and vector store for semantic search.
|
|
916
1434
|
* All key-value operations delegate to the StateStore.
|
|
@@ -927,12 +1445,18 @@ declare class MemoryManager {
|
|
|
927
1445
|
* Store a key-value pair in memory.
|
|
928
1446
|
* If a vector store and embedder are configured and embed is true,
|
|
929
1447
|
* also embeds the value for semantic search.
|
|
1448
|
+
*
|
|
1449
|
+
* Returns `{ usage }` when embedding happened, carrying the embedder's
|
|
1450
|
+
* cost/token reporting out to the caller for cost attribution.
|
|
930
1451
|
*/
|
|
931
|
-
remember(key: string, value: unknown, stateStore: StateStore, sessionId: string | undefined, options?: RememberOptions): Promise<
|
|
1452
|
+
remember(key: string, value: unknown, stateStore: StateStore, sessionId: string | undefined, options?: RememberOptions, signal?: AbortSignal): Promise<RememberResult>;
|
|
932
1453
|
/**
|
|
933
1454
|
* Recall a value from memory by key, or perform semantic search if query is provided.
|
|
1455
|
+
*
|
|
1456
|
+
* Always returns `{ data }`; semantic recalls additionally include
|
|
1457
|
+
* `usage` from the embedder (when the embedder reported it).
|
|
934
1458
|
*/
|
|
935
|
-
recall(key: string, stateStore: StateStore, sessionId: string | undefined, options?: RecallOptions): Promise<
|
|
1459
|
+
recall(key: string, stateStore: StateStore, sessionId: string | undefined, options?: RecallOptions, signal?: AbortSignal): Promise<RecallResult>;
|
|
936
1460
|
/** Delete a memory entry. If a vector store is configured, also removes the embedding. */
|
|
937
1461
|
forget(key: string, stateStore: StateStore, sessionId: string | undefined, options?: {
|
|
938
1462
|
scope?: 'session' | 'global';
|
|
@@ -958,13 +1482,17 @@ type WorkflowContextInit = {
|
|
|
958
1482
|
config: AxlConfig;
|
|
959
1483
|
providerRegistry: ProviderRegistry;
|
|
960
1484
|
sessionHistory?: ChatMessage[];
|
|
961
|
-
onTrace?: (event:
|
|
962
|
-
|
|
1485
|
+
onTrace?: (event: AxlEvent) => void;
|
|
1486
|
+
/** Per-token streaming callback. `meta` carries `askId`/`parentAskId`/
|
|
1487
|
+
* `depth`/`agent` so consumers can route or filter (e.g., `meta.depth === 0`
|
|
1488
|
+
* for root-only chat UIs). */
|
|
1489
|
+
onToken?: (token: string, meta: CallbackMeta) => void;
|
|
1490
|
+
/** Pre-execution tool-call callback. `meta` carries the ask correlation. */
|
|
963
1491
|
onToolCall?: (call: {
|
|
964
1492
|
name: string;
|
|
965
1493
|
args: unknown;
|
|
966
1494
|
callId?: string;
|
|
967
|
-
}) => void;
|
|
1495
|
+
}, meta: CallbackMeta) => void;
|
|
968
1496
|
pendingDecisions?: Map<string, (d: HumanDecision) => void>;
|
|
969
1497
|
budgetContext?: {
|
|
970
1498
|
totalCost: number;
|
|
@@ -991,9 +1519,26 @@ type WorkflowContextInit = {
|
|
|
991
1519
|
onAgentStart?: (info: {
|
|
992
1520
|
agent: string;
|
|
993
1521
|
model: string;
|
|
994
|
-
}) => void;
|
|
1522
|
+
}, meta: CallbackMeta) => void;
|
|
995
1523
|
/** Callback fired after each ctx.ask() completes (once per ask invocation). */
|
|
996
1524
|
onAgentCallComplete?: (call: AgentCallInfo) => void;
|
|
1525
|
+
/** Internal: shared auto-checkpoint counters. Set by `createChildContext`
|
|
1526
|
+
* so parent + child share the same number space, preventing checkpoint
|
|
1527
|
+
* store key collisions across nested `WorkflowContext` instances.
|
|
1528
|
+
*
|
|
1529
|
+
* - `byAgent` — per-agent counter for `ctx.ask` auto-checkpoints; each
|
|
1530
|
+
* agent's first ask gets `0`, second gets `1`, etc. Composed name:
|
|
1531
|
+
* `__auto/<agent>/ask/<n>`. Reads naturally as "orchestrator's first
|
|
1532
|
+
* ask, second ask…" instead of a global ordinal.
|
|
1533
|
+
* - `root` — counter for `ctx.spawn` / `race` / `parallel` / `map`
|
|
1534
|
+
* wrappers, which don't have an agent context (they wrap arbitrary
|
|
1535
|
+
* fn callbacks). Composed name: `__auto/<primitive>/<n>`.
|
|
1536
|
+
*
|
|
1537
|
+
* Root contexts default to a fresh `{ byAgent: new Map(), root: 0 }`. */
|
|
1538
|
+
autoCheckpointCounters?: {
|
|
1539
|
+
byAgent: Map<string, number>;
|
|
1540
|
+
root: number;
|
|
1541
|
+
};
|
|
997
1542
|
};
|
|
998
1543
|
/**
|
|
999
1544
|
* The central coordination object for all Axl primitives.
|
|
@@ -1018,8 +1563,34 @@ declare class WorkflowContext<TInput = unknown> {
|
|
|
1018
1563
|
private pendingDecisions?;
|
|
1019
1564
|
private budgetContext?;
|
|
1020
1565
|
private stateStore?;
|
|
1021
|
-
|
|
1022
|
-
|
|
1566
|
+
/** Root step counter for this execution. Inherited by every ctx.ask()
|
|
1567
|
+
* frame so all events from this WorkflowContext (root + nested) share
|
|
1568
|
+
* a single monotonic counter, even when concurrent branch primitives
|
|
1569
|
+
* fire asks before any single parent ask exists. Per-instance so
|
|
1570
|
+
* separate executions don't cross-talk. */
|
|
1571
|
+
private stepRefRoot;
|
|
1572
|
+
/**
|
|
1573
|
+
* Auto-checkpoint counters for internal `_checkpoint` callers. Held by
|
|
1574
|
+
* reference so child contexts created via `createChildContext` share
|
|
1575
|
+
* the same number space — otherwise a tool handler's nested `ctx.ask()`
|
|
1576
|
+
* (which auto-checkpoints) would collide with the parent's
|
|
1577
|
+
* auto-checkpoints in the state store. See `WorkflowContextInit
|
|
1578
|
+
* .autoCheckpointCounters` for the per-agent vs root split.
|
|
1579
|
+
* User-facing `ctx.checkpoint(name, fn)` requires an explicit name and
|
|
1580
|
+
* does NOT touch these counters — it goes straight to the store under
|
|
1581
|
+
* the caller-supplied key.
|
|
1582
|
+
*/
|
|
1583
|
+
private autoCheckpointCounters;
|
|
1584
|
+
/** Idempotency guards for `workflow_start` / `workflow_end` emission.
|
|
1585
|
+
* Both `runtime.execute()` and `runtime.stream()` have paths where a
|
|
1586
|
+
* post-emit side-effect (checkpoint deletion, state-store persistence)
|
|
1587
|
+
* can throw AFTER `_emitWorkflowEnd({status: 'completed'})` has already
|
|
1588
|
+
* fired — the outer catch would then fire `_emitWorkflowEnd({status:
|
|
1589
|
+
* 'failed'})` for a second time. These flags make both emitters
|
|
1590
|
+
* single-fire so consumers never see paired-then-conflicting terminal
|
|
1591
|
+
* events for one execution. */
|
|
1592
|
+
private _workflowStartEmitted;
|
|
1593
|
+
private _workflowEndEmitted;
|
|
1023
1594
|
private signal?;
|
|
1024
1595
|
private summaryCache?;
|
|
1025
1596
|
private workflowName?;
|
|
@@ -1036,8 +1607,21 @@ declare class WorkflowContext<TInput = unknown> {
|
|
|
1036
1607
|
* Create a child context for nested agent invocations (e.g., agent-as-tool).
|
|
1037
1608
|
* Shares: budget tracking, abort signals, trace emission, provider registry,
|
|
1038
1609
|
* state store, span manager, memory manager, MCP manager, config,
|
|
1039
|
-
* awaitHuman handler, pending decisions, tool overrides
|
|
1040
|
-
*
|
|
1610
|
+
* awaitHuman handler, pending decisions, tool overrides, AND the
|
|
1611
|
+
* streaming callbacks (onToken / onAgentStart / onToolCall).
|
|
1612
|
+
* Isolates: session history.
|
|
1613
|
+
*
|
|
1614
|
+
* Streaming callbacks now propagate into nested asks because every callback
|
|
1615
|
+
* invocation carries `meta.askId`/`meta.parentAskId`/`meta.depth` so
|
|
1616
|
+
* consumers that want root-only behavior can filter on `meta.depth === 0`
|
|
1617
|
+
* instead of relying on the runtime to drop nested events. This is the
|
|
1618
|
+
* "nested ask visibility" fix from spec §3.2.
|
|
1619
|
+
*
|
|
1620
|
+
* The shared step counter lives in `askStorage` (ALS), so there is no
|
|
1621
|
+
* per-context counter to pass through anymore. Nested events are
|
|
1622
|
+
* correlated to their parent via `parentAskId` (set on every nested ask
|
|
1623
|
+
* by ALS frame allocation) — the deprecated `parentToolCallId` field
|
|
1624
|
+
* was removed in 0.16.0.
|
|
1041
1625
|
*/
|
|
1042
1626
|
createChildContext(): WorkflowContext;
|
|
1043
1627
|
/**
|
|
@@ -1046,6 +1630,18 @@ declare class WorkflowContext<TInput = unknown> {
|
|
|
1046
1630
|
* take priority over the instance-level signal.
|
|
1047
1631
|
*/
|
|
1048
1632
|
private get currentSignal();
|
|
1633
|
+
/**
|
|
1634
|
+
* Build a `CallbackMeta` for the current ask frame. Used at every
|
|
1635
|
+
* `onToken`/`onToolCall`/`onAgentStart` call site so consumers can
|
|
1636
|
+
* route or filter by ask correlation (`meta.depth === 0` for root
|
|
1637
|
+
* chat UIs, etc.).
|
|
1638
|
+
*
|
|
1639
|
+
* If the call is somehow outside an ask frame (e.g., a programmatic
|
|
1640
|
+
* `tool.run()` test harness), falls back to a synthetic meta keyed off
|
|
1641
|
+
* `executionId` so the type contract holds — consumers see `depth: 0`
|
|
1642
|
+
* and can ignore those events.
|
|
1643
|
+
*/
|
|
1644
|
+
private currentCallbackMeta;
|
|
1049
1645
|
ask<T = string>(agent: Agent, prompt: string, options?: AskOptions<T>): Promise<T>;
|
|
1050
1646
|
private executeAgentCall;
|
|
1051
1647
|
/**
|
|
@@ -1062,16 +1658,49 @@ declare class WorkflowContext<TInput = unknown> {
|
|
|
1062
1658
|
/**
|
|
1063
1659
|
* Execute a function with checkpoint-replay semantics.
|
|
1064
1660
|
*
|
|
1065
|
-
* On first execution, runs `fn()`, saves the result
|
|
1066
|
-
* On replay (resume after restart), returns the saved result
|
|
1067
|
-
* This prevents duplicate side effects (double API
|
|
1661
|
+
* On first execution, runs `fn()`, saves the result under `name`, and
|
|
1662
|
+
* returns it. On replay (resume after restart), returns the saved result
|
|
1663
|
+
* without re-executing. This prevents duplicate side effects (double API
|
|
1664
|
+
* calls, double refunds, etc.).
|
|
1665
|
+
*
|
|
1666
|
+
* `name` must be a stable, caller-supplied identifier — the same call
|
|
1667
|
+
* site MUST pass the same name across runs of the same execution for
|
|
1668
|
+
* replay to work. Names are scoped to a single execution and must be
|
|
1669
|
+
* unique within it; reusing a name (e.g. inside a loop) gives
|
|
1670
|
+
* last-write-wins behavior. For loops, compose names from the iterator:
|
|
1671
|
+
* `ctx.checkpoint(`process-${id}`, fn)`.
|
|
1672
|
+
*
|
|
1673
|
+
* Names starting with `__auto/` are reserved for runtime-internal
|
|
1674
|
+
* auto-checkpointing of `ctx.ask` / spawn / race / parallel / map.
|
|
1068
1675
|
*/
|
|
1069
|
-
checkpoint<T>(fn: () => Promise<T>): Promise<T>;
|
|
1676
|
+
checkpoint<T>(name: string, fn: () => Promise<T>): Promise<T>;
|
|
1070
1677
|
/**
|
|
1071
|
-
* Internal checkpoint implementation shared by both the public
|
|
1072
|
-
* and the automatic checkpointing in
|
|
1678
|
+
* Internal checkpoint implementation shared by both the public
|
|
1679
|
+
* `checkpoint(name, fn)` and the automatic checkpointing in
|
|
1680
|
+
* ask/spawn/race/parallel/map. Internal callers pass an `__auto/...`
|
|
1681
|
+
* name composed by `_autoCheckpointName`.
|
|
1682
|
+
*
|
|
1683
|
+
* `agent` is the originating agent for ask auto-checkpoints — passing
|
|
1684
|
+
* it explicitly stamps `event.agent` on the trace events even though
|
|
1685
|
+
* the emit fires before/after `fn()` (where the ask's ALS frame
|
|
1686
|
+
* either doesn't exist yet or has already torn down). Without this,
|
|
1687
|
+
* post-fn `checkpoint_save` rows show no agent in the trace UI.
|
|
1073
1688
|
*/
|
|
1074
1689
|
private _checkpoint;
|
|
1690
|
+
/** Generate a stable auto-checkpoint name for an internal primitive.
|
|
1691
|
+
*
|
|
1692
|
+
* For `ctx.ask`, the originating agent is known and gets a per-agent
|
|
1693
|
+
* counter — the resulting name reads as "orchestrator's first ask"
|
|
1694
|
+
* (`__auto/orchestrator-agent/ask/0`) instead of a global ordinal.
|
|
1695
|
+
* For `spawn` / `race` / `parallel` / `map`, no agent context is
|
|
1696
|
+
* available (those wrap arbitrary fn callbacks), so the name uses
|
|
1697
|
+
* the root counter: `__auto/spawn/0`, `__auto/race/3`, etc.
|
|
1698
|
+
*
|
|
1699
|
+
* All counters live on a shared ref passed through `createChildContext`,
|
|
1700
|
+
* so a tool handler's nested `ctx.ask()` (which runs in a child
|
|
1701
|
+
* WorkflowContext) can never collide with the parent's auto-names in
|
|
1702
|
+
* the state store. */
|
|
1703
|
+
private _autoCheckpointName;
|
|
1075
1704
|
spawn<T>(n: number, fn: (index: number) => Promise<T>, options?: SpawnOptions): Promise<Result<T>[]>;
|
|
1076
1705
|
private _spawnImpl;
|
|
1077
1706
|
vote<T>(results: Result<T>[], options: VoteOptions<T>): T | Promise<T>;
|
|
@@ -1099,6 +1728,49 @@ declare class WorkflowContext<TInput = unknown> {
|
|
|
1099
1728
|
private _mapImpl;
|
|
1100
1729
|
awaitHuman(options: AwaitHumanOptions): Promise<HumanDecision>;
|
|
1101
1730
|
private _awaitHumanImpl;
|
|
1731
|
+
/**
|
|
1732
|
+
* Compose an `AbortSignal` for a memory operation's underlying embedder
|
|
1733
|
+
* fetch. Combines the parent context signal (user cancellation,
|
|
1734
|
+
* `runtime.execute({ signal })`) with the budget hard_stop abort so
|
|
1735
|
+
* that either cause correctly aborts an in-flight embed call.
|
|
1736
|
+
*
|
|
1737
|
+
* Returns `undefined` if there's nothing to cancel on — the embedder
|
|
1738
|
+
* runs without a signal in that case, matching its prior behavior.
|
|
1739
|
+
*
|
|
1740
|
+
* @internal
|
|
1741
|
+
*/
|
|
1742
|
+
private _composeMemorySignal;
|
|
1743
|
+
/**
|
|
1744
|
+
* Accumulate a cost amount into the active `budgetContext` and trip the
|
|
1745
|
+
* `exceeded` flag if we've crossed the limit. On `hard_stop` policy,
|
|
1746
|
+
* also fires the abort controller so in-flight operations cancel.
|
|
1747
|
+
*
|
|
1748
|
+
* Called from every code path that spends money: the `agent_call` loop,
|
|
1749
|
+
* semantic memory operations (`ctx.remember({embed:true})`, `ctx.recall({query})`),
|
|
1750
|
+
* and any future cost-emitting primitive. Centralizing the logic here
|
|
1751
|
+
* means `ctx.budget({ limit, policy })` accurately enforces the limit
|
|
1752
|
+
* across ALL cost sources — not just agent calls.
|
|
1753
|
+
*
|
|
1754
|
+
* @internal
|
|
1755
|
+
*/
|
|
1756
|
+
private _accumulateBudgetCost;
|
|
1757
|
+
/** @internal — idempotent; no-ops on second+ call within one ctx. */
|
|
1758
|
+
_emitWorkflowStart(input: unknown): void;
|
|
1759
|
+
/** @internal — idempotent; no-ops on second+ call within one ctx.
|
|
1760
|
+
* Protects against the post-emit-side-effect double-fire (reviewer
|
|
1761
|
+
* bug B1): `runtime.execute()` / `runtime.stream()` emit
|
|
1762
|
+
* `workflow_end(completed)`, then call `deleteCheckpoints` /
|
|
1763
|
+
* `persistExecution`. If either throws, the outer catch would
|
|
1764
|
+
* otherwise fire a second `workflow_end(failed)` with conflicting
|
|
1765
|
+
* status. First-wins semantics: the completed event stands, the
|
|
1766
|
+
* inner side-effect failure propagates as a normal thrown error. */
|
|
1767
|
+
_emitWorkflowEnd(info: {
|
|
1768
|
+
status: 'completed' | 'failed';
|
|
1769
|
+
duration: number;
|
|
1770
|
+
result?: unknown;
|
|
1771
|
+
error?: string;
|
|
1772
|
+
aborted?: boolean;
|
|
1773
|
+
}): void;
|
|
1102
1774
|
log(event: string, data?: unknown): void;
|
|
1103
1775
|
/**
|
|
1104
1776
|
* Store a value in memory, scoped to the current session (default) or globally.
|
|
@@ -1125,7 +1797,13 @@ declare class WorkflowContext<TInput = unknown> {
|
|
|
1125
1797
|
* @param options - Optional: schema, routerModel, metadata, retries
|
|
1126
1798
|
*/
|
|
1127
1799
|
delegate<T = string>(agents: Agent[], prompt: string, options?: DelegateOptions<T>): Promise<T>;
|
|
1128
|
-
|
|
1800
|
+
/**
|
|
1801
|
+
* Internal emitter input — intentionally loose so call sites don't need to
|
|
1802
|
+
* build a perfectly-narrowed discriminated-union member. The resulting
|
|
1803
|
+
* `AxlEvent` (exported type) remains strict, and TypeScript narrows it at
|
|
1804
|
+
* consumer sites via the `type` discriminator.
|
|
1805
|
+
*/
|
|
1806
|
+
private emitEvent;
|
|
1129
1807
|
}
|
|
1130
1808
|
|
|
1131
1809
|
/** Retry policy for tool handlers */
|
|
@@ -1193,6 +1871,15 @@ type Workflow<TInput extends z.ZodType = z.ZodType, TOutput extends z.ZodType =
|
|
|
1193
1871
|
readonly outputSchema: TOutput | undefined;
|
|
1194
1872
|
readonly handler: (ctx: WorkflowContext<z.infer<TInput>>) => Promise<z.infer<TOutput>>;
|
|
1195
1873
|
};
|
|
1874
|
+
/**
|
|
1875
|
+
* Bivariant-parameter alias for `Workflow<any, any>`. Function parameters
|
|
1876
|
+
* are contravariant under strict types, so `Workflow<TInput=MsgType>` won't
|
|
1877
|
+
* satisfy a `Workflow<unknown, unknown>` slot. The standard escape hatch is
|
|
1878
|
+
* to widen to `any`. This alias gives that workaround a name so call sites
|
|
1879
|
+
* (e.g. `AxlRuntime.register`, `AxlTestRuntime.WorkflowLike.handler`) don't
|
|
1880
|
+
* each independently re-derive it.
|
|
1881
|
+
*/
|
|
1882
|
+
type AnyWorkflow = Workflow<any, any>;
|
|
1196
1883
|
/**
|
|
1197
1884
|
* Define a named workflow with Zod-validated input/output and an async handler.
|
|
1198
1885
|
* Register workflows with `AxlRuntime.register()` to execute them.
|
|
@@ -1204,37 +1891,112 @@ declare function workflow<TInput extends z.ZodType, TOutput extends z.ZodType =
|
|
|
1204
1891
|
/**
|
|
1205
1892
|
* A streamable workflow execution.
|
|
1206
1893
|
*
|
|
1207
|
-
* Extends Node's Readable and implements AsyncIterable<
|
|
1208
|
-
*
|
|
1894
|
+
* Extends Node's Readable and implements `AsyncIterable<AxlEvent>`. Supports
|
|
1895
|
+
* `.on()` events, `for-await-of`, the `.text` iterator (root-only tokens),
|
|
1896
|
+
* the `.lifecycle` iterator (structural events only), and `.pipe()`.
|
|
1897
|
+
*
|
|
1898
|
+
* The wire carries `AxlEvent` directly — there is no per-stream synthesized
|
|
1899
|
+
* shape. Consumers narrow on `event.type` and use `AskScoped` fields
|
|
1900
|
+
* (`askId`, `parentAskId`, `depth`) for routing/filtering.
|
|
1209
1901
|
*/
|
|
1210
1902
|
declare class AxlStream extends Readable {
|
|
1211
1903
|
private bus;
|
|
1212
|
-
|
|
1904
|
+
/**
|
|
1905
|
+
* Per-ask token buffers split into "in-progress" and "committed"
|
|
1906
|
+
* halves so `fullText` only includes tokens from attempts that
|
|
1907
|
+
* actually won. Scoping is per-`askId` so concurrent root-level asks
|
|
1908
|
+
* (`ctx.parallel`, `ctx.spawn`, `ctx.race`, `ctx.map`) don't
|
|
1909
|
+
* interleave each other's tokens — each branch's chunks stay
|
|
1910
|
+
* contiguous, and a `pipeline(failed)` on one branch only discards
|
|
1911
|
+
* THAT branch's in-progress buffer (previously: shared buffer caused
|
|
1912
|
+
* a failure on one branch to discard a peer's in-flight successful
|
|
1913
|
+
* tokens). Insertion order in the Maps reflects which ask emitted
|
|
1914
|
+
* its first token first, which is what `fullText` joins on.
|
|
1915
|
+
*
|
|
1916
|
+
* On `pipeline(status: 'committed')` for an ask, that ask's
|
|
1917
|
+
* in-progress entry flushes to its committed entry. On
|
|
1918
|
+
* `pipeline(status: 'failed')` or `ask_end({ok:false})` for an ask,
|
|
1919
|
+
* that ask's in-progress entry is discarded. Spec/16 §4.3.
|
|
1920
|
+
*
|
|
1921
|
+
* Tokens emitted outside any ask (synthesized test fixtures with no
|
|
1922
|
+
* `askId`) fall back to an empty-string sentinel key — preserves the
|
|
1923
|
+
* single-buffer behavior for that legacy case.
|
|
1924
|
+
*/
|
|
1925
|
+
private attemptByAsk;
|
|
1926
|
+
private committedByAsk;
|
|
1213
1927
|
private result;
|
|
1214
1928
|
private finished;
|
|
1215
1929
|
readonly promise: Promise<unknown>;
|
|
1216
1930
|
private eventQueue;
|
|
1217
1931
|
private waiters;
|
|
1218
1932
|
constructor();
|
|
1933
|
+
/** Wire-format event names callers can subscribe to via `.on(name, fn)`.
|
|
1934
|
+
* Derived from the canonical `AXL_EVENT_TYPES` tuple — adding a new
|
|
1935
|
+
* variant in `types.ts` automatically extends the subscribable set. */
|
|
1219
1936
|
private static readonly STREAM_EVENTS;
|
|
1220
1937
|
on(event: string, handler: (...args: unknown[]) => void): this;
|
|
1221
1938
|
off(event: string, handler: (...args: unknown[]) => void): this;
|
|
1222
1939
|
[Symbol.asyncIterator](): {
|
|
1223
|
-
next: () => Promise<IteratorResult<
|
|
1940
|
+
next: () => Promise<IteratorResult<AxlEvent>>;
|
|
1224
1941
|
[Symbol.asyncIterator](): /*elided*/ any;
|
|
1225
1942
|
[Symbol.asyncDispose](): Promise<void>;
|
|
1226
1943
|
};
|
|
1227
1944
|
get text(): AsyncIterable<string>;
|
|
1228
|
-
|
|
1945
|
+
/**
|
|
1946
|
+
* Iterator over `{ askId, text }` pairs — one emission per token chunk,
|
|
1947
|
+
* tagged with the ask frame that produced it. Complements `.text`
|
|
1948
|
+
* (root-only stream): consumers building a split-pane UI that shows
|
|
1949
|
+
* each sub-agent's output in its own lane can group by `askId`
|
|
1950
|
+
* without iterating the raw stream and hand-filtering on `event.type`.
|
|
1951
|
+
*
|
|
1952
|
+
* Nested and root tokens both flow through. The `agent` field names
|
|
1953
|
+
* the producing agent for UI labelling; it's undefined when the token
|
|
1954
|
+
* was emitted outside any ask (rare — synthesized test fixtures).
|
|
1955
|
+
*/
|
|
1956
|
+
get textByAsk(): AsyncIterable<{
|
|
1957
|
+
askId: string;
|
|
1958
|
+
agent?: string;
|
|
1959
|
+
text: string;
|
|
1960
|
+
}>;
|
|
1961
|
+
/**
|
|
1962
|
+
* Iterator over structural lifecycle events only — skips per-token chatter
|
|
1963
|
+
* and progressive partial_object emissions. Useful for waterfall UIs and
|
|
1964
|
+
* any consumer that wants the "what happened" timeline without per-chunk
|
|
1965
|
+
* noise. Renamed from `.steps` in the unified-event-model migration
|
|
1966
|
+
* because these are events, not pipeline steps.
|
|
1967
|
+
*/
|
|
1968
|
+
get lifecycle(): AsyncIterable<AxlEvent>;
|
|
1229
1969
|
pipe<T extends NodeJS.WritableStream>(destination: T, options?: {
|
|
1230
1970
|
end?: boolean;
|
|
1231
1971
|
}): T;
|
|
1232
|
-
/** Push
|
|
1233
|
-
_push(event:
|
|
1234
|
-
/**
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1972
|
+
/** Push an event onto the stream. Called by the runtime. */
|
|
1973
|
+
_push(event: AxlEvent): void;
|
|
1974
|
+
/**
|
|
1975
|
+
* Signal successful completion.
|
|
1976
|
+
*
|
|
1977
|
+
* `executionId` is required — the runtime must allocate it before
|
|
1978
|
+
* calling `stream()` so terminal events always carry a real id.
|
|
1979
|
+
* Previously the default-empty parameter surfaced blank executionIds
|
|
1980
|
+
* on error paths that threw before `execInfo` was assigned (review S4).
|
|
1981
|
+
*/
|
|
1982
|
+
_done(result: unknown, executionId: string): void;
|
|
1983
|
+
/** Signal an error. `executionId` is required for the same reason as
|
|
1984
|
+
* `_done`: terminal events must carry a real id even when the
|
|
1985
|
+
* failure happens before any real trace event fires (review S4). */
|
|
1986
|
+
_error(error: Error, executionId: string): void;
|
|
1987
|
+
/** Concatenated root-only text from committed attempts plus the
|
|
1988
|
+
* current in-flight attempt(s). Retried (gate-rejected) attempts
|
|
1989
|
+
* are excluded — see spec/16 §4.3. Reading mid-attempt returns the
|
|
1990
|
+
* in-progress text; reading after `pipeline(committed)` (which
|
|
1991
|
+
* fires before `done`) returns the canonical winning text.
|
|
1992
|
+
*
|
|
1993
|
+
* With concurrent root-level asks (`ctx.parallel`, `ctx.spawn`,
|
|
1994
|
+
* `ctx.race`, `ctx.map`), each branch's tokens are scoped per-`askId`
|
|
1995
|
+
* and emitted contiguously in the order each ask first started
|
|
1996
|
+
* emitting tokens. A `pipeline(failed)` or `ask_end({ok:false})` on
|
|
1997
|
+
* one branch only discards THAT branch's in-progress buffer —
|
|
1998
|
+
* sibling branches are unaffected. For UIs that want each sub-agent
|
|
1999
|
+
* in its own lane, prefer `textByAsk`. */
|
|
1238
2000
|
get fullText(): string;
|
|
1239
2001
|
}
|
|
1240
2002
|
|
|
@@ -1275,6 +2037,25 @@ declare class Session {
|
|
|
1275
2037
|
|
|
1276
2038
|
type ExecuteOptions = {
|
|
1277
2039
|
metadata?: Record<string, unknown>;
|
|
2040
|
+
/** Handler for tool approval requests. When provided, tools with `requireApproval` resolve
|
|
2041
|
+
* via this handler instead of suspending the execution and registering a pending decision.
|
|
2042
|
+
* Useful for in-process testing and ad-hoc invocations where you don't want to poll
|
|
2043
|
+
* `runtime.getPendingDecisions()` and call `runtime.resolveDecision()`. */
|
|
2044
|
+
awaitHumanHandler?: (options: AwaitHumanOptions) => Promise<HumanDecision>;
|
|
2045
|
+
};
|
|
2046
|
+
/**
|
|
2047
|
+
* Shape of events forwarded to an eval `onProgress` callback. Mirrors
|
|
2048
|
+
* `@axlsdk/eval`'s `EvalProgressEvent` so runtime consumers can type their
|
|
2049
|
+
* callbacks without importing the optional peer dep.
|
|
2050
|
+
*/
|
|
2051
|
+
type EvalProgressEventShape = {
|
|
2052
|
+
type: 'item_done';
|
|
2053
|
+
itemIndex: number;
|
|
2054
|
+
totalItems: number;
|
|
2055
|
+
} | {
|
|
2056
|
+
type: 'run_done';
|
|
2057
|
+
totalItems: number;
|
|
2058
|
+
failures: number;
|
|
1278
2059
|
};
|
|
1279
2060
|
type CreateContextOptions = {
|
|
1280
2061
|
metadata?: Record<string, unknown>;
|
|
@@ -1284,8 +2065,23 @@ type CreateContextOptions = {
|
|
|
1284
2065
|
signal?: AbortSignal;
|
|
1285
2066
|
/** Prior conversation history for multi-turn eval testing. */
|
|
1286
2067
|
sessionHistory?: ChatMessage[];
|
|
1287
|
-
/** Token streaming callback.
|
|
1288
|
-
|
|
2068
|
+
/** Token streaming callback. `meta` carries `askId`/`parentAskId`/`depth`/`agent`
|
|
2069
|
+
* so consumers can route or filter by ask correlation (e.g.,
|
|
2070
|
+
* `meta.depth === 0` for root-only chat UIs). */
|
|
2071
|
+
onToken?: (token: string, meta: CallbackMeta) => void;
|
|
2072
|
+
/** Fires when an agent invokes a tool. `meta` carries the same ask
|
|
2073
|
+
* correlation shape as `onToken`. */
|
|
2074
|
+
onToolCall?: (call: {
|
|
2075
|
+
name: string;
|
|
2076
|
+
args: unknown;
|
|
2077
|
+
callId?: string;
|
|
2078
|
+
}, meta: CallbackMeta) => void;
|
|
2079
|
+
/** Fires when an agent begins processing a turn. `meta` carries the
|
|
2080
|
+
* same ask correlation shape as `onToken`. */
|
|
2081
|
+
onAgentStart?: (info: {
|
|
2082
|
+
agent: string;
|
|
2083
|
+
model?: string;
|
|
2084
|
+
}, meta: CallbackMeta) => void;
|
|
1289
2085
|
/** Handler for tool approval requests. Called when an agent invokes a tool with requireApproval. */
|
|
1290
2086
|
awaitHumanHandler?: (options: AwaitHumanOptions) => Promise<HumanDecision>;
|
|
1291
2087
|
};
|
|
@@ -1313,7 +2109,25 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1313
2109
|
private historicalExecutionsLoadPromise;
|
|
1314
2110
|
private evalHistory;
|
|
1315
2111
|
private evalHistoryLoadPromise;
|
|
2112
|
+
/** Resolved cap on `ExecutionInfo.events` per execution. Cached on
|
|
2113
|
+
* the instance so per-event onTrace handlers don't reach into
|
|
2114
|
+
* `this.config.state` on every emission. */
|
|
2115
|
+
private readonly maxEventsPerExecution;
|
|
1316
2116
|
constructor(config?: AxlConfig);
|
|
2117
|
+
/**
|
|
2118
|
+
* Whether `config.trace.redact` is enabled on this runtime. A narrow
|
|
2119
|
+
* boolean getter is preferred over exposing the full config because:
|
|
2120
|
+
* (a) `Readonly<AxlConfig>` is shallow so the config would be mutable
|
|
2121
|
+
* at runtime through sub-objects, subverting any compliance guarantee;
|
|
2122
|
+
* (b) observability consumers like Studio only need the boolean, not
|
|
2123
|
+
* the whole config tree; (c) if future observability config needs to
|
|
2124
|
+
* expand, each new flag gets its own narrow getter.
|
|
2125
|
+
*
|
|
2126
|
+
* Studio's server-side redaction helpers (executions, memory, sessions,
|
|
2127
|
+
* evals, decisions, tools, playground, workflows) all route through
|
|
2128
|
+
* this accessor to decide whether to scrub response payloads.
|
|
2129
|
+
*/
|
|
2130
|
+
isRedactEnabled(): boolean;
|
|
1317
2131
|
/**
|
|
1318
2132
|
* Initialize MCP servers configured in the config.
|
|
1319
2133
|
* Call this before executing workflows that use MCP tools.
|
|
@@ -1327,13 +2141,39 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1327
2141
|
/** Get the MCP manager (if initialized). */
|
|
1328
2142
|
getMcpManager(): McpManager | undefined;
|
|
1329
2143
|
private createStateStore;
|
|
2144
|
+
/**
|
|
2145
|
+
* Run a workflow body inside an ALREADY-CONSTRUCTED `WorkflowContext`
|
|
2146
|
+
* with full lifecycle invariants: emit `workflow_start` → run handler
|
|
2147
|
+
* → parse output → emit `workflow_end` → delete checkpoints → persist.
|
|
2148
|
+
*
|
|
2149
|
+
* Shared between `execute()` and `stream()`. Centralizes the
|
|
2150
|
+
* "start iff end" pairing invariant so a future emit path
|
|
2151
|
+
* (e.g., `resumeExecution`) can inherit correct behavior by routing
|
|
2152
|
+
* through this helper. Also factors out the AbortError detection.
|
|
2153
|
+
*
|
|
2154
|
+
* Side effects on `execInfo`: sets `status` / `completedAt` /
|
|
2155
|
+
* `duration` / `result` (or `error`) before emitting `workflow_end`.
|
|
2156
|
+
* On throw: emits `workflow_end({status: 'failed', aborted?})` and
|
|
2157
|
+
* persists before rethrowing. `abortControllers.delete` runs in
|
|
2158
|
+
* `finally` regardless of outcome.
|
|
2159
|
+
*
|
|
2160
|
+
* Caller responsibilities:
|
|
2161
|
+
* - Allocate `executionId` and register it in `abortControllers` map
|
|
2162
|
+
* BEFORE calling this helper (so early-throw paths still have a
|
|
2163
|
+
* correlation id available for terminal events).
|
|
2164
|
+
* - Construct `execInfo` and `ctx` before calling.
|
|
2165
|
+
* - Pass `span` if the call site is inside a tracer span — this
|
|
2166
|
+
* helper sets `axl.workflow.cost` / `.duration` attributes on
|
|
2167
|
+
* success.
|
|
2168
|
+
*/
|
|
2169
|
+
private runWorkflowBody;
|
|
1330
2170
|
/**
|
|
1331
2171
|
* Persist a completed/failed execution to the state store (fire-and-forget)
|
|
1332
2172
|
* and move it from the active executions map to the historical cache.
|
|
1333
2173
|
*/
|
|
1334
2174
|
private persistExecution;
|
|
1335
2175
|
/** Register a workflow with the runtime. */
|
|
1336
|
-
register(workflow:
|
|
2176
|
+
register(workflow: AnyWorkflow): void;
|
|
1337
2177
|
/** Register standalone tools for Studio introspection and direct testing. */
|
|
1338
2178
|
registerTool(...tools: Tool<any, any>[]): void;
|
|
1339
2179
|
/** Register standalone agents for Studio playground and introspection. */
|
|
@@ -1381,6 +2221,18 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1381
2221
|
/** Run a registered eval by name. */
|
|
1382
2222
|
runRegisteredEval(name: string, options?: {
|
|
1383
2223
|
metadata?: Record<string, unknown>;
|
|
2224
|
+
/** Called after each dataset item completes (execution + scoring). */
|
|
2225
|
+
onProgress?: (event: EvalProgressEventShape) => void;
|
|
2226
|
+
/** Abort signal — checked before starting each item. */
|
|
2227
|
+
signal?: AbortSignal;
|
|
2228
|
+
/**
|
|
2229
|
+
* When `true`, populate `EvalItem.traces` on every item (success + failure
|
|
2230
|
+
* paths). Forwards to `runEval({ captureTraces: true })`, which wraps each
|
|
2231
|
+
* item's execution in `runtime.trackExecution({ captureTraces: true })`.
|
|
2232
|
+
* Verbose-mode `agent_call_start.data.messages` snapshots are stripped from
|
|
2233
|
+
* captured traces to keep memory bounded.
|
|
2234
|
+
*/
|
|
2235
|
+
captureTraces?: boolean;
|
|
1384
2236
|
}): Promise<unknown>;
|
|
1385
2237
|
/** Get all execution info (running + completed + historical). */
|
|
1386
2238
|
getExecutions(): Promise<ExecutionInfo[]>;
|
|
@@ -1457,6 +2309,10 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1457
2309
|
concurrency?: number;
|
|
1458
2310
|
budget?: string;
|
|
1459
2311
|
metadata?: Record<string, unknown>;
|
|
2312
|
+
}, options?: {
|
|
2313
|
+
onProgress?: (event: EvalProgressEventShape) => void;
|
|
2314
|
+
signal?: AbortSignal;
|
|
2315
|
+
captureTraces?: boolean;
|
|
1460
2316
|
}): Promise<unknown>;
|
|
1461
2317
|
/**
|
|
1462
2318
|
* Compare two evaluation results to detect regressions and improvements.
|
|
@@ -1484,14 +2340,43 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1484
2340
|
* Returns cost (same as `trackCost`) plus metadata extracted from trace events:
|
|
1485
2341
|
* models (unique URIs), tokens (input/output/reasoning sums), and agent call count.
|
|
1486
2342
|
*
|
|
2343
|
+
* ## Cost vs tokens semantics
|
|
2344
|
+
*
|
|
2345
|
+
* - `cost` is the full aggregate across EVERY event with a top-level
|
|
2346
|
+
* `event.cost` set: agent calls, tool calls, semantic memory ops, etc.
|
|
2347
|
+
* This is the number to reconcile against your provider bill.
|
|
2348
|
+
*
|
|
2349
|
+
* - `metadata.tokens` is narrowly scoped to **agent** prompt/completion/
|
|
2350
|
+
* reasoning tokens. Embedder tokens from semantic `ctx.remember({embed:true})`
|
|
2351
|
+
* / `ctx.recall({query})` are deliberately NOT summed here — they're a
|
|
2352
|
+
* different category (input-only, different pricing, different model).
|
|
2353
|
+
* Conflating them would make "prompt tokens" misleading in the UI. If you
|
|
2354
|
+
* need embedder token counts, subscribe to `runtime.on('trace', ...)` and
|
|
2355
|
+
* read `data.usage.tokens` on `memory_remember` / `memory_recall` events.
|
|
2356
|
+
*
|
|
2357
|
+
* Pass `{ captureTraces: true }` to also collect the raw `AxlEvent[]` observed
|
|
2358
|
+
* during `fn()`. This is opt-in because it keeps every event in memory for the
|
|
2359
|
+
* duration of the call — useful for eval per-item capture, debugging, and test
|
|
2360
|
+
* assertions, but overhead grows with trace volume. When enabled, verbose-mode
|
|
2361
|
+
* `agent_call_start.data.messages` snapshots are omitted from captured events (still
|
|
2362
|
+
* broadcast via onTrace) to keep memory bounded — callers who need the full
|
|
2363
|
+
* verbose snapshot should subscribe to `runtime.on('trace', ...)` directly.
|
|
2364
|
+
*
|
|
1487
2365
|
* Works with both `createContext()` and `execute()` calls inside `fn`.
|
|
1488
2366
|
*/
|
|
1489
|
-
trackExecution<T>(fn: () => Promise<T
|
|
2367
|
+
trackExecution<T>(fn: () => Promise<T>, options?: {
|
|
2368
|
+
captureTraces?: boolean;
|
|
2369
|
+
}): Promise<{
|
|
1490
2370
|
result: T;
|
|
1491
2371
|
cost: number;
|
|
2372
|
+
traces?: AxlEvent[];
|
|
1492
2373
|
metadata: {
|
|
1493
2374
|
models: string[];
|
|
1494
2375
|
modelCallCounts?: Record<string, number>;
|
|
2376
|
+
/**
|
|
2377
|
+
* Agent token totals only — does not include embedder tokens from
|
|
2378
|
+
* semantic memory operations. See the method-level JSDoc above.
|
|
2379
|
+
*/
|
|
1495
2380
|
tokens: {
|
|
1496
2381
|
input: number;
|
|
1497
2382
|
output: number;
|
|
@@ -1519,8 +2404,8 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1519
2404
|
* The emit('trace', event) call happens before this method is called, so
|
|
1520
2405
|
* programmatic subscribers always receive events regardless of trace config.
|
|
1521
2406
|
*/
|
|
1522
|
-
private
|
|
1523
|
-
private
|
|
2407
|
+
private outputAxlEvent;
|
|
2408
|
+
private logAxlEvent;
|
|
1524
2409
|
/**
|
|
1525
2410
|
* Append a handoff record to session metadata.
|
|
1526
2411
|
* Note: The read-modify-write is not atomic. Concurrent handoffs in the same
|
|
@@ -1529,8 +2414,177 @@ declare class AxlRuntime extends EventEmitter {
|
|
|
1529
2414
|
* cross-execution concurrency on the same session, which is unlikely.
|
|
1530
2415
|
*/
|
|
1531
2416
|
private appendHandoffRecord;
|
|
2417
|
+
/**
|
|
2418
|
+
* Patch `duration` on the handoff record matching `toAskId` (the target
|
|
2419
|
+
* frame's askId, which the runtime stamps on `handoff_start` and which
|
|
2420
|
+
* appears as `askId` on the target's `ask_end`).
|
|
2421
|
+
*
|
|
2422
|
+
* Called from two places per handoff:
|
|
2423
|
+
* - target's `ask_end` — first-write source for ONEWAY (no return event).
|
|
2424
|
+
* - `handoff_return` — overwrites for ROUNDTRIP with the round-trip
|
|
2425
|
+
* wall-clock figure (intentional: round-trip
|
|
2426
|
+
* duration is the more useful metric for the
|
|
2427
|
+
* source-paused-for-N-ms semantic).
|
|
2428
|
+
*
|
|
2429
|
+
* No-op if no record matches `toAskId` (e.g., stream subscribed mid-
|
|
2430
|
+
* handoff, or session metadata got wiped) — `duration` stays undefined,
|
|
2431
|
+
* which is the documented default for `HandoffRecord`.
|
|
2432
|
+
*/
|
|
2433
|
+
private updateHandoffDuration;
|
|
1532
2434
|
}
|
|
1533
2435
|
|
|
2436
|
+
/**
|
|
2437
|
+
* Shared helpers for working with `AxlEvent` streams.
|
|
2438
|
+
*
|
|
2439
|
+
* Consumers writing their own accumulators / reducers reach for these so
|
|
2440
|
+
* they don't have to re-derive spec invariants at every call site. The
|
|
2441
|
+
* core runtime, AxlTestRuntime, and Studio's cost reducer ALL use these —
|
|
2442
|
+
* keeping one source of truth for each invariant.
|
|
2443
|
+
*/
|
|
2444
|
+
|
|
2445
|
+
/**
|
|
2446
|
+
* Variants that directly carry an authoritative cost charge from the
|
|
2447
|
+
* provider (or embedder). `ask_end` is a per-ask ROLLUP of these leaves
|
|
2448
|
+
* — counting it alongside them would double-charge. Any future
|
|
2449
|
+
* cost-emitting variant MUST be added here AND NOT be a rollup.
|
|
2450
|
+
*
|
|
2451
|
+
* Treated as a `Set` for O(1) membership checks; exported `as const`
|
|
2452
|
+
* tuple so exhaustiveness fixtures can cross-check against
|
|
2453
|
+
* `AXL_EVENT_TYPES`.
|
|
2454
|
+
*/
|
|
2455
|
+
declare const COST_BEARING_LEAF_TYPES: readonly ["agent_call_end", "tool_call_end", "memory_remember", "memory_recall"];
|
|
2456
|
+
/**
|
|
2457
|
+
* Cost contribution of `event` to a running total.
|
|
2458
|
+
*
|
|
2459
|
+
* Returns the event's `cost` if it's a cost-bearing leaf; 0 otherwise.
|
|
2460
|
+
* The key invariant (spec/16 decision 10): `ask_end` events carry a
|
|
2461
|
+
* per-ask ROLLUP of leaf costs that already passed through consumer
|
|
2462
|
+
* accumulators, so they contribute 0 here to avoid double-counting.
|
|
2463
|
+
*
|
|
2464
|
+
* Use this at every place you'd write `total += event.cost`:
|
|
2465
|
+
*
|
|
2466
|
+
* for (const ev of info.events) total += eventCostContribution(ev);
|
|
2467
|
+
*
|
|
2468
|
+
* Consumers who want the authoritative per-ask rollup read
|
|
2469
|
+
* `ask_end.cost` directly — that field is populated whether or not
|
|
2470
|
+
* the leaf events were summed separately. Spec decision 10.
|
|
2471
|
+
*/
|
|
2472
|
+
declare function eventCostContribution(event: AxlEvent): number;
|
|
2473
|
+
/**
|
|
2474
|
+
* True when the event is a cost-bearing leaf (contributes directly to
|
|
2475
|
+
* totals) — used by internal emitters that need to know whether to
|
|
2476
|
+
* bump per-frame askCost rollups.
|
|
2477
|
+
*
|
|
2478
|
+
* Distinct from `eventCostContribution(e) > 0`: an `agent_call_end`
|
|
2479
|
+
* with `cost: 0` is still a leaf (produced by a free / cached turn),
|
|
2480
|
+
* just one that happens to contribute zero.
|
|
2481
|
+
*/
|
|
2482
|
+
declare function isCostBearingLeaf(event: AxlEvent): boolean;
|
|
2483
|
+
/**
|
|
2484
|
+
* True when the event originates from the root ask (`depth === 0`)
|
|
2485
|
+
* or has no ask correlation at all (workflow / done / error / log).
|
|
2486
|
+
*
|
|
2487
|
+
* Used by consumers that want "just the chat bubble" tokens or
|
|
2488
|
+
* "just the root ask" visuals. Nested-ask UIs drop this filter.
|
|
2489
|
+
*
|
|
2490
|
+
* `depth` is coerced through `?? 0` so events without the field
|
|
2491
|
+
* (out-of-ask lifecycle events, synthesized terminals) are treated
|
|
2492
|
+
* as root-level — they're never at depth ≥ 1.
|
|
2493
|
+
*/
|
|
2494
|
+
declare function isRootLevel(event: AxlEvent): boolean;
|
|
2495
|
+
|
|
2496
|
+
/**
|
|
2497
|
+
* Tolerant JSON parser for progressive structured-output streaming.
|
|
2498
|
+
*
|
|
2499
|
+
* Accepts partial / truncated JSON and returns the longest parseable prefix
|
|
2500
|
+
* as a structured value. Used by `ctx.ask({ schema })` while streaming so
|
|
2501
|
+
* consumers can render fields as they arrive — see `partial_object` AxlEvent.
|
|
2502
|
+
*
|
|
2503
|
+
* Scope (intentional minimum):
|
|
2504
|
+
* - Single-pass tokenizer + recursive-descent state machine.
|
|
2505
|
+
* - Only TRAILING truncation is tolerated. Mid-document malformed input
|
|
2506
|
+
* throws. (A consumer rendering progressive output sees one well-formed
|
|
2507
|
+
* subtree at a time, never bogus shape changes.)
|
|
2508
|
+
* - Supports objects, arrays, strings (with `\"` `\\` `\n` `\t` `\r` `\b`
|
|
2509
|
+
* `\f` `\/` `\uXXXX`), numbers (int/float/exp/negative), `true` /
|
|
2510
|
+
* `false` / `null`.
|
|
2511
|
+
* - Rejects: trailing commas, comments, unquoted keys.
|
|
2512
|
+
*
|
|
2513
|
+
* Truncation recovery:
|
|
2514
|
+
* - Unterminated string → return content parsed so far.
|
|
2515
|
+
* - Unterminated number → return valid prefix if it's a complete number;
|
|
2516
|
+
* drop the key/value if the prefix is malformed
|
|
2517
|
+
* (`-`, `1.`, `1e` → drop).
|
|
2518
|
+
* - Unclosed `[` → array with parsed elements.
|
|
2519
|
+
* - Unclosed `{` → object with parsed pairs. A key without a value
|
|
2520
|
+
* is dropped.
|
|
2521
|
+
* - `,` or `:` at EOF → ignored; the last complete value wins.
|
|
2522
|
+
*
|
|
2523
|
+
* Zero runtime deps. ~250 LOC.
|
|
2524
|
+
*/
|
|
2525
|
+
/** Parse a JSON-shaped string that may be truncated mid-stream. */
|
|
2526
|
+
declare function parsePartialJson(input: string): unknown;
|
|
2527
|
+
|
|
2528
|
+
/**
|
|
2529
|
+
* Per-variant redaction rules for `AxlEvent`.
|
|
2530
|
+
*
|
|
2531
|
+
* `config.trace.redact` is an observability-boundary filter that scrubs
|
|
2532
|
+
* user/LLM content from events before they reach consumers. Two layers
|
|
2533
|
+
* historically applied this filter independently:
|
|
2534
|
+
*
|
|
2535
|
+
* 1. Core: `WorkflowContext.emitEvent()` — emit-time scrub before `onTrace`.
|
|
2536
|
+
* 2. Studio: `redactStreamEvent()` — wire-boundary scrub before WS broadcast
|
|
2537
|
+
* and again at REST serialization (`redactExecutionInfo`).
|
|
2538
|
+
*
|
|
2539
|
+
* Both layers walked the same `AxlEvent` discriminated union, with separate
|
|
2540
|
+
* if/else and switch/case ladders. Adding a new variant required updating
|
|
2541
|
+
* both. They had drifted: WS missed `workflow_start`/`workflow_end`,
|
|
2542
|
+
* `log`, and the full `memory_*` walk that core applied. Defense-in-depth
|
|
2543
|
+
* also broke for runtimes that flipped `redact` after emitting events —
|
|
2544
|
+
* REST reads of stored `ExecutionInfo.events` would leak fields the WS
|
|
2545
|
+
* layer didn't know to scrub.
|
|
2546
|
+
*
|
|
2547
|
+
* `REDACTION_RULES` is the single source of truth: a `Record<AxlEventType,
|
|
2548
|
+
* RuleFor<...>>` so adding a new variant to `AXL_EVENT_TYPES` without a
|
|
2549
|
+
* corresponding entry is a typecheck error. Every rule is pure (no
|
|
2550
|
+
* mutation), so the same rule runs at emit time and at the wire boundary
|
|
2551
|
+
* with identical results.
|
|
2552
|
+
*
|
|
2553
|
+
* Numeric/structural fields (`cost`, `tokens`, `duration`, `askId`,
|
|
2554
|
+
* `parentAskId`, `depth`, `agent`, `executionId`, `step`, `timestamp`,
|
|
2555
|
+
* `callId`, `tool`, `model`, `workflow`) are NEVER scrubbed — they're
|
|
2556
|
+
* non-PII observability metadata and load-bearing for cost rails. Rules
|
|
2557
|
+
* preserve these by spreading `{ ...event }` and only overriding the
|
|
2558
|
+
* specific user-content field(s) for that variant.
|
|
2559
|
+
*/
|
|
2560
|
+
|
|
2561
|
+
declare const REDACTED = "[redacted]";
|
|
2562
|
+
/** Type-safe rule signature: takes a specific event variant, returns the same variant. */
|
|
2563
|
+
type RuleFor<T extends AxlEventType> = (event: AxlEventOf<T>) => AxlEventOf<T>;
|
|
2564
|
+
/**
|
|
2565
|
+
* Per-variant rule table. Adding a new variant to `AXL_EVENT_TYPES`
|
|
2566
|
+
* without a corresponding entry here is a typecheck error — the
|
|
2567
|
+
* `Record<AxlEventType, ...>` mapped type forces exhaustiveness.
|
|
2568
|
+
*
|
|
2569
|
+
* For variants that ship no user content today (`delegate`,
|
|
2570
|
+
* `handoff_return`, `checkpoint_*`), the rule is `passthrough` — but
|
|
2571
|
+
* that's still an explicit, reviewed decision rather than a
|
|
2572
|
+
* silent omission.
|
|
2573
|
+
*/
|
|
2574
|
+
declare const REDACTION_RULES: {
|
|
2575
|
+
[K in AxlEventType]: RuleFor<K>;
|
|
2576
|
+
};
|
|
2577
|
+
/**
|
|
2578
|
+
* Apply the redaction rule for `event.type` and return a new event with
|
|
2579
|
+
* user-content fields scrubbed. Pure: never mutates the input.
|
|
2580
|
+
*
|
|
2581
|
+
* Caller responsibility: only invoke when redaction is enabled. The rules
|
|
2582
|
+
* unconditionally scrub — they don't gate on `config.trace.redact`. Both
|
|
2583
|
+
* `WorkflowContext.emitEvent` (core) and `redactStreamEvent` (Studio)
|
|
2584
|
+
* check the flag before calling this function.
|
|
2585
|
+
*/
|
|
2586
|
+
declare function redactEvent(event: AxlEvent): AxlEvent;
|
|
2587
|
+
|
|
1534
2588
|
/** Base error class for all Axl errors */
|
|
1535
2589
|
declare class AxlError extends Error {
|
|
1536
2590
|
readonly code: string;
|
|
@@ -1788,12 +2842,8 @@ declare class MemoryStore implements StateStore {
|
|
|
1788
2842
|
private executionHistory;
|
|
1789
2843
|
private evalHistory;
|
|
1790
2844
|
constructor();
|
|
1791
|
-
saveCheckpoint(executionId: string,
|
|
1792
|
-
getCheckpoint(executionId: string,
|
|
1793
|
-
getLatestCheckpoint(executionId: string): Promise<{
|
|
1794
|
-
step: number;
|
|
1795
|
-
data: unknown;
|
|
1796
|
-
} | null>;
|
|
2845
|
+
saveCheckpoint(executionId: string, name: string, data: unknown): Promise<void>;
|
|
2846
|
+
getCheckpoint(executionId: string, name: string): Promise<unknown | null>;
|
|
1797
2847
|
saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
|
|
1798
2848
|
getSession(sessionId: string): Promise<ChatMessage[]>;
|
|
1799
2849
|
deleteSession(sessionId: string): Promise<void>;
|
|
@@ -1837,13 +2887,44 @@ declare class MemoryStore implements StateStore {
|
|
|
1837
2887
|
declare class SQLiteStore implements StateStore {
|
|
1838
2888
|
private db;
|
|
1839
2889
|
constructor(filePath: string);
|
|
2890
|
+
/**
|
|
2891
|
+
* Idempotent schema migration. Tracks version via `PRAGMA user_version`
|
|
2892
|
+
* so reopens skip applied steps. Wrapped in `BEGIN IMMEDIATE` so
|
|
2893
|
+
* concurrent `SQLiteStore` constructors serialize at the file level
|
|
2894
|
+
* and rollback on failure leaves the DB in a clean pre-migration
|
|
2895
|
+
* state.
|
|
2896
|
+
*
|
|
2897
|
+
* Migration history:
|
|
2898
|
+
* - v1 (spec/16): rename `execution_history.steps` → `events`. The
|
|
2899
|
+
* JS-level `ExecutionInfo.steps` was renamed to `.events` in PR 1
|
|
2900
|
+
* commit 1; this brings the on-disk schema in line.
|
|
2901
|
+
* - v2 (named checkpoints): rename `checkpoints.step` (INTEGER) →
|
|
2902
|
+
* `checkpoints.name` (TEXT). The runtime now requires
|
|
2903
|
+
* `ctx.checkpoint(name, fn)` so the per-context numeric counter is
|
|
2904
|
+
* gone — names are caller-supplied stable identifiers. Existing
|
|
2905
|
+
* numeric step values become stringified names ("0", "1", …) to
|
|
2906
|
+
* preserve replay continuity for in-flight executions across the
|
|
2907
|
+
* upgrade boundary.
|
|
2908
|
+
*
|
|
2909
|
+
* Applied BEFORE `initTables()` so the subsequent `CREATE TABLE
|
|
2910
|
+
* IF NOT EXISTS` runs against the post-migration column name. Fresh
|
|
2911
|
+
* installs just create the table with `events` directly and bump
|
|
2912
|
+
* `user_version` to the current version.
|
|
2913
|
+
*
|
|
2914
|
+
* TOCTOU guard (review B-3): the initial `user_version` read is
|
|
2915
|
+
* informational only — a concurrent process can complete the
|
|
2916
|
+
* migration between that read and our `BEGIN IMMEDIATE`. We
|
|
2917
|
+
* re-read `user_version` inside the transaction and short-circuit
|
|
2918
|
+
* if it's already at target, so the non-idempotent half (writes
|
|
2919
|
+
* that went beyond a simple ALTER) never double-applies under a
|
|
2920
|
+
* race. The current v0→v1 step IS idempotent via the column-
|
|
2921
|
+
* presence check, but future migrations may not be, and the
|
|
2922
|
+
* transactional re-read costs nothing.
|
|
2923
|
+
*/
|
|
2924
|
+
private migrate;
|
|
1840
2925
|
private initTables;
|
|
1841
|
-
saveCheckpoint(executionId: string,
|
|
1842
|
-
getCheckpoint(executionId: string,
|
|
1843
|
-
getLatestCheckpoint(executionId: string): Promise<{
|
|
1844
|
-
step: number;
|
|
1845
|
-
data: unknown;
|
|
1846
|
-
} | null>;
|
|
2926
|
+
saveCheckpoint(executionId: string, name: string, data: unknown): Promise<void>;
|
|
2927
|
+
getCheckpoint(executionId: string, name: string): Promise<unknown | null>;
|
|
1847
2928
|
saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
|
|
1848
2929
|
getSession(sessionId: string): Promise<ChatMessage[]>;
|
|
1849
2930
|
deleteSession(sessionId: string): Promise<void>;
|
|
@@ -1902,12 +2983,8 @@ declare class RedisStore implements StateStore {
|
|
|
1902
2983
|
private execHistorySetKey;
|
|
1903
2984
|
private evalHistoryKey;
|
|
1904
2985
|
private evalHistorySetKey;
|
|
1905
|
-
saveCheckpoint(executionId: string,
|
|
1906
|
-
getCheckpoint(executionId: string,
|
|
1907
|
-
getLatestCheckpoint(executionId: string): Promise<{
|
|
1908
|
-
step: number;
|
|
1909
|
-
data: unknown;
|
|
1910
|
-
} | null>;
|
|
2986
|
+
saveCheckpoint(executionId: string, name: string, data: unknown): Promise<void>;
|
|
2987
|
+
getCheckpoint(executionId: string, name: string): Promise<unknown | null>;
|
|
1911
2988
|
saveSession(sessionId: string, history: ChatMessage[]): Promise<void>;
|
|
1912
2989
|
getSession(sessionId: string): Promise<ChatMessage[]>;
|
|
1913
2990
|
deleteSession(sessionId: string): Promise<void>;
|
|
@@ -1946,7 +3023,7 @@ declare class OpenAIEmbedder implements Embedder {
|
|
|
1946
3023
|
baseUrl?: string;
|
|
1947
3024
|
dimensions?: number;
|
|
1948
3025
|
});
|
|
1949
|
-
embed(texts: string[]): Promise<
|
|
3026
|
+
embed(texts: string[], signal?: AbortSignal): Promise<EmbedResult>;
|
|
1950
3027
|
}
|
|
1951
3028
|
|
|
1952
3029
|
/**
|
|
@@ -1997,4 +3074,4 @@ declare class NoopSpanManager implements SpanManager {
|
|
|
1997
3074
|
*/
|
|
1998
3075
|
declare function createSpanManager(config?: TelemetryConfig): Promise<SpanManager>;
|
|
1999
3076
|
|
|
2000
|
-
export { type Agent, type AgentCallInfo, type AgentConfig, AnthropicProvider, type AskOptions, type AwaitHumanOptions, type AxlConfig, AxlError, AxlRuntime, AxlStream, BudgetExceededError, type BudgetOptions, type BudgetResult, type ChatMessage, type ChatOptions, type CreateContextOptions, type DelegateOptions, type Effort, type Embedder, type EvalHistoryEntry, type ExecutionInfo, type ExecutionState, GeminiProvider, type GuardrailBlockHandler, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HumanDecision, InMemoryVectorStore, type InputGuardrail, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, MemoryManager, MemoryStore, NoConsensus, NoopSpanManager, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, type OutputGuardrail, type OutputValidator, type PendingDecision, type Provider, type ProviderAdapter, ProviderRegistry, type ProviderResponse, QuorumNotMet, type RaceOptions, type RecallOptions, RedisStore, type RememberOptions, type ResolvedThinkingOptions, type Result, type RetryPolicy, SQLiteStore, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type
|
|
3077
|
+
export { AXL_EVENT_TYPES, type Agent, type AgentCallEndData, type AgentCallInfo, type AgentCallParams, type AgentCallStartData, type AgentConfig, AnthropicProvider, type AnyWorkflow, type AskOptions, type AskScoped, type AwaitHumanData, type AwaitHumanOptions, type AwaitHumanResolvedData, type AxlConfig, AxlError, type AxlEvent, type AxlEventBase, type AxlEventOf, type AxlEventType, AxlRuntime, AxlStream, BudgetExceededError, type BudgetOptions, type BudgetResult, COST_BEARING_LEAF_TYPES, type CallbackMeta, type ChatMessage, type ChatOptions, type CheckpointEventData, type CreateContextOptions, type DelegateData, type DelegateOptions, type Effort, type EmbedResult, type EmbedUsage, type Embedder, type EvalHistoryEntry, type ExecuteOptions, type ExecutionInfo, type ExecutionState, GeminiProvider, type GuardrailBlockHandler, type GuardrailData, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HandoffReturnData, type HandoffStartData, type HumanDecision, InMemoryVectorStore, type InputGuardrail, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, type MemoryEventData, MemoryManager, MemoryStore, NoConsensus, NoopSpanManager, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, type OutputGuardrail, type OutputValidator, type PendingDecision, type Provider, type ProviderAdapter, ProviderRegistry, type ProviderResponse, QuorumNotMet, REDACTED, REDACTION_RULES, type RaceOptions, type RecallOptions, type RecallResult, RedisStore, type RememberOptions, type RememberResult, type ResolvedThinkingOptions, type Result, type RetryPolicy, SQLiteStore, type SchemaCheckData, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type TelemetryConfig, TimeoutError, type Tool, type ToolApprovalData, type ToolCallData, type ToolCallMessage, type ToolCallStartData, type ToolChoice, type ToolConfig, ToolDenied, type ToolDeniedData, type ToolHooks, type ValidateData, type ValidateResult, ValidationError, type VectorEntry, type VectorResult, type VectorStore, type VerifyData, VerifyError, type VerifyOptions, type VerifyRetry, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, type WorkflowEndData, type WorkflowStartData, agent, createSpanManager, defineConfig, eventCostContribution, extractJson, isCostBearingLeaf, isRootLevel, parsePartialJson, redactEvent, resolveThinkingOptions, tool, workflow, zodToJsonSchema };
|