docs: include JSDoc in website API markers

This commit is contained in:
Tianyi Cui
2026-07-19 14:14:02 +08:00
parent 7747aa450c
commit 9163f61299
32 changed files with 1479 additions and 12 deletions

View File

@@ -12,6 +12,15 @@ A context is a proxy: normal property reads go through the service resolver, whi
### ctx.extend(meta?)
```ts website-api
/**
* Create a child context with extra metadata on top of the current scope.
*
* The child prototypally inherits every property of this context; own
* properties of `meta` shadow the inherited ones. The parent is not mutated.
*
* @param meta — own properties (including symbol keys) to define on the child.
* @returns a child context inheriting from this one.
*/
extend(meta = {}): this
```
@@ -27,6 +36,18 @@ The child prototypally inherits every property of this context; own properties o
### ctx.isolate(name, label?)
```ts website-api
/**
* Create a child context with an independent service scope for `name`.
*
* Below the returned context, reads and writes of the service `name`
* resolve against the new label instead of the parent's, so a different
* implementation can be provided without affecting the parent scope.
* Passing the same `label` to two `isolate()` calls joins their scopes.
*
* @param name — the service name to isolate.
* @param label — scope label to join; defaults to a fresh unique symbol.
* @returns a child context whose `name` service resolves in the new scope.
*/
isolate(name: string, label?: symbol)
```
@@ -43,6 +64,18 @@ Below the returned context, reads and writes of the service `name` resolve again
### ctx.intercept(name, config)
```ts website-api
/**
* Add service-specific intercept config for plugins started below this
* context.
*
* Plugins loaded under the returned context see `config` merged into the
* service's resolved config (ancestor entries first; see
* `Service[symbols.resolveConfig]`). The parent context is not affected.
*
* @param name — the service name whose config to intercept.
* @param config — the intercept config to merge for that service.
* @returns a child context carrying the additional intercept entry.
*/
intercept<K extends InjectKey>(name: K, config: Context[K] extends { [symbols.config]: infer T } ? T : never): this
intercept(name: string, config: any): this
```
@@ -60,6 +93,7 @@ Plugins loaded under the returned context see `config` merged into the service's
### ctx.root
```ts website-api
/** The root context of the application (every child context shares it). @experimental */
root: this
```
@@ -70,6 +104,7 @@ The root context of the application (every child context shares it). @experiment
### ctx.baseUrl
```ts website-api
/** Base URL used to resolve relative plugin/module specifiers, if the runtime sets one. */
baseUrl?: string
```
@@ -80,6 +115,7 @@ Base URL used to resolve relative plugin/module specifiers, if the runtime sets
### ctx.events
```ts website-api
/** The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...). */
events: EventsService
```
@@ -90,6 +126,7 @@ The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...)
### ctx.logger
```ts website-api
/** The logging service. Call `ctx.logger(name)` for a named logger. */
logger: LoggerService
```
@@ -100,6 +137,7 @@ The logging service. Call `ctx.logger(name)` for a named logger.
### ctx.reflect
```ts website-api
/** The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...). */
reflect: ReflectService
```
@@ -110,6 +148,7 @@ The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...).
### ctx.registry
```ts website-api
/** The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`). */
registry: RegistryService
```
@@ -122,6 +161,7 @@ The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject
### Context.effect
```ts website-api
/** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
static readonly effect: unique symbol
```
@@ -132,6 +172,7 @@ Symbol key under which a disposer exposes its EffectMeta diagnostics tree.
### Context.filter
```ts website-api
/** Symbol key for a context's listener filter, consulted on every event dispatch. */
static readonly filter: unique symbol
```
@@ -142,6 +183,7 @@ Symbol key for a context's listener filter, consulted on every event dispatch.
### Context.isolate
```ts website-api
/** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
static readonly isolate: unique symbol
```
@@ -152,6 +194,7 @@ Symbol key of the isolation map (see the `Context[symbols.isolate]` property).
### Context.intercept
```ts website-api
/** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
static readonly intercept: unique symbol
```
@@ -162,6 +205,15 @@ Symbol key of the intercept map (see the `Context[symbols.intercept]` property).
### Context.is(value)
```ts website-api
/**
* Returns true for Cordis context proxies and context prototypes.
*
* Works across realms and across multiple copies of cordis, because the
* brand is keyed by a global symbol rather than by `instanceof`.
*
* @param value — the value to test.
* @returns `true` if `value` is a Cordis context, narrowing its type.
*/
static is(value: any): value is Context
```
@@ -179,6 +231,14 @@ Works across realms and across multiple copies of cordis, because the brand is k
### ctx.get(name, strict?)
```ts website-api
/**
* Read a service from the store without the inject requirement.
*
* @param name — the service name.
* @param strict — when `true` (default), only return implementations
* whose providing fiber is currently active.
* @returns the service value, or `undefined` when not (yet) provided.
*/
get<K extends string & keyof this>(name: K, strict?: boolean): undefined | this[K]
get(name: string, strict?: boolean): any
```
@@ -195,6 +255,15 @@ Read a service from the store without the inject requirement.
### ctx.set(name, value)
```ts website-api
/**
* Overwrite a provided service's value.
*
* Only the fiber that provided the service may set it; setting an
* unprovided name throws.
*
* @param name — the service name.
* @param value — the new service value.
*/
set<K extends string & keyof this>(name: K, value: undefined | this[K]): void
set(name: string, value: any): void
```
@@ -210,6 +279,18 @@ Only the fiber that provided the service may set it; setting an unprovided name
### ctx.provide(name, value)
```ts website-api
/**
* Register a service implementation owned by the current fiber.
*
* The service becomes visible to dependents in the same isolation scope
* once the fiber is active; it is unregistered (waking dependents) when
* the returned disposer runs or the fiber unloads. Throws if the name is
* already provided in this scope or declared as an accessor.
*
* @param name — the service name.
* @param value — the service value.
* @returns a disposer that unregisters the service.
*/
provide<K extends string & keyof this>(name: K, value: undefined | this[K]): () => void
provide(name: string, value?: any): () => void
```
@@ -227,6 +308,15 @@ The service becomes visible to dependents in the same isolation scope once the f
### ctx.accessor(name, options)
```ts website-api
/**
* Define a computed context property backed by get/set hooks.
*
* The accessor is removed when the current fiber unloads. Throws if the
* name is already declared.
*
* @param name — the context property name.
* @param options — the `get` hook and optional `set` hook.
*/
accessor(name: string, options: Omit<Property.Accessor, 'type'>): void
```
@@ -241,6 +331,16 @@ The accessor is removed when the current fiber unloads. Throws if the name is al
### ctx.mixin(name, mixins)
```ts website-api
/**
* Expose selected members of a service directly on `ctx`.
*
* Each mixed-in key becomes an accessor that forwards to the service
* (binding methods to it), so e.g. `ctx.on` forwards to `ctx.events.on`.
* Mixins are removed when the current fiber unloads.
*
* @param name — the context property holding the source service.
* @param mixins — keys to forward, or a source-key → ctx-key map.
*/
mixin<K extends string & keyof this>(name: K, mixins: (keyof this & keyof this[K])[] | Dict<string>): void
mixin<T extends {}>(source: T, mixins: (keyof this & keyof T)[] | Dict<string>): void
```

View File

@@ -7,6 +7,13 @@ The event system mixed into every context. Harness-defined events are cataloged
### ctx.parallel(name, ...args)
```ts website-api
/**
* Dispatch an event, running all listeners concurrently.
*
* @param name — the event name.
* @param args — arguments passed to every listener.
* @returns a promise resolving once every listener has settled.
*/
parallel<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promise<void>
parallel<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promise<void>
```
@@ -23,6 +30,12 @@ Dispatch an event, running all listeners concurrently.
### ctx.emit(name, ...args)
```ts website-api
/**
* Dispatch an event synchronously, ignoring listener return values.
*
* @param name — the event name.
* @param args — arguments passed to every listener.
*/
emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void
emit<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): void
```
@@ -37,6 +50,13 @@ Dispatch an event synchronously, ignoring listener return values.
### ctx.serial(name, ...args)
```ts website-api
/**
* Dispatch an event, awaiting listeners in order until one bails.
*
* @param name — the event name.
* @param args — arguments passed to each listener.
* @returns the first bail value (non-null, non-false, non-undefined), if any.
*/
serial<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
serial<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
```
@@ -53,6 +73,13 @@ Dispatch an event, awaiting listeners in order until one bails.
### ctx.bail(name, ...args)
```ts website-api
/**
* Dispatch an event, calling listeners in order until one bails.
*
* @param name — the event name.
* @param args — arguments passed to each listener.
* @returns the first bail value (non-null, non-false, non-undefined), if any.
*/
bail<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
bail<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
```
@@ -69,6 +96,16 @@ Dispatch an event, calling listeners in order until one bails.
### ctx.waterfall(name, ...args)
```ts website-api
/**
* Dispatch an event whose last argument is a `next` continuation.
*
* Each listener wraps the rest of the chain: calling `next()` invokes the
* next listener (finally the built-in behavior); not calling it vetoes.
*
* @param name — the event name.
* @param args — listener arguments; the final one is the innermost `next`.
* @returns the outermost listener's return value.
*/
waterfall<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
waterfall<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
```
@@ -86,6 +123,14 @@ Each listener wraps the rest of the chain: calling `next()` invokes the next lis
### ctx.on(name, listener, options?)
```ts website-api
/**
* Register an event listener owned by the current fiber.
*
* @param name — the event name to listen for.
* @param listener — called with the dispatch arguments.
* @param options — listener options; a boolean is shorthand for `prepend`.
* @returns a disposer removing the listener; `true` if it was still registered.
*/
on<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean
```
@@ -102,6 +147,14 @@ Register an event listener owned by the current fiber.
### ctx.once(name, listener, options?)
```ts website-api
/**
* Same as `on()`, but the listener disposes itself after its first call.
*
* @param name — the event name to listen for.
* @param listener — called at most once with the dispatch arguments.
* @param options — listener options; a boolean is shorthand for `prepend`.
* @returns a disposer removing the listener; `true` if it was still registered.
*/
once<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean
```
@@ -120,6 +173,7 @@ Same as `on()`, but the listener disposes itself after its first call.
Options accepted by `ctx.on()` and `ctx.once()`.
```ts website-api
/** Options accepted by `ctx.on()` and `ctx.once()`. */
interface EventOptions {
/** Add the listener before existing listeners for the same event. */
prepend?: boolean
@@ -136,6 +190,14 @@ Event dispatch strategy used by the event service.
`emit` runs synchronous listeners without awaiting them, `parallel` awaits all listeners together, `serial` awaits them in order until one bails, `bail` stops on the first synchronous bail value, and `waterfall` composes listeners around a final `next` callback.
```ts website-api
/**
* Event dispatch strategy used by the event service.
*
* `emit` runs synchronous listeners without awaiting them, `parallel` awaits
* all listeners together, `serial` awaits them in order until one bails,
* `bail` stops on the first synchronous bail value, and `waterfall` composes
* listeners around a final `next` callback.
*/
type DispatchMode = 'emit' | 'parallel' | 'serial' | 'bail' | 'waterfall'
```

View File

@@ -7,6 +7,19 @@ A fiber is one loaded plugin instance: its lifecycle state, validated config, an
### ctx.effect(execute, label?)
```ts website-api
/**
* Register a cleanup-aware effect on this fiber.
*
* `execute` runs immediately; the disposers it produces are collected and
* run (in reverse order) either when the returned disposer is called or
* when the fiber unloads, whichever comes first. Calling the disposer twice
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
* already disposed, and `TypeError` if `execute` returns an invalid shape.
*
* @param execute — the effect body; see {@link Effect} for accepted shapes.
* @param label — effect label shown in `getEffects()` diagnostics.
* @returns a disposer that tears the effect down and settles once done.
*/
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
```
@@ -24,6 +37,7 @@ Register a cleanup-aware effect on this fiber.
### ctx.fiber
```ts website-api
/** The fiber (plugin runtime instance) that owns this context. */
fiber: Fiber
```
@@ -41,6 +55,7 @@ A fiber tracks dependency state, validated config, lifecycle effects, and cleanu
### fiber.uid
```ts website-api
/** Unique id within the registry; 0 for the root fiber, `null` once disposed. */
public uid: number | null
```
@@ -51,6 +66,7 @@ Unique id within the registry; 0 for the root fiber, `null` once disposed.
### fiber.ctx
```ts website-api
/** The context this fiber's plugin runs in (extends the parent context). */
public readonly ctx: Context
```
@@ -61,6 +77,7 @@ The context this fiber's plugin runs in (extends the parent context).
### fiber.config
```ts website-api
/** The validated plugin config (updated by `update()`). */
public config: any
```
@@ -71,6 +88,7 @@ The validated plugin config (updated by `update()`).
### fiber.state
```ts website-api
/** Current lifecycle state; transitions emit `internal/status`. */
public state
```
@@ -81,6 +99,7 @@ Current lifecycle state; transitions emit `internal/status`.
### fiber.dispose
```ts website-api
/** Dispose this fiber: unload the plugin, then settle once cleanup finished. */
public readonly dispose: () => Promise<void>
```
@@ -91,6 +110,7 @@ Dispose this fiber: unload the plugin, then settle once cleanup finished.
### fiber.store
```ts website-api
/** Snapshot of required service implementations while loaded; `undefined` otherwise. */
public store: Dict<Impl> | undefined
```
@@ -101,6 +121,7 @@ Snapshot of required service implementations while loaded; `undefined` otherwise
### fiber.inertia
```ts website-api
/** The in-flight load/unload transition, if one is currently running. */
public inertia: Promise<void> | undefined
```
@@ -111,6 +132,7 @@ The in-flight load/unload transition, if one is currently running.
### fiber.name
```ts website-api
/** The plugin's display name, inherited from the nearest named ancestor, else `'root'`. */
get name()
```
@@ -121,6 +143,12 @@ The plugin's display name, inherited from the nearest named ancestor, else `'roo
### fiber.assertActive()
```ts website-api
/**
* Throw if the fiber has already been disposed.
*
* @returns nothing when the fiber is still active.
* @throws {CordisError} `INACTIVE_EFFECT` when the fiber's uid has been cleared.
*/
assertActive()
```
@@ -133,6 +161,19 @@ Throw if the fiber has already been disposed.
### fiber.effect(execute, label?)
```ts website-api
/**
* Register a cleanup-aware effect on this fiber.
*
* `execute` runs immediately; the disposers it produces are collected and
* run (in reverse order) either when the returned disposer is called or
* when the fiber unloads, whichever comes first. Calling the disposer twice
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
* already disposed, and `TypeError` if `execute` returns an invalid shape.
*
* @param execute — the effect body; see {@link Effect} for accepted shapes.
* @param label — effect label shown in `getEffects()` diagnostics.
* @returns a disposer that tears the effect down and settles once done.
*/
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>
```
@@ -150,6 +191,11 @@ Register a cleanup-aware effect on this fiber.
### fiber.getEffects()
```ts website-api
/**
* Return metadata for currently registered effects.
*
* @returns one {@link EffectMeta} tree per labeled live effect.
*/
getEffects()
```
@@ -162,6 +208,12 @@ Return metadata for currently registered effects.
### fiber.await()
```ts website-api
/**
* Wait for current lifecycle work and rethrow startup errors.
*
* @returns this fiber, once it has settled into a stable state.
* @throws the config-validation or plugin-startup error, if any.
*/
async await()
```
@@ -174,6 +226,12 @@ Wait for current lifecycle work and rethrow startup errors.
### fiber.restart()
```ts website-api
/**
* Dispose and immediately reload this plugin with its current config.
*
* @returns a promise resolving once the reload settled.
* @throws {CordisError} `INACTIVE_EFFECT` when the fiber is already disposed.
*/
async restart()
```
@@ -186,6 +244,17 @@ Dispose and immediately reload this plugin with its current config.
### fiber.update(config, noSave?)
```ts website-api
/**
* Validate and apply new config, then restart the plugin.
*
* Runs the `internal/update` waterfall first, so update hooks (and HMR)
* can veto or replace the restart.
*
* @param config — the new raw config; validated before anything restarts.
* @param noSave — hint for persistence hooks not to write the change back.
* @returns nothing; the restart runs behind the `internal/update` waterfall.
* @throws {ValidationError} when the new config fails validation.
*/
update(config: any, noSave = false)
```
@@ -205,6 +274,13 @@ Effect body result accepted by `ctx.effect()` and plugin startup.
Either a single disposer, a promise of one, or a (possibly async) iterable yielding several — generator effects register each yielded disposer as it is produced.
```ts website-api
/**
* Effect body result accepted by `ctx.effect()` and plugin startup.
*
* Either a single disposer, a promise of one, or a (possibly async) iterable
* yielding several — generator effects register each yielded disposer as it
* is produced.
*/
type Effect<T = any> =
| SyncEffect<T>
| AsyncEffect<T>
@@ -218,6 +294,12 @@ Function returned by an effect to release resources during disposal.
Disposers run in reverse registration order when the owning fiber unloads; they may be async, in which case unloading awaits them.
```ts website-api
/**
* Function returned by an effect to release resources during disposal.
*
* Disposers run in reverse registration order when the owning fiber unloads;
* they may be async, in which case unloading awaits them.
*/
type Disposable<T = any> = () => T
```
@@ -228,6 +310,7 @@ type Disposable<T = any> = () => T
Tree node used to expose nested effect labels for diagnostics.
```ts website-api
/** Tree node used to expose nested effect labels for diagnostics. */
interface EffectMeta {
/** Human-readable effect label, e.g. `ctx.on("event")` or `ctx.provide("name")`. */
label: string
@@ -243,6 +326,7 @@ interface EffectMeta {
Framework error with a stable machine-readable code.
```ts website-api
/** Framework error with a stable machine-readable code. */
class CordisError extends Error {
/**
* @param code — the stable error code; also the default message.
@@ -251,6 +335,7 @@ class CordisError extends Error {
constructor(public code: CordisError.Code, message?: string)
}
/** Cordis error code definitions. */
namespace CordisError {
export type Code = keyof typeof Code
@@ -267,6 +352,7 @@ namespace CordisError {
Error raised when plugin configuration fails standard-schema validation.
```ts website-api
/** Error raised when plugin configuration fails standard-schema validation. */
class ValidationError extends TypeError {
name = 'ValidationError'

View File

@@ -7,6 +7,16 @@ Plugin loading and dependency injection.
### ctx.inject(deps, callback)
```ts website-api
/**
* Run a callback once the requested services are available.
*
* Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback
* is unloaded and re-run whenever a required service changes.
*
* @param deps — required services, as an array or a name → config map.
* @param callback — plugin body called with `(ctx, config)`.
* @returns the fiber; awaiting it settles once loading finished.
*/
inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>
```
@@ -23,6 +33,14 @@ Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback is unloade
### ctx.plugin(plugin, ...args)
```ts website-api
/**
* Load a plugin in the current context.
*
* @param plugin — a function, class, or `{ apply }` object plugin.
* @param args — the plugin config, validated against its `Config` schema.
* @returns the fiber; awaiting it settles once loading finished
* (rejecting on config or startup errors).
*/
plugin<P extends Plugin>(plugin: P, ...args: Spread<GetPluginConfig<P>>): Fiber & PromiseLike<Fiber>
```
@@ -40,11 +58,13 @@ Load a plugin in the current context.
Supported plugin entrypoint shapes.
```ts website-api
/** Supported plugin entrypoint shapes. */
type Plugin<T = any> =
| Plugin.Function<T>
| Plugin.Constructor<T>
| Plugin.Object<T>
/** Types associated with plugin entrypoints and runtime records. */
namespace Plugin {
/** Shared metadata understood by the plugin registry and related tooling. */
export interface Base<T = any> {
@@ -104,8 +124,16 @@ Service dependency declaration accepted by plugins and the `@Inject` decorator.
Array form requests services without intercept config. Object form maps each service name to optional intercept config for the plugin context.
```ts website-api
/**
* Service dependency declaration accepted by plugins and the `@Inject`
* decorator.
*
* Array form requests services without intercept config. Object form maps each
* service name to optional intercept config for the plugin context.
*/
type Inject<M = Dict> = (keyof M)[] | { [K in keyof M]?: M[K] }
/** Utilities for normalizing plugin dependency declarations. */
namespace Inject {
/**
* Convert array/object/class-inherited inject metadata into a plain map.

View File

@@ -12,6 +12,7 @@ Subclasses call `super(ctx, name)` from their constructor. The service is regist
### service.name
```ts website-api
/** The service name this instance is registered under. */
public name!: string
```
@@ -24,6 +25,7 @@ The service name this instance is registered under.
### Service.init
```ts website-api
/** Symbol key of an instance method run after construction (class plugins). */
static readonly init: unique symbol
```
@@ -34,6 +36,7 @@ Symbol key of an instance method run after construction (class plugins).
### Service.check
```ts website-api
/** Symbol key of the availability predicate passed to `ctx.provide()`. */
static readonly check: unique symbol
```
@@ -44,6 +47,7 @@ Symbol key of the availability predicate passed to `ctx.provide()`.
### Service.config
```ts website-api
/** Symbol key of the phantom intercept-config type parameter. */
static readonly config: unique symbol
```
@@ -54,6 +58,7 @@ Symbol key of the phantom intercept-config type parameter.
### Service.invoke
```ts website-api
/** Symbol key of the call body making a service callable (e.g. `ctx.logger()`). */
static readonly invoke: unique symbol
```
@@ -64,6 +69,7 @@ Symbol key of the call body making a service callable (e.g. `ctx.logger()`).
### Service.extend
```ts website-api
/** Symbol key of the helper deriving an extended service instance. */
static readonly extend: unique symbol
```
@@ -74,6 +80,7 @@ Symbol key of the helper deriving an extended service instance.
### Service.tracker
```ts website-api
/** Symbol key of the tracker metadata used for context tracing. */
static readonly tracker: unique symbol
```
@@ -84,6 +91,7 @@ Symbol key of the tracker metadata used for context tracing.
### Service.resolveConfig
```ts website-api
/** Symbol key of the intercept-config resolution helper below. */
static readonly resolveConfig: unique symbol
```

View File

@@ -11,6 +11,15 @@ Concrete agent factory and driver service.
### ctx.agentLoop.create(id, options?, meta?)
```ts website-api
/**
* Create an agent and session under one caller-supplied identity, owned by
* the accessing fiber. Constructor-driven config calls mint a fresh combined
* id before entering this boundary.
* @param id - shared agent/session identity.
* @param options - concrete loop options.
* @param meta - optional fresh-session workspace metadata.
* @returns the published running agent.
*/
create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Agent
```
@@ -27,6 +36,12 @@ Create an agent and session under one caller-supplied identity, owned by the acc
### ctx.agentLoop.createAgent(ownerCtx, options)
```ts website-api
/**
* Create an owned agent on a caller-supplied session id.
* @param ownerCtx - caller context that structurally owns the transaction.
* @param options - identities, session seed/metadata, loop options, setup, and cancellation.
* @returns the published handle.
*/
async createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>
```
@@ -42,6 +57,12 @@ Create an owned agent on a caller-supplied session id.
### ctx.agentLoop.resume(ownerCtx, options)
```ts website-api
/**
* Resume an owned agent from the configured persistence service.
* @param ownerCtx - caller context that owns load, setup, and the live lifecycle.
* @param options - persisted identity, loop options, setup, and cancellation.
* @returns the published handle.
*/
async resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>
```

View File

@@ -11,6 +11,18 @@ Agent registry (`ctx.agents`): tracks live agents so UI, hook, and orchestrator
### ctx.agents.setFactory(factory)
```ts website-api
/**
* Register the agent-creation factory (the loop calls this on construction,
* effect-scoped). A traced Cordis service is canonicalized to its concrete
* target; each create/resume call is then traced through that caller's
* context so ownership follows the caller without stacking proxy layers.
* Throws if a factory is already registered. Returns the disposer; on
* dispose the factory slot is cleared.
* @param factory - the loop-owned factory {@link create}/{@link resume} delegate to.
* @returns the disposer that clears the factory slot. The exact
* Cordis effect disposer (single-shot): composite (generator) effects may
* yield it directly — exact identity nests the teardown in order.
*/
setFactory(factory: AgentFactory): () => void
```
@@ -25,6 +37,15 @@ Register the agent-creation factory (the loop calls this on construction, effect
### ctx.agents.create(options)
```ts website-api
/**
* Create and publish a new agent through the registered factory.
* Distinct from {@link register} (which records an already-constructed
* agent): this constructs the agent and its session. Rejects if no factory is
* registered or creation/setup fails. The resolved {@link AgentHandle} lets
* the owner tear down exactly this agent.
* @param options - shared identity, session seed/metadata, and agent options.
* @returns the handle after setup, rollback-covered publication, and loop start complete.
*/
async create(options: CreateAgentOptions): Promise<AgentHandle>
```
@@ -39,6 +60,13 @@ Create and publish a new agent through the registered factory. Distinct from reg
### ctx.agents.resume(options)
```ts website-api
/**
* Load a persisted session and resume an agent on it through the registered
* factory. Rejects if no factory is registered; the factory rejects if
* session persistence is not configured or persistence/setup fails.
* @param options - persisted identity, configuration, and optional setup.
* @returns the handle after setup, rollback-covered publication, and loop start complete.
*/
async resume(options: ResumeAgentOptions): Promise<AgentHandle>
```
@@ -53,6 +81,24 @@ Load a persisted session and resume an agent on it through the registered factor
### ctx.agents.register(agent)
```ts website-api
/**
* Register a live agent. Throws if an agent with the same id is already
* registered. Emits `agent/created` on registration and `agent/disposed`
* when the calling fiber is disposed — both with the agent's scope carrier
* (`scopeTarget(agent, agent)`): the subject is the agent in hand, so the
* emits are scope-filtered regardless of which context invoked `register`
* (calling through `agent.ctx` scopes EFFECTS; dispatch scoping always
* requires passing the carrier). Returns the disposer.
* @param agent - the already-constructed agent to record in the store.
* @returns the EXACT Cordis effect disposer (single-shot; a repeat call
* returns undefined without awaiting an in-flight teardown). Exact
* identity is load-bearing: a composite (generator) effect that owns a
* teardown ORDER — the agent factory's lifecycle chain — must yield THIS
* function so Cordis nests the unregistration at that yield position;
* yielding a wrapper would leave it disposing as a concurrent sibling on
* owner unload, unregistering the agent (and emitting `agent/disposed`)
* while its final turn is still draining.
*/
register(agent: Agent): () => void
```
@@ -67,6 +113,21 @@ Register a live agent. Throws if an agent with the same id is already registered
### ctx.agents.enter(agent, owner)
```ts website-api
/**
* Insert an already-constructed agent without announcing it. This is the
* advanced ordered-lifecycle primitive used by the async agent factory: it
* first completes setup while the agent is unpublished, then assigns the
* returned detach closure into its pre-installed composite teardown before
* calling {@link announce}. Ordinary callers use {@link register}.
* @param agent - the prepared, unpublished agent.
* @param owner - live agent whose scoped context created this agent, or
* undefined for a top-level runtime root. This is runtime ownership, not
* the resumed session's durable parent lineage.
* @returns an idempotent closure that removes this exact entry and emits
* `agent/disposed` with listener failures contained. When called from a
* synchronous `agent/created` listener, removal and disposal wait until
* that creation dispatch unwinds.
*/
enter(agent: Agent, owner: Agent | undefined): () => void
```
@@ -82,6 +143,13 @@ Insert an already-constructed agent without announcing it. This is the advanced
### ctx.agents.announce(agent)
```ts website-api
/**
* Announce an agent previously inserted with {@link enter}.
* @param agent - the live inserted agent to announce.
* @throws if `agent` is not the exact live registry entry for its id, or its
* creation announcement already began (including a reentrant call from a
* creation listener).
*/
announce(agent: Agent): void
```
@@ -94,6 +162,11 @@ Announce an agent previously inserted with enter.
### ctx.agents.get(id)
```ts website-api
/**
* Look up a live agent.
* @param id - the shared agent/session id to look up.
* @returns the agent, or undefined when no live agent has that id.
*/
get(id: SessionId): Agent | undefined
```
@@ -108,6 +181,14 @@ Look up a live agent.
### ctx.agents.isOwnedBy(id, owner)
```ts website-api
/**
* Test whether a live agent was created through one exact parent agent's
* scoped context. Runtime ownership is independent of durable session
* lineage and remains unambiguous when unrelated providers reuse an id.
* @param id - the candidate child agent's shared agent/session id.
* @param owner - the expected runtime creator agent.
* @returns true only while the exact child entry is live under that owner.
*/
isOwnedBy(id: SessionId, owner: Agent): boolean
```
@@ -123,6 +204,10 @@ Test whether a live agent was created through one exact parent agent's scoped co
### ctx.agents.list()
```ts website-api
/**
* All live agents, in registration order.
* @returns a fresh array; mutating it does not affect the registry.
*/
list(): Agent[]
```
@@ -135,6 +220,12 @@ All live agents, in registration order.
### ctx.agents.roots()
```ts website-api
/**
* All live top-level agents in registration order. A top-level agent was
* created without an owning agent context; durable session lineage does not
* affect this runtime relation, so a resumed fork may still be a root.
* @returns a fresh array; mutating it does not affect the registry.
*/
roots(): Agent[]
```

View File

@@ -11,6 +11,24 @@ Approval service that applies session policy before answerers and logs every ask
### ctx.approval.request(req)
```ts website-api
/**
* Ask the composed answerers to decide one readonly same-process request.
* The service borrows the request, agent, session, and live signal directly.
* The request requires an open turn because the audit pair must be enclosed
* by the durable log's commit/replay boundary; an idle ask rejects before
* appending anything. The answerer phase always produces an outcome: an
* aborted signal yields `'cancelled'`, a missing or throwing answerer yields
* `'unavailable'` (fail closed), and a rogue non-vocabulary return value is
* normalized to `'unavailable'`. A failure that prevents either audit append
* from committing still rejects because returning an unlogged decision would
* violate the pair. Session contains post-commit observer failures, so an
* authoritative append cannot reject the request or suppress its matching
* audit event.
* @param req - the pending decision (agent, tool identity, reason, signal).
* @returns the closed outcome; `'allowed-once'` is the only grant.
* @throws when no turn is open or either audit event fails before the session
* append commit point.
*/
async request(req: ApprovalRequest): Promise<ApprovalOutcome>
```

View File

@@ -11,6 +11,12 @@ Registry (`ctx.bashEnv`) for trusted, per-execution `DSH_*` variables. The names
### ctx.bashEnv.register(contributor)
```ts website-api
/**
* Register one environment contributor. Names and keys are unique; built-in
* keys are reserved. Registration is disposed with the calling plugin fiber.
* @param contributor - declared key ownership and per-execution resolver.
* @returns the disposer that unregisters the contribution.
*/
register(contributor: BashEnvContributor): () => void
```
@@ -25,6 +31,11 @@ Register one environment contributor. Names and keys are unique; built-in keys a
### ctx.bashEnv.collect(execution)
```ts website-api
/**
* Build the trusted `DSH_*` snapshot for one bash tool execution.
* @param execution - the current tool execution.
* @returns an immutable environment overlay containing built-ins and current contributions.
*/
collect(execution: ToolExecution): DshEnvironment
```
@@ -39,6 +50,10 @@ Build the trusted `DSH_*` snapshot for one bash tool execution.
### ctx.bashEnv.list()
```ts website-api
/**
* Enumerate plugin-contributed variables without executing their resolvers.
* @returns declarations sorted by environment variable name.
*/
list(): BashEnvVariableInfo[]
```

View File

@@ -16,6 +16,11 @@ Implementations must honor these semantics:
### ctx.bash.sandboxMode
```ts website-api
/**
* The sandbox mode this executor applies by default, or `undefined` when it
* does not sandbox commands.
* @returns the configured default sandbox mode, when supported.
*/
get sandboxMode(): SandboxMode | undefined
```
@@ -26,6 +31,12 @@ The sandbox mode this executor applies by default, or `undefined` when it does n
### ctx.bash.resolve(request)
```ts website-api
/**
* Apply implementation-owned defaults and caps to a request before execution.
* @param request - the caller's request; omitted fields get this
* implementation's defaults, capped fields are clamped.
* @returns the fully-specified spec to hand to {@link run}/{@link start}.
*/
abstract resolve(request: BashExecRequest): BashExecSpec
```
@@ -40,6 +51,12 @@ Apply implementation-owned defaults and caps to a request before execution.
### ctx.bash.run(spec)
```ts website-api
/**
* Run a command in the foreground; resolves when it finishes.
* @param spec - a resolved spec from {@link resolve}, never a raw request.
* @returns the outcome; nonzero exits, timeout kills, and abort kills
* resolve with a descriptive result rather than reject.
*/
abstract run(spec: BashExecSpec): Promise<BashRunResult>
```
@@ -54,6 +71,11 @@ Run a command in the foreground; resolves when it finishes.
### ctx.bash.start(spec)
```ts website-api
/**
* Start a background process and return its handle immediately.
* @param spec - a resolved spec from {@link resolve}, never a raw request.
* @returns the live process handle (reads, kill, quiescence promise).
*/
abstract start(spec: BashExecSpec): BashProcess
```

View File

@@ -11,6 +11,13 @@ Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and subs
### ctx.codeRuntime.language
```ts website-api
/**
* The source language {@link run} expects `program` to be written in, as a
* lowercase identifier. Informational, not gating — a consumer that
* generates language-specific presentation (typed SDK stubs, usage
* instructions) switches on it and fails loud on a language it cannot
* present. Well-known value: `'typescript'`.
*/
abstract readonly language: string
```
@@ -21,6 +28,12 @@ The source language run expects `program` to be written in, as a lowercase ident
### ctx.codeRuntime.isolation
```ts website-api
/**
* The execution substrate, as a lowercase identifier. Informational, not
* gating — a descriptor so deployments and diagnostics can tell backends
* apart, not a security claim. Well-known values: `'worker-thread'`,
* `'process'`, `'container'`.
*/
abstract readonly isolation: string
```
@@ -31,6 +44,15 @@ The execution substrate, as a lowercase identifier. Informational, not gating
### ctx.codeRuntime.run(request)
```ts website-api
/**
* Execute one program against the request's bindings and capture what it
* emitted. See the class doc for the resolution contract (error is a result
* field; rejection means seam misuse only).
* @param request - the program, its bindings, and the abort signal; the
* request carries everything the runtime acts on, with no hidden defaults.
* @returns the run's outcome: completion value (when transferable), the
* ordered log capture, and the failure (if any).
*/
abstract run(request: CodeRunRequest): Promise<CodeRunResult>
```

View File

@@ -11,6 +11,21 @@ Abstract compaction service. Implementations own trigger policy, retention, and
### ctx.compact.compactIfNeeded(agent, fullSystemPrompt, sessionPrefix, signal)
```ts website-api
/**
* Check token pressure and compact if the conversation is too large.
* Estimate the next request, including its session prefix, derived history,
* and system prompt. Above threshold, compact a head-anchored range ending at
* a balanced tool boundary and reconsolidate any prior automatic checkpoint.
* Return `null` when no compaction is needed or an open tail leaves no safe
* cutoff. A single oversized retained unit or prefix cannot be repaired here.
*
* @param agent - agent context owning the session surface and model options.
* @param fullSystemPrompt - assembled system prompt, counted toward the estimate.
* @param sessionPrefix - the instance's composed session prefix, counted toward the
* estimate.
* @param signal - cancellation signal; model-backed implementations must forward it.
* @returns the compaction result, or `null` if no compaction was needed.
*/
abstract compactIfNeeded( agent: CompactAgentContext, fullSystemPrompt: string, sessionPrefix: readonly Message[], signal: AbortSignal, ): Promise<CompactionResult | null>
```
@@ -28,6 +43,23 @@ Check token pressure and compact if the conversation is too large. Estimate the
### ctx.compact.compactRegion(start, end, agent, signal?)
```ts website-api
/**
* Forcibly compact a range of surface nodes into a single summary node.
* `start` and `end` name an inclusive span by surface position, not numeric seq
* order; replacements can make visible seqs non-monotonic. Both edges must be
* balanced so assistant tool calls remain paired with their results. A model-
* backed implementation forwards cancellation and rejects active, missing,
* reversed, or unbalanced ranges. The target session is `agent.session`.
* Use {@link toolPairingBalancedBefore} and {@link toolPairingBalancedAfter}
* for the edge checks.
*
* @param start - first surface seq, inclusive.
* @param end - last surface seq, inclusive.
* @param agent - context whose session is mutated and whose routing options guide summarization.
* @param signal - optional cancellation; model-backed implementations must forward it.
* @throws when compaction is active or the range is missing, reversed, or unbalanced.
* @returns the appended event seqs, summary, replaced range, and token accounting.
*/
abstract compactRegion( start: number, end: number, agent: CompactAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>
```

View File

@@ -11,6 +11,16 @@ Every event the harness packages declare on the cordis event bus (40 total), gro
**Mode:** `emit`
```ts website-api
/**
* A fully configured agent and live session were published. Setup is
* composition-only; `agent/session-start` is the first startup-driving seam.
* Synchronous listener failure vetoes publication, while returned-promise
* rejection is reported. Detach requested during dispatch waits until every
* creation listener has observed the stable entry.
* @param agent - the newly registered agent with its live session and completed setup.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode emit
*/
'agent/created'(this: Scoped<Agent>, agent: Agent): void
```
@@ -25,6 +35,14 @@ A fully configured agent and live session were published. Setup is composition-o
**Mode:** `emit`
```ts website-api
/**
* An agent left the registry; AgentLoop emits this after driver quiescence
* but before session detachment and scoped-registration unwind. Custom
* registry users own their driver-ordering contract.
* @param agent - the exact agent removed from the registry.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode emit
*/
'agent/disposed'(this: Scoped<Agent>, agent: Agent): void
```
@@ -39,6 +57,16 @@ An agent left the registry; AgentLoop emits this after driver quiescence but bef
**Mode:** `emit`
```ts website-api
/**
* A step or turn errored. The loop reports a failure here (plus the logger)
* even when the error has no in-turn position for a session `error` event.
* @param agent - the agent whose turn errored.
* @param turn - the turn in which the failure surfaced.
* @param step - the step at which the failure surfaced.
* @param error - the failure, verbatim.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode emit
*/
'agent/error'(this: Scoped<Agent>, agent: Agent, turn: number, step: number, error: Error): void
```
@@ -56,6 +84,22 @@ A step or turn errored. The loop reports a failure here (plus the logger) even w
**Mode:** `serial`
```ts website-api
/**
* Awaited serial checkpoint for session-surface mutation after prompt
* assembly and before `step/start`; appends land outside the pending step.
* The loop derives history once afterward, so compaction records and
* replacements are included without rewriting an assembled request. The
* prompt and prefix are the exact pressure inputs for that request, and
* `signal` cancels listener work.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @param agent - the agent opening the step.
* @param turn - the open turn number.
* @param step - the pending step number.
* @param fullSystemPrompt - the assembled prompt.
* @param sessionPrefix - the frozen request prefix.
* @param signal - the turn abort signal.
* @mode serial
*/
'agent/pre-step'(this: Scoped<Agent>, agent: Agent, turn: number, step: number, fullSystemPrompt: string, sessionPrefix: readonly Message[], signal: AbortSignal): Promise<void> | void
```
@@ -75,6 +119,15 @@ Awaited serial checkpoint for session-surface mutation after prompt assembly and
**Mode:** `waterfall`
```ts website-api
/**
* Allow, rewrite, or block one drained prompt before it becomes a user
* message. Call `next()` for the unchanged default.
* @param agent - the agent draining its inbox.
* @param content - the drained message's blocks, as queued.
* @param source - the message's resolved source.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode waterfall
*/
'agent/prompt-submit'(this: Scoped<Agent>, agent: Agent, content: ContentBlock[], source: MessageSource, next: () => Promise<PromptDecision>): Promise<PromptDecision>
```
@@ -91,6 +144,15 @@ Allow, rewrite, or block one drained prompt before it becomes a user message. Ca
**Mode:** `emit`
```ts website-api
/**
* Detached, frozen content entered the agent's inbox. Source defaults have
* already been applied, so these are the exact values retained for the log.
* @param agent - the agent whose inbox received the message.
* @param content - the accepted content blocks retained by the inbox.
* @param info - the accepted source plus whether it entered as steering.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode emit
*/
'agent/queued'(this: Scoped<Agent>, agent: Agent, content: ContentBlock[], info: { source: MessageSource; steering: boolean }): void
```
@@ -107,6 +169,17 @@ Detached, frozen content entered the agent's inbox. Source defaults have already
**Mode:** `waterfall`
```ts website-api
/**
* Replace the frozen call configuration. Model-visible content must use
* logged channels; this seam cannot mutate messages. Injection here joins
* the next request because the current step boundary is already fixed.
* @param agent - the agent making the model call.
* @param turn - the open turn number.
* @param step - the step whose request this is.
* @param config - the config the loop would use (frozen); return a replacement to switch.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode waterfall
*/
'agent/request'(this: Scoped<Agent>, agent: Agent, turn: number, step: number, config: LlmCallConfig, next: () => Promise<LlmCallConfig>): Promise<LlmCallConfig>
```
@@ -124,6 +197,20 @@ Replace the frozen call configuration. Model-visible content must use logged cha
**Mode:** `waterfall`
```ts website-api
/**
* Compose request-only messages placed before derived history. The frozen
* result is computed once per loop instance, logged on its anchoring request
* header, and reused so the provider prefix remains stable. Interrupted
* composition is discarded. Composition precedes the first `agent/pre-step`
* and request boundary, so listener appends join the current request and
* pressure accounting sees the composed prefix. Changing context belongs in
* history; contributors should prepend to `await next()` to preserve registration order.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @param agent - the agent whose session prefix is being composed.
* @param prefix - the frozen seed; return an extended replacement.
* @param signal - aborts composition when the step is torn down.
* @mode waterfall
*/
'agent/session-prefix'(this: Scoped<Agent>, agent: Agent, prefix: Message[], signal: AbortSignal, next: () => Promise<Message[]>): Promise<Message[]>
```
@@ -140,6 +227,16 @@ Compose request-only messages placed before derived history. The frozen result i
**Mode:** `emit`
```ts website-api
/**
* The session lifecycle began, once before the first turn. Use
* `agent.inject()` to seed model-facing context. This is a notification, not
* a veto; disposal requested by a lifecycle owner is rechecked before the
* driver starts.
* @param agent - the agent whose session lifecycle began.
* @param source - why the session started (fresh startup, resume, …).
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode emit
*/
'agent/session-start'(this: Scoped<Agent>, agent: Agent, source: SessionStartSource): void
```
@@ -155,6 +252,14 @@ The session lifecycle began, once before the first turn. Use `agent.inject()` to
**Mode:** `emit`
```ts website-api
/**
* Agent status changed (`idle` ⇄ `running`, or → `disposed`). `send()` does
* not enter `running` synchronously; drive lifecycle from this event.
* @param agent - the agent whose status flipped.
* @param status - the status just entered (the transition's destination).
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode emit
*/
'agent/status'(this: Scoped<Agent>, agent: Agent, status: AgentStatus): void
```
@@ -170,6 +275,16 @@ Agent status changed (`idle` ⇄ `running`, or → `disposed`). `send()` does no
**Mode:** `waterfall`
```ts website-api
/**
* Waterfall: post-process the assembled assistant {@link Message} before
* tool dispatch (validation, content rewriting, …).
* @param agent - the agent that received the step's response.
* @param turn - the open turn number.
* @param step - the step that produced the message.
* @param message - the assistant message as assembled from the stream.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode waterfall
*/
'agent/step-result'(this: Scoped<Agent>, agent: Agent, turn: number, step: number, message: Message, next: () => Promise<Message>): Promise<Message>
```
@@ -187,6 +302,15 @@ Waterfall: post-process the assembled assistant Message before tool dispatch (va
**Mode:** `waterfall`
```ts website-api
/**
* Override whether the turn continues. The default continues after tool
* calls or steering and stops otherwise; a continue reason becomes steering.
* @param agent - the agent deciding whether to run another step.
* @param turn - the turn being continued or stopped.
* @param defaultDecision - what the loop would do absent an override.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode waterfall
*/
'agent/turn-continuation'(this: Scoped<Agent>, agent: Agent, turn: number, defaultDecision: ContinuationDecision, next: () => Promise<ContinuationDecision>): Promise<ContinuationDecision>
```
@@ -203,6 +327,15 @@ Override whether the turn continues. The default continues after tool calls or s
**Mode:** `serial`
```ts website-api
/**
* Monotonic terminal-stop checkpoint after continuation and steering are
* folded; a stop remains authoritative through turn close and flush:
* steering queued in that window is discarded, while ordinary sends survive.
* @param agent - the agent whose composed continuation outcome may be stopped.
* @param turn - the turn at its terminal-stop checkpoint.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @mode serial
*/
'agent/turn-stop'(this: Scoped<Agent>, agent: Agent, turn: number): ContinuationStop | undefined
```
@@ -220,6 +353,15 @@ Monotonic terminal-stop checkpoint after continuation and steering are folded; a
**Mode:** `emit`
```ts website-api
/**
* A declarative agent entry failed before it could publish a live agent.
* Consumers that buffer work for the configured identity use this
* transient signal to reject that work instead of waiting forever. Normal
* factory teardown suppresses failures from the cancelled startup attempt.
* @param sessionId - exact shared agent/session identity that failed startup.
* @param error - persistence, setup, or publication failure.
* @mode emit
*/
'agent-loop/config-start-failed'(sessionId: SessionId, error: unknown): void
```
@@ -237,6 +379,13 @@ A declarative agent entry failed before it could publish a live agent. Consumers
**Mode:** `waterfall`
```ts website-api
/**
* Ask composed answerers for one decision. Return an outcome to claim the
* request or call `next()`; failure yields the fail-closed default.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
* @param req - the pending decision (agent, tool identity, reason, signal).
* @mode waterfall
*/
'approval/request'(this: Scoped<ApprovalService>, req: ApprovalRequest, next: () => Promise<ApprovalOutcome>): Promise<ApprovalOutcome>
```
@@ -253,6 +402,13 @@ Ask composed answerers for one decision. Return an outcome to claim the request
**Mode:** `waterfall`
```ts website-api
/**
* Single-slot decision for the next {@link FileSystem.editText}. Calling
* `next()` yields an unconditional edit; the first returned guard wins.
* @param target - the resolved target about to be edited.
* @param actor - the opaque tool-execution context the decider keys off.
* @mode waterfall
*/
'fs/edit-intent'(target: FsTarget, actor: object | undefined, next: () => { version: FsVersion } | undefined | Promise<{ version: FsVersion } | undefined>): Promise<{ version: FsVersion } | undefined>
```
@@ -268,6 +424,14 @@ Single-slot decision for the next FileSystem.editText. Calling `next()` yields a
**Mode:** `emit`
```ts website-api
/**
* Record a successful observation. Listeners must be synchronous recorders:
* throws fail the tool call and returned promises are not awaited.
* @param target - the target that was read/written/edited.
* @param version - the version the actor now holds as its observation.
* @param actor - the observing tool-execution context; undefined records nothing useful.
* @mode emit
*/
'fs/observed'(target: FsTarget, version: FsVersion, actor: object | undefined): void
```
@@ -284,6 +448,14 @@ Record a successful observation. Listeners must be synchronous recorders: throws
**Mode:** `waterfall`
```ts website-api
/**
* Single-slot decision for the next {@link FileSystem.writeText}. Calling
* `next()` yields the bare provider's unconditional write; the first listener
* that returns an intent owns the decision rather than composing with peers.
* @param target - the resolved target about to be written.
* @param actor - the opaque tool-execution context the decider keys off.
* @mode waterfall
*/
'fs/write-intent'(target: FsTarget, actor: object | undefined, next: () => FsWriteIntent | undefined | Promise<FsWriteIntent | undefined>): Promise<FsWriteIntent | undefined>
```
@@ -301,6 +473,17 @@ Single-slot decision for the next FileSystem.writeText. Calling `next()` yields
**Mode:** `waterfall`
```ts website-api
/**
* Waterfall around every streaming model call (retry, replay, routing).
* Bound to the {@link LlmService}; call `next()` to reach the resolved
* adapter's stream, or yield your own chunks to short-circuit.
* @param options - the full request. A LOOP-built request arrives
* deep-frozen (mutation throws): its content is a pure function of the
* session log (the reconstructability RFC), so listeners read it, never
* rewrite it. A hand-built one-shot (compaction summarize) is the
* caller's own object and stays mutable here.
* @mode waterfall
*/
'llm/stream'(this: LlmService, options: GenerateOptions, next: () => AsyncIterable<StreamChunk>): AsyncIterable<StreamChunk>
```
@@ -317,6 +500,17 @@ Waterfall around every streaming model call (retry, replay, routing). Bound to t
**Mode:** `emit`
```ts website-api
/**
* Creation announcement during session publication. A synchronous throw vetoes and rolls
* back with a paired disposal; detach requested during dispatch is deferred.
* A returned-promise rejection is logged but cannot retroactively veto this
* synchronous boundary.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners
* receive only sessions entered through that agent's context.
* @param session - the session just entered and announced.
* @dshScopeScan unsupported
* @mode emit
*/
'session/created'(this: Scoped<Session>, session: Session): void
```
@@ -331,6 +525,15 @@ Creation announcement during session publication. A synchronous throw vetoes and
**Mode:** `emit`
```ts website-api
/**
* Emitted once when an announced session leaves the store, including
* publication rollback, but never for an entry whose creation announcement
* did not begin. Listener failures are logged and contained.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`) reuses the owner scope.
* @param session - the session that is no longer live in the store.
* @dshScopeScan unsupported
* @mode emit
*/
'session/disposed'(this: Scoped<Session>, session: Session): void
```
@@ -345,6 +548,17 @@ Emitted once when an announced session leaves the store, including publication r
**Mode:** `emit`
```ts website-api
/**
* Post-commit, fire-and-forget append feed. The listener snapshot resolves
* before the log push, but callbacks run after it; observer failures are
* logged and contained without making the committed append fail.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners
* receive only events from sessions entered through that agent's context.
* @param session - the session whose log grew.
* @param event - the appended event, exactly as recorded.
* @dshScopeScan unsupported
* @mode emit
*/
'session/event'(this: Scoped<Session>, session: Session, event: SessionEvent): void
```
@@ -360,6 +574,15 @@ Post-commit, fire-and-forget append feed. The listener snapshot resolves before
**Mode:** `parallel`
```ts website-api
/**
* Awaited parallel durability checkpoint: every listener runs and the
* caller awaits all of them, with no waterfall veto. Dispatch through
* {@link SessionStore.flush}. Scope-filtered dispatch
* (`@deepseek-ai/dsh-scope`) reuses the session's owner scope.
* @param session - the session whose buffered events must reach durable storage.
* @dshScopeScan unsupported
* @mode parallel
*/
'session/flush'(this: Scoped<Session>, session: Session): Promise<void> | void
```
@@ -376,6 +599,14 @@ Awaited parallel durability checkpoint: every listener runs and the caller await
**Mode:** `emit`
```ts website-api
/**
* A ready child settled. Scope-filtered dispatch uses the same delegating
* parent carrier as `subagent/start`, so the lifecycle pair reaches the
* same scoped audience.
* @param info - the run identity and terminal outcome.
* @dshScopeScan unsupported
* @mode emit
*/
'subagent/end'(this: Scoped<SubagentService>, info: SubagentRunEndInfo): void
```
@@ -390,6 +621,11 @@ A ready child settled. Scope-filtered dispatch uses the same delegating parent c
**Mode:** `emit`
```ts website-api
/**
* A provider became resolvable in the registry.
* @param provider - the registered provider.
* @mode emit
*/
'subagent/provider-added'(provider: SubagentProvider): void
```
@@ -404,6 +640,11 @@ A provider became resolvable in the registry.
**Mode:** `emit`
```ts website-api
/**
* A provider left the registry. Accepted runs remain holder-owned.
* @param name - the provider name that no longer resolves.
* @mode emit
*/
'subagent/provider-removed'(name: string): void
```
@@ -418,6 +659,16 @@ A provider left the registry. Accepted runs remain holder-owned.
**Mode:** `emit`
```ts website-api
/**
* A provider established a ready child. For in-process providers,
* `ctx.agents.get(info.id)` resolves during this notification.
* Scope-filtered dispatch keys the carrier by the delegating parent, so a
* parent-scoped listener observes only its own delegations. Paired with
* `subagent/end`.
* @param info - the provider and ready child identity.
* @dshScopeScan unsupported
* @mode emit
*/
'subagent/start'(this: Scoped<SubagentService>, info: SubagentRunInfo): void
```
@@ -434,6 +685,14 @@ A provider established a ready child. For in-process providers, `ctx.agents.get(
**Mode:** `waterfall`
```ts website-api
/**
* Expert waterfall over the assembled sections, tools, and variables.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners
* receive only that scope's assemblies. The returned value is authoritative.
* @param assembly - the mutable assembly built from registered providers.
* @param context - the caller's per-assembly context.
* @mode waterfall
*/
'system-prompt/assemble'(this: Scoped<SystemPrompt>, assembly: PromptAssembly, context: AssembleContext, next: () => Promise<PromptAssembly>): Promise<PromptAssembly>
```
@@ -449,6 +708,11 @@ Expert waterfall over the assembled sections, tools, and variables. Scope-filter
**Mode:** `emit`
```ts website-api
/**
* Emitted when any prompt provider changes. This registry notification is
* unfiltered because a global change affects every scope.
* @mode emit
*/
'system-prompt/change'(): void
```
@@ -463,6 +727,15 @@ Emitted when any prompt provider changes. This registry notification is unfilter
**Mode:** `emit`
```ts website-api
/**
* A tool was registered or unregistered, or a scoped restriction changed
* (the available tool set changed — possibly for one scope only). An
* UNFILTERED registry-subject notification, deliberately not scope-filtered
* dispatch: a global change concerns every agent's next assembly, so a
* scoped listener subscribing here sees every change, not just its own
* scope's.
* @mode emit
*/
'tools/change'(): void
```
@@ -475,6 +748,14 @@ A tool was registered or unregistered, or a scoped restriction changed (the avai
**Mode:** `waterfall`
```ts website-api
/**
* Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns
* a normalized result; wrappers may change only `exec.signal`, while call
* identity remains immutable.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
* @param exec - the allowed call about to dispatch (name, parsed arguments, caller agent, signal).
* @mode waterfall
*/
'tools/execute'(this: Scoped<ToolRegistry>, exec: ToolExecution, next: () => Promise<ToolExecutionResult>): Promise<ToolExecutionResult>
```
@@ -489,6 +770,14 @@ Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns a nor
**Mode:** `waterfall`
```ts website-api
/**
* Accept, replace, enrich, or block a normalized dispatch result. `next()`
* accepts it unchanged; thrown tools still reach this seam as errors.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
* @param exec - the call that just ran (name, parsed arguments, caller agent).
* @param result - the dispatch outcome a listener may accept, replace, or block.
* @mode waterfall
*/
'tools/post-execute'(this: Scoped<ToolRegistry>, exec: ToolExecution, result: Readonly<ToolExecutionResult>, next: () => Promise<PostToolDecision>): Promise<PostToolDecision>
```
@@ -504,6 +793,13 @@ Accept, replace, enrich, or block a normalized dispatch result. `next()` accepts
**Mode:** `waterfall`
```ts website-api
/**
* Allow, deny, or ask before dispatch. `next()` delegates to allow; missing
* approval support turns `ask` into denial.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
* @param exec - the pending call (name, parsed arguments, caller agent).
* @mode waterfall
*/
'tools/pre-execute'(this: Scoped<ToolRegistry>, exec: ToolExecution, next: () => Promise<PreToolDecision>): Promise<PreToolDecision>
```
@@ -518,6 +814,13 @@ Allow, deny, or ask before dispatch. `next()` delegates to allow; missing approv
**Mode:** `emit`
```ts website-api
/**
* Observe the frozen, lossless-JSON final outcome. Listener failures are contained.
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.
* @param exec - the execution object that traversed the pipeline.
* @param result - a deep-frozen snapshot of the final returned result.
* @mode emit
*/
'tools/result'(this: Scoped<ToolRegistry>, exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): undefined
```
@@ -535,6 +838,16 @@ Observe the frozen, lossless-JSON final outcome. Listener failures are contained
**Mode:** `emit`
```ts website-api
/**
* One `agent()` call settled (clean result, child failure, or run
* cancellation). Paired with {@link Events['workflow/agent-start']} by
* `agent.seq`, exactly once per started call on every stop path — on an
* engine termination path (a worker killed past its grace) the end is
* engine-synthesized with outcome `'cancelled'`.
* @param info - the run's identity snapshot.
* @param agent - the call identity plus its outcome.
* @mode emit
*/
'workflow/agent-end'(info: WorkflowRunInfo, agent: WorkflowAgentEndInfo): void
```
@@ -550,6 +863,15 @@ One `agent()` call settled (clean result, child failure, or run cancellation). P
**Mode:** `emit`
```ts website-api
/**
* One `agent()` call established a ready child run. Paired with
* {@link Events['workflow/agent-end']} by `agent.seq`. A call that never
* receives a ready run from the provider emits neither
* event in this pair.
* @param info - the run's identity snapshot.
* @param agent - the call's sequence number, label, phase, and child id.
* @mode emit
*/
'workflow/agent-start'(info: WorkflowRunInfo, agent: WorkflowAgentInfo): void
```
@@ -565,6 +887,15 @@ One `agent()` call established a ready child run. Paired with Events['workflow/a
**Mode:** `emit`
```ts website-api
/**
* A workflow run settled (any stop reason). Fired when
* {@link WorkflowRun.result} resolves. Paired with
* {@link Events['workflow/start']}.
* @param info - the run's identity snapshot.
* @param result - the outcome data (stop reason, error, agent count) —
* deliberately WITHOUT the result value (see {@link WorkflowResultInfo}).
* @mode emit
*/
'workflow/end'(info: WorkflowRunInfo, result: WorkflowResultInfo): void
```
@@ -580,6 +911,12 @@ A workflow run settled (any stop reason). Fired when WorkflowRun.result resolves
**Mode:** `emit`
```ts website-api
/**
* The script emitted a narration line (a `log(message)` call).
* @param info - the run's identity snapshot.
* @param message - the logged message, verbatim.
* @mode emit
*/
'workflow/log'(info: WorkflowRunInfo, message: string): void
```
@@ -595,6 +932,13 @@ The script emitted a narration line (a `log(message)` call).
**Mode:** `emit`
```ts website-api
/**
* The script entered a phase (a `phase(title)` call) — progress grouping
* for observers; no execution semantics.
* @param info - the run's identity snapshot.
* @param title - the phase title, verbatim.
* @mode emit
*/
'workflow/phase'(info: WorkflowRunInfo, title: string): void
```
@@ -610,6 +954,12 @@ The script entered a phase (a `phase(title)` call) — progress grouping for obs
**Mode:** `emit`
```ts website-api
/**
* A workflow run started — the script's meta block validated, the body
* about to execute. Paired with {@link Events['workflow/end']}.
* @param info - the run's identity snapshot (id + meta).
* @mode emit
*/
'workflow/start'(info: WorkflowRunInfo): void
```

View File

@@ -11,6 +11,15 @@ Abstract filesystem provider. Targets must preserve identity across aliases; rea
### ctx.fs.resolve(path, opts?)
```ts website-api
/**
* Resolve a model/plugin-supplied path into a stable {@link FsTarget}. May perform I/O (a
* remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence
* async even though the local backend only normalizes + realpaths.
*
* @param path - the path to resolve; relative paths resolve against `opts.cwd`.
* @param opts - optional cwd override and cancellation signal.
* @returns the stable target; the same file yields the same `targetKey`.
*/
abstract resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): Promise<FsTarget>
```
@@ -26,6 +35,12 @@ Resolve a model/plugin-supplied path into a stable FsTarget. May perform I/O (a
### ctx.fs.stat(target, signal?)
```ts website-api
/**
* Return target metadata, or `undefined` when the target does not exist.
* @param target - the resolved target to stat.
* @param signal - aborts the metadata round-trip.
* @returns metadata only, never content; undefined for an absent target.
*/
abstract stat(target: FsTarget, signal?: AbortSignal): Promise<FsInfo | undefined>
```
@@ -41,6 +56,20 @@ Return target metadata, or `undefined` when the target does not exist.
### ctx.fs.lstat(path, opts?, signal?)
```ts website-api
/**
* Return path metadata without following the final path component when it is a
* symbolic link. This is intentionally path-shaped, not target-shaped:
* {@link resolve} follows symlinks to produce the stable identity used by
* normal reads/writes, while `lstat` lets a consumer reject the path itself
* before that follow happens.
*
* `opts.cwd` follows {@link resolve}'s cwd rules. `undefined` means the path is
* absent.
* @param path - the path to inspect; relative paths resolve against `opts.cwd`.
* @param opts - `cwd` overrides the backend's default base for relative paths.
* @param signal - aborts the metadata round-trip.
* @returns metadata only, never content; undefined for an absent path.
*/
abstract lstat(path: string, opts?: { cwd?: string }, signal?: AbortSignal): Promise<FsPathInfo | undefined>
```
@@ -58,6 +87,12 @@ Return path metadata without following the final path component when it is a sym
### ctx.fs.readText(target, signal?)
```ts website-api
/**
* Read the whole regular text file as a single decoded string.
* @param target - the resolved target to read.
* @param signal - aborts the read.
* @returns the full decoded UTF-8 content.
*/
abstract readText(target: FsTarget, signal?: AbortSignal): Promise<string>
```
@@ -73,6 +108,15 @@ Read the whole regular text file as a single decoded string.
### ctx.fs.streamText(target, signal?)
```ts website-api
/**
* Stream the whole regular text file as decoded text chunks (same text
* semantics as {@link readText}, for large files). The backend owns
* cross-chunk UTF-8 decoding and binary rejection so the policy layer never
* touches raw bytes.
* @param target - the resolved target to read.
* @param signal - aborts the stream, including between chunks.
* @returns the chunk iterable, decoded and validated like {@link readText}.
*/
abstract streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>
```
@@ -88,6 +132,13 @@ Stream the whole regular text file as decoded text chunks (same text semantics a
### ctx.fs.listDir(target, signal?)
```ts website-api
/**
* List direct children of a directory in stable name order. Returns resolved
* child targets plus cheap metadata only; never reads file contents.
* @param target - the resolved directory target.
* @param signal - aborts the listing.
* @returns one entry per direct child, in stable name order.
*/
abstract listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>
```
@@ -103,6 +154,15 @@ List direct children of a directory in stable name order. Returns resolved child
### ctx.fs.writeText(target, content, expected?, signal?)
```ts website-api
/**
* Atomically create or replace UTF-8 text. `expected` guards intent and
* staleness; omission allows unconditional overwrite.
* @param target - the resolved target to write.
* @param content - the full new file content.
* @param expected - the write intent guarding the write; omit for unconditional.
* @param signal - aborts before the atomic rename takes effect.
* @returns the outcome, including the version the write produced.
*/
abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>
```
@@ -120,6 +180,16 @@ Atomically create or replace UTF-8 text. `expected` guards intent and staleness;
### ctx.fs.editText(target, edit, expected?, signal?)
```ts website-api
/**
* Atomically edit literal text. When supplied, the version guard is checked
* before matching so stale content reports `FS_STALE_VERSION`; omission edits
* the current content without a freshness precondition.
* @param target - the resolved target to edit.
* @param edit - the literal search/replace request.
* @param expected - the version guard; omit for an unconditional edit.
* @param signal - aborts before the atomic rename takes effect.
* @returns the outcome, including the version the edit produced.
*/
abstract editText(target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal): Promise<FsEditOutcome>
```

View File

@@ -11,6 +11,14 @@ The abstract `llm` service: an adapter registry plus a streaming model-call surf
### ctx.llm.registerAdapter(providers, adapter)
```ts website-api
/**
* Register an adapter for the given provider routes. Throws `LlmError` with code
* `DUPLICATE_ADAPTER` if any provider already has an adapter (all-or-nothing).
* Disposed with the fiber.
* @param providers - every provider route this adapter should serve.
* @param adapter - the adapter that streams calls for those providers.
* @returns the disposer that unregisters all of them.
*/
registerAdapter(providers: string[], adapter: LlmAdapter): () => void
```
@@ -26,6 +34,10 @@ Register an adapter for the given provider routes. Throws `LlmError` with code `
### ctx.llm.listProviders()
```ts website-api
/**
* Describe provider routes with a registered adapter.
* @returns detached provider metadata in registration order.
*/
listProviders(): LlmProviderInfo[]
```
@@ -38,6 +50,12 @@ Describe provider routes with a registered adapter.
### ctx.llm.listModels(provider)
```ts website-api
/**
* Discover models advertised by one registered provider. Catalog membership
* is advisory and never changes routing or request validation.
* @param provider - registered provider route to inspect.
* @returns detached model metadata in adapter-preferred order.
*/
async listModels(provider: string): Promise<LlmModelInfo[]>
```
@@ -52,6 +70,15 @@ Discover models advertised by one registered provider. Catalog membership is adv
### ctx.llm.stream(options)
```ts website-api
/**
* Stream one model call as raw chunks (token-level deltas). Throws
* `LlmError` with code `NO_ADAPTER` if no adapter is registered for
* `options.provider`. Replay state is retained only when the same adapter
* instance owns its historical provider and the target provider. Dispatches
* through the `llm/stream` waterfall.
* @param options - the full request; `options.provider` selects the adapter.
* @returns the chunk stream, possibly wrapped by `llm/stream` listeners.
*/
stream(options: GenerateOptions): AsyncIterable<StreamChunk>
```

View File

@@ -11,6 +11,10 @@ Owns the deployment's permission presets and their write path. Requires a confin
### ctx.permission.names
```ts website-api
/**
* The advertised preset names, in the preset table's declaration order.
* @returns every switchable preset name.
*/
get names(): readonly string[]
```
@@ -21,6 +25,13 @@ The advertised preset names, in the preset table's declaration order.
### ctx.permission.current(events)
```ts website-api
/**
* Resolve the preset matching the effective knob values. A still-matching
* last selection wins shared-bundle ties; otherwise the first table match
* wins, or {@link CUSTOM_PRESET} when no entry matches.
* @param events - the session's events in log order.
* @returns the effective preset name, or `custom` when nothing matches.
*/
current(events: readonly SessionEvent[]): string
```
@@ -35,6 +46,12 @@ Resolve the preset matching the effective knob values. A still-matching last sel
### ctx.permission.resolve(name)
```ts website-api
/**
* Resolve a preset's knob bundle.
* @param name - the preset name to resolve.
* @returns the configured bundle.
* @throws when `name` is not in the table.
*/
resolve(name: string): PresetSpec
```
@@ -49,6 +66,13 @@ Resolve a preset's knob bundle.
### ctx.permission.optionOf(name)
```ts website-api
/**
* Build the client option for a table entry or {@link CUSTOM_PRESET}. A
* missing label falls back to the table key.
* @param name - a table key, or `custom`.
* @returns the option a client renders.
* @throws when `name` is neither a table key nor `custom`.
*/
optionOf(name: string): PresetOption
```
@@ -63,6 +87,12 @@ Build the client option for a table entry or CUSTOM_PRESET. A missing label fall
### ctx.permission.set(session, name)
```ts website-api
/**
* Record a changed preset, then update each changed knob through its own
* setter. Selecting the effective preset again appends nothing.
* @param session - the session the switch belongs to.
* @param name - the preset to switch to; unknown names throw.
*/
set(session: Session, name: string): void
```

View File

@@ -11,6 +11,17 @@ Abstract process-sandbox service. confine must return enforcing argv or fail clo
### ctx.sandbox.confine(argv, policy)
```ts website-api
/**
* Wrap `argv` so it executes confined under `policy` on this host; the
* caller spawns the returned argv in place of its own.
* @param argv - the exact argv the caller is about to spawn (program plus
* arguments), NOT a shell string — a shell-shaped consumer passes
* `['bash', '-c', command]`.
* @param policy - the file-effect policy this execution runs under,
* carried per call (see {@link SandboxPolicy}).
* @returns the argv to spawn instead, plus the enforcement completeness
* the selected backend achieves for it.
*/
abstract confine(argv: readonly string[], policy: SandboxPolicy): ConfinedArgv
```

View File

@@ -11,6 +11,13 @@ Durable append-only session storage. Implementations preserve contiguous, lossle
### ctx.sessionPersistence.locate(meta)
```ts website-api
/**
* Resolve this backend's independent local artifact for a session without
* reading, creating, flushing, or otherwise materializing it. Backends such
* as SQLite that do not own one artifact per session return `undefined`.
* @param meta - the immutable session header whose artifact is requested.
* @returns the backend-specific absolute location, when one exists.
*/
abstract locate(meta: SessionHeader): SessionLocation | undefined
```
@@ -25,6 +32,13 @@ Resolve this backend's independent local artifact for a session without reading,
### ctx.sessionPersistence.create(meta)
```ts website-api
/**
* Register a new session's metadata. A backend MAY defer the physical write
* until the first {@link append} (lazy materialization), in which case a
* created-but-never-appended session is absent from {@link list}
* — abandoned sessions leave nothing behind.
* @param meta - the immutable header (id, version, cwd, lineage) to record.
*/
abstract create(meta: SessionHeader): Promise<void>
```
@@ -37,6 +51,15 @@ Register a new session's metadata. A backend MAY defer the physical write until
### ctx.sessionPersistence.append(id, events)
```ts website-api
/**
* Durably persist a batch of events (called from the write-behind drain at
* the `session/flush` checkpoint). Honors the append-only and contiguous-seq
* contracts: the first event's `seq` MUST equal the stored next-seq (after
* `load` has durably closed any interrupted turn). Rejects non-JSON-
* serializable `event.data` with an error naming the offending event type.
* @param id - the session the batch belongs to.
* @param events - the contiguous batch to persist, in seq order.
*/
abstract append(id: SessionId, events: readonly SessionEvent[]): Promise<void>
```
@@ -50,6 +73,14 @@ Durably persist a batch of events (called from the write-behind drain at the `se
### ctx.sessionPersistence.load(id)
```ts website-api
/**
* Load a header and balanced contiguous log. A complete interrupted final
* turn is preserved and durably closed with missing tool errors plus any open
* step and turn boundaries; only a torn final record is discarded. Unknown
* versions and corruption in the committed prefix reject.
* @param id - the persisted session to reload.
* @returns the header and a log ending on a balanced `turn/end`.
*/
abstract load(id: SessionId): Promise<{ meta: SessionHeader; events: SessionEvent[] }>
```
@@ -64,6 +95,10 @@ Load a header and balanced contiguous log. A complete interrupted final turn is
### ctx.sessionPersistence.list()
```ts website-api
/**
* Lightweight listing from metadata, without a full-log parse.
* @returns one header per materialized session.
*/
abstract list(): Promise<SessionHeader[]>
```

View File

@@ -11,6 +11,10 @@ Live-preferred logical-corpus exact-read and relationship-tracing service.
### ctx.sessionQuery.listSessions()
```ts website-api
/**
* List the complete logical corpus using live-preferred records.
* @returns deterministic newest-first cloned session records.
*/
listSessions(): Promise<SessionRecord[]>
```
@@ -23,6 +27,11 @@ List the complete logical corpus using live-preferred records.
### ctx.sessionQuery.listEvents(sessionId)
```ts website-api
/**
* List lightweight raw-log event records for one logical session.
* @param sessionId - live-preferred session id to read.
* @returns event records in ascending seq order.
*/
async listEvents(sessionId: SessionId): Promise<SessionEventRecord[]>
```
@@ -37,6 +46,12 @@ List lightweight raw-log event records for one logical session.
### ctx.sessionQuery.traceSession(sessionId)
```ts website-api
/**
* Trace known ancestry and descendants from one corpus observation.
* @param sessionId - logical session id to trace.
* @returns a complete lineage or an explicit unresolved parent boundary.
* @throws when corpus resolution fails, the target is absent, or its known ancestry cycles.
*/
async traceSession(sessionId: SessionId): Promise<SessionLineageTrace>
```
@@ -51,6 +66,12 @@ Trace known ancestry and descendants from one corpus observation.
### ctx.sessionQuery.traceEvent(request)
```ts website-api
/**
* Trace one event's direct positional and provenance relationships.
* @param request - target session id and event seq.
* @returns direct links plus the target's positional replacement chain.
* @throws when source resolution fails, the target is absent, or surface/provenance validation fails.
*/
async traceEvent(request: SessionEventTraceRequest): Promise<SessionEventTrace>
```
@@ -65,6 +86,11 @@ Trace one event's direct positional and provenance relationships.
### ctx.sessionQuery.readEvent(request)
```ts website-api
/**
* Read one full event plus a bounded raw-log context window.
* @param request - target session/seq and context sizes.
* @returns cloned target and neighboring events.
*/
async readEvent(request: SessionEventReadRequest): Promise<SessionEventWindow>
```

View File

@@ -12,6 +12,27 @@ Persistence is intentionally not implemented here — persistence plugins subscr
### ctx.sessions.create(id?, options?)
```ts website-api
/**
* Create a session owned by the calling fiber: disposing that fiber stops
* event notification and removes the session from the store. `options.seed`
* populates the session with a copy of those events (replay/fork);
* `options.meta` attaches creation metadata (validated absolute `cwd`,
* `parentSession` lineage) as the immutable {@link SessionHeader} (the store
* fills `version`/`id`/`createdAt`).
*
* For an agent whose session must be torn down IN ORDER with its loop (so the
* loop's final flush is captured before the store attachment ends), do NOT use this
* — fold the session lifecycle into the agent's own effect via
* {@link prepare} + {@link enter} + {@link announce} (see
* `dsh-agent-loop`'s creation transaction).
*
* @param id - the session id; omitted, the store mints `session-<n>`.
* @param options - seed events and/or creation metadata for the header.
* @returns the live session, already entered and announced.
* @throws if a session with `id` already exists, metadata is not a plain
* lossless-JSON record with valid scalar fields, or `meta.cwd` is a
* non-absolute path (storage backends key directories off it).
*/
create(id?: SessionId, options?: CreateSessionOptions): Session
```
@@ -28,6 +49,22 @@ For an agent whose session must be torn down IN ORDER with its loop (so the loop
### ctx.sessions.prepare(id?, options?)
```ts website-api
/**
* Build a session WITHOUT entering it into the store — validate the id/cwd and
* construct the {@link Session} (with its immutable {@link SessionHeader}).
* Pairs with {@link enter} + {@link announce}: a caller that owns a composite
* `ctx.effect` (the agent factory) folds the session lifecycle into that ONE
* effect so a fiber unload tears the session + agent down as a single ORDERED
* chain rather than as racing sibling effects — which would remove the publication hooks
* before the loop's closing `session/flush`, dropping the closing events.
*
* @param id - the session id; omitted, the store mints `session-<n>`.
* @param options - seed events and/or creation metadata for the header.
* @returns the constructed session, NOT yet in the store.
* @throws if a session with `id` already exists, metadata is not a plain
* lossless-JSON record with valid scalar fields, or `meta.cwd` is a
* non-absolute path.
*/
prepare(id?: SessionId, options?: CreateSessionOptions): Session
```
@@ -43,6 +80,28 @@ Build a session WITHOUT entering it into the store — validate the id/cwd and c
### ctx.sessions.enter(session)
```ts website-api
/**
* Enter a {@link prepare}d session into the store: install the module-private
* append publication hooks and add it to the store. Returns the DETACH
* disposer (hooks + store removal). Does NOT emit `session/created` —
* the caller yields this disposer inside its effect and THEN calls
* {@link announce}, so a throwing `session/created` listener rolls the attach
* back instead of leaking it.
*
* Re-checks the id for a duplicate: `prepare` and `enter` are public
* cross-package primitives and a caller may interleave arbitrary work (or
* another create) between them, so a stale prepared session must NOT overwrite
* a live store entry of the same id — its detach disposer would later delete
* the REAL session. The {@link create} convenience and the agent factory call
* the two back-to-back so they never trip this, but the public seam cannot
* assume that.
*
* @param session - a {@link prepare}d session not yet in the store.
* @returns the detach disposer (publication hooks + store removal). When called from
* a synchronous `session/created` listener, removal and disposal wait until
* that creation dispatch unwinds.
* @throws if a session with this id is already in the store.
*/
enter(session: Session): () => void
```
@@ -58,6 +117,13 @@ Re-checks the id for a duplicate: `prepare` and `enter` are public cross-package
### ctx.sessions.announce(session)
```ts website-api
/** Emit `session/created` exactly once for an {@link enter}ed session (with
* the carrier {@link enter} captured). Separate from {@link enter} so the
* caller can yield the detach disposer first (rollback safety — see
* {@link enter}).
* @param session - the entered session to announce to listeners.
* @throws if the session is not live or its announcement already began,
* including a reentrant call from a creation listener. */
announce(session: Session): void
```
@@ -70,6 +136,17 @@ Emit `session/created` exactly once for an entered session (with the carrier ent
### ctx.sessions.flush(session)
```ts website-api
/**
* Dispatch the awaited `session/flush` durability checkpoint for `session`,
* with the carrier captured at {@link enter}. THE flush entry point: the
* store owns the carrier, so callers (the loop's turn-end checkpoint, idle
* injection, teardown drains) must come through here rather than dispatch a
* raw `ctx.parallel('session/flush', …)` — one owner, one spelling, and the
* scoped-dispatch invariant can pin it.
* @param session - the session whose buffered events must reach durable storage.
* @returns resolves when every flush listener has settled; after all settle,
* rejects with the first registered listener failure if any listener failed.
*/
async flush(session: Session): Promise<void>
```
@@ -84,6 +161,11 @@ Dispatch the awaited `session/flush` durability checkpoint for `session`, with t
### ctx.sessions.get(id)
```ts website-api
/**
* Look up a live session.
* @param id - the session id to look up.
* @returns the session, or undefined when no live session has that id.
*/
get(id: SessionId): Session | undefined
```
@@ -98,6 +180,10 @@ Look up a live session.
### ctx.sessions.list()
```ts website-api
/**
* All live sessions, in creation order.
* @returns a fresh array; mutating it does not affect the store.
*/
list(): Session[]
```
@@ -110,6 +196,19 @@ All live sessions, in creation order.
### ctx.sessions.fork(source, boundary?, childSessionId?)
```ts website-api
/**
* Create a live child session from a turn-enclosed prefix of a live source.
* `boundary` is an inclusive source event seq; omitted means the source's
* current last event. A non-empty selected slice must end at `turn/end`.
*
* @param source - Live source session object or id.
* @param boundary - Inclusive source event seq to fork through; omitted means
* the source's current last event, and omitted on an empty source forks an
* empty child.
* @param childSessionId - Optional child session id; omitted delegates to
* `SessionStore`'s id policy.
* @returns The created live child session.
*/
fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId): Session
```

View File

@@ -11,6 +11,14 @@ Registry of skill providers. It merges provider catalogs with stable first-wins
### ctx.skills.registerProvider(provider)
```ts website-api
/**
* Register a borrowed same-process provider synchronously during plugin apply. Duplicate and
* reserved names throw; remote initialization belongs in `list()`. Fiber disposal unregisters
* the provider and invalidates catalog caches.
* @param provider - the provider to register by `provider.name`.
* @returns the exact Cordis effect disposer that unregisters this provider;
* composite effects may yield it directly to preserve teardown ordering.
*/
registerProvider(provider: SkillProvider): () => void
```
@@ -25,6 +33,13 @@ Register a borrowed same-process provider synchronously during plugin apply. Dup
### ctx.skills.register(skill)
```ts website-api
/**
* Register a borrowed readonly runtime skill. Project entries outrank runtime entries, which
* outrank user entries. Same-name runtime entries are first-wins; a duplicate logs a warning and
* receives a no-op disposer so it cannot remove the winner.
* @param skill - the complete skill definition to expose for discovery.
* @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.
*/
register(skill: SkillRegistration): () => void
```
@@ -39,6 +54,13 @@ Register a borrowed readonly runtime skill. Project entries outrank runtime entr
### ctx.skills.list(options?)
```ts website-api
/**
* List model-invocable skill summaries for a workspace. Lookup options and
* provider candidates are readonly same-process values borrowed throughout
* discovery.
* @param options - lookup options; `cwd` selects project roots and `signal` cancels discovery.
* @returns sorted summaries, excluding skills disabled for model invocation.
*/
async list(options: SkillLookupOptions = {}): Promise<SkillSummary[]>
```
@@ -53,6 +75,14 @@ List model-invocable skill summaries for a workspace. Lookup options and provide
### ctx.skills.get(name, options?)
```ts website-api
/**
* Load and validate the winning candidate, passing its opaque discovery locator back to the
* provider. Cancellation is rechecked after selection, including cache hits, and raced against
* loading so an uncooperative provider cannot hang the caller.
* @param name - kebab-case skill name.
* @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
* @returns the full skill, including body content, or `undefined`.
*/
async get(name: string, options: SkillLookupOptions = {}): Promise<SkillDefinition | undefined>
```

View File

@@ -15,6 +15,11 @@ Semantics every implementation must honor:
### ctx.spillStore.saveText(input)
```ts website-api
/**
* Persist `input.content` to a session-scoped spill artifact.
* @param input - the owner, provenance, suggested name, and full text to save.
* @returns the saved artifact's {@link SpillRef}; rejects on a storage failure.
*/
abstract saveText(input: SaveTextSpill): Promise<SpillRef>
```

View File

@@ -11,6 +11,13 @@ Named provider registry and capability-checked start surface.
### ctx.subagents.registerProvider(provider)
```ts website-api
/**
* Register a provider under its name. Registration is effect-scoped and HMR
* safe; removing a provider blocks new starts but does not revoke runs that
* were already returned to their holders.
* @param provider - the trusted provider implementation.
* @returns the exact Cordis effect disposer.
*/
registerProvider(provider: SubagentProvider): () => void
```
@@ -25,6 +32,11 @@ Register a provider under its name. Registration is effect-scoped and HMR safe;
### ctx.subagents.getProvider(name)
```ts website-api
/**
* Look up a provider by name.
* @param name - the provider name.
* @returns the provider, or undefined when absent.
*/
getProvider(name: string): SubagentProvider | undefined
```
@@ -39,6 +51,10 @@ Look up a provider by name.
### ctx.subagents.list()
```ts website-api
/**
* List registered provider names in insertion order.
* @returns the registered names.
*/
list(): string[]
```
@@ -51,6 +67,15 @@ List registered provider names in insertion order.
### ctx.subagents.start(name, request)
```ts website-api
/**
* Establish a ready child on the named provider. Capability and semantic
* checks run before delegation. Provider ownership lasts until its promise
* fulfills; a rejection therefore has no run for the caller to dispose and
* emits no run lifecycle events.
* @param name - the provider to use.
* @param request - child prompt, parent, signal, and optional capabilities.
* @returns the ready holder-owned run.
*/
async start(name: string, request: SubagentStartRequest): Promise<SubagentRun>
```

View File

@@ -11,6 +11,14 @@ Registry service for the prompt inputs assembled before each model step.
### ctx.systemPrompt.section(section)
```ts website-api
/**
* Register an ordered prompt section in the calling context's scope. A scoped
* section shadows a global section with the same name; duplicates within one
* layer and non-finite orders throw. Registration and disposal emit
* `system-prompt/change`.
* @param section - the section to register.
* @returns the exact Cordis effect disposer.
*/
section(section: PromptSection): () => void
```
@@ -25,6 +33,13 @@ Register an ordered prompt section in the calling context's scope. A scoped sect
### ctx.systemPrompt.tools(provider)
```ts website-api
/**
* Register a tool-schema provider in the calling context's scope. Global and
* matching scoped providers both contribute; returning the reserved
* {@link TOOL_ORDER_REST} name makes assembly fail.
* @param provider - evaluated for each assembly with its context.
* @returns the exact Cordis effect disposer.
*/
tools(provider: (context: AssembleContext) => ToolProviderResult): () => void
```
@@ -39,6 +54,14 @@ Register a tool-schema provider in the calling context's scope. Global and match
### ctx.systemPrompt.variable(name, provider)
```ts website-api
/**
* Register a prompt variable in the calling context's scope. Scoped values
* shadow globals; invalid or duplicate names throw. A provider may return
* `undefined`, but rendering a section that references that value then fails.
* @param name - the `[a-z][a-z0-9_]*` reference name.
* @param provider - evaluated for each assembly.
* @returns the exact Cordis effect disposer.
*/
variable(name: string, provider: (context: AssembleContext) => string | undefined): () => void
```
@@ -54,6 +77,13 @@ Register a prompt variable in the calling context's scope. Scoped values shadow
### ctx.systemPrompt.assemble(context?)
```ts website-api
/**
* Assemble global and scoped providers, detach tool parameters, apply
* canonical ordering, then run the assembly waterfall. Scoped sections and
* variables shadow globals; the returned waterfall value is authoritative.
* @param context - the optional scope and plugin-defined assembly fields.
* @returns the authoritative post-waterfall assembly.
*/
async assemble(context: AssembleContext = {}): Promise<PromptAssembly>
```

View File

@@ -11,6 +11,14 @@ The `tasks` service: the runtime-global background task registry. See the module
### ctx.tasks.start(spec)
```ts website-api
/**
* Preflight access, validation, and owner cleanup before starting and
* atomically registering work. A throwing starter leaves nothing registered;
* after it returns, registration cannot fail. Settlement records the outcome,
* notifies listeners, and releases waiters.
* @param spec - task identity, owner, and synchronous starter.
* @returns the registry-issued `<kind>-N` id.
*/
start(spec: TaskStart): TaskId
```
@@ -25,6 +33,12 @@ Preflight access, validation, and owner cleanup before starting and atomically r
### ctx.tasks.list(caller?)
```ts website-api
/**
* List caller-owned and unowned tasks in registration order without exposing
* another session's labels.
* @param caller - reading agent; a non-agent caller sees only unowned tasks.
* @returns fresh snapshots.
*/
list(caller?: Agent): TaskSnapshot[]
```
@@ -39,6 +53,13 @@ List caller-owned and unowned tasks in registration order without exposing anoth
### ctx.tasks.get(id, caller?)
```ts website-api
/**
* Return a non-consuming snapshot without changing its read cursor or notice
* state. Throws for an unknown or foreign task.
* @param id - task to look up.
* @param caller - reading agent checked against the owner.
* @returns a fresh snapshot.
*/
get(id: TaskId, caller?: Agent): TaskSnapshot
```
@@ -54,6 +75,14 @@ Return a non-consuming snapshot without changing its read cursor or notice state
### ctx.tasks.read(id, caller?)
```ts website-api
/**
* Read the next stream delta, or the idempotent final output after settlement.
* A terminal read marks the task reported. Throws for an unknown or foreign
* task.
* @param id - task to read.
* @param caller - reading agent checked against the owner.
* @returns output text and the post-read snapshot.
*/
read(id: TaskId, caller?: Agent): TaskRead
```
@@ -69,6 +98,15 @@ Read the next stream delta, or the idempotent final output after settlement. A t
### ctx.tasks.kill(id, caller?, reason?)
```ts website-api
/**
* Request cancellation, then mark the task stopping and reported. A producer
* throw propagates without changing task state. Throws for an unknown or
* foreign task.
* @param id - task to cancel.
* @param caller - killing agent checked against the owner.
* @param reason - logged reason forwarded to the producer.
* @returns `requested` for live work, otherwise `already-finished`.
*/
kill(id: TaskId, caller?: Agent, reason?: string): 'requested' | 'already-finished'
```
@@ -85,6 +123,18 @@ Request cancellation, then mark the task stopping and reported. A producer throw
### ctx.tasks.wait(id, timeoutMs, caller?, signal?)
```ts website-api
/**
* Wait for settlement or timeout without cancelling the task. Caller abort
* rejects only while the task is live; after settlement it returns the
* terminal snapshot so a notice suppressed for this waiter is still delivered.
* Timed-out and aborted waits detach their resolvers. Throws for invalid,
* unknown, or foreign input.
* @param id - task to wait for.
* @param timeoutMs - positive finite wait bound in milliseconds.
* @param caller - waiting agent checked against the owner.
* @param signal - optional cancellation of the wait itself.
* @returns snapshot at settlement or timeout.
*/
async wait(id: TaskId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise<TaskSnapshot>
```
@@ -102,6 +152,13 @@ Wait for settlement or timeout without cancelling the task. Caller abort rejects
### ctx.tasks.onTaskDone(listener)
```ts website-api
/**
* Register an effect-scoped completion listener. Each listener is contained;
* returned promises are observed but not awaited. No listener runs after
* service disposal.
* @param listener - receives each terminal snapshot and its exact owner.
* @returns disposer that unregisters the listener.
*/
onTaskDone(listener: TaskDoneListener): () => void
```
@@ -116,6 +173,12 @@ Register an effect-scoped completion listener. Each listener is contained; retur
### ctx.tasks.attachSurface(name)
```ts website-api
/**
* Attach an effect-scoped surface that can read and stop tasks. {@link start}
* refuses work while none is attached.
* @param name - diagnostic label; duplicate names remain independent.
* @returns disposer that detaches this surface.
*/
attachSurface(name: string): () => void
```

View File

@@ -11,6 +11,7 @@ Replay owner for one service-wide estimator and isolated per-session folds.
### ctx.tokenMeter.contextWindow
```ts website-api
/** Provider context-window capacity used by pressure consumers. */
readonly contextWindow: number
```
@@ -21,6 +22,22 @@ Provider context-window capacity used by pressure consumers.
### ctx.tokenMeter.measure(session, requestHeader?)
```ts website-api
/**
* Measure current request pressure and surface through the durable tail.
*
* Provider usage is reused only when the latest successful call's canonical
* request envelope matches `requestHeader` and its total is no lower than
* that call's full heuristic anchor; otherwise the complete envelope and
* surface are heuristically repriced.
*
* `requestHeader` affects request pressure only; surface fields always
* describe the current session surface. Every call clones those positional
* nodes, so measurement is O(surface).
*
* @param session - session to replay through its current durable tail.
* @param requestHeader - optional effective request envelope replacing the latest logged header.
* @returns a detached deeply immutable pressure and surface measurement.
*/
measure(session: Session, requestHeader?: EpochHeader): TokenMeasurement
```
@@ -38,6 +55,11 @@ Provider usage is reused only when the latest successful call's canonical reques
### ctx.tokenMeter.estimateMessage(message)
```ts website-api
/**
* Heuristically price one model-visible message.
* @param message - message to price without mutation.
* @returns content and role-framing tokens under the fixed service heuristic.
*/
estimateMessage(message: Message): number
```

View File

@@ -11,6 +11,12 @@ Tool registry and execution pipeline. Scoped registrations shadow globals; one v
### ctx.tools.register(definition)
```ts website-api
/**
* Register globally or in the calling agent scope. Scoped tools shadow
* globals; duplicates within one layer and the reserved `run_code` name fail.
* @param definition - the tool schema, execution, and optional presentation functions.
* @returns the exact disposer that unregisters the tool.
*/
register(definition: ToolDefinition): () => void
```
@@ -25,6 +31,13 @@ Register globally or in the calling agent scope. Scoped tools shadow globals; du
### ctx.tools.restrict(filter)
```ts website-api
/**
* Restrict global tools for the calling agent scope. Empty filters, unknown
* names, scope-local names, and reserved transport names fail. Restrictions
* intersect; scoped registrations remain visible.
* @param filter - global-surface mask: `allow` (keep only) and/or `deny` (remove).
* @returns the exact disposer that lifts this restriction.
*/
restrict(filter: ToolRestriction): () => void
```
@@ -39,6 +52,16 @@ Restrict global tools for the calling agent scope. Empty filters, unknown names,
### ctx.tools.guard(guard)
```ts website-api
/**
* Register a monotonic guard after the extensible `tools/pre-execute`
* waterfall. A plain-context guard applies globally; one registered through
* `agent.ctx` applies only to that agent. Any matching guard may deny by
* returning a reason, while no guard can force-allow a call another guard
* denied. The exact effect disposer is returned for ordered ownership and
* HMR cleanup.
* @param guard - synchronous check; a returned string denies the execution.
* @returns the exact disposer that unregisters the guard.
*/
guard(guard: ToolGuard): () => void
```
@@ -53,6 +76,15 @@ Register a monotonic guard after the extensible `tools/pre-execute` waterfall. A
### ctx.tools.get(name, scope?)
```ts website-api
/**
* Look up a tool as one scope sees it (scoped
* shadows global; a restricted-away global reads as absent). Presenters pass
* the calling agent so the rendered card matches the definition that
* actually executed.
* @param name - the tool name as registered.
* @param scope - the viewing scope (the agent); omitted = the global view.
* @returns the definition the scope resolves, or undefined when none is visible.
*/
get(name: string, scope?: ScopeKey): ToolDefinition | undefined
```
@@ -68,6 +100,12 @@ Look up a tool as one scope sees it (scoped shadows global; a restricted-away gl
### ctx.tools.schemas(scope?)
```ts website-api
/**
* Project visible definitions onto the allowlisted model-facing schema fields,
* excluding execution and presentation callbacks.
* @param scope - the viewing scope (the agent); omitted = the global view.
* @returns one deep-cloned schema per visible tool.
*/
schemas(scope?: ScopeKey): ToolSchema[]
```
@@ -82,6 +120,13 @@ Project visible definitions onto the allowlisted model-facing schema fields, exc
### ctx.tools.executionMode(exec)
```ts website-api
/**
* Classify a pending call through the caller's visible tool definition. Only
* an exact `true` is parallel; unknown, hidden, undeclared, invalid, or
* throwing classifiers are exclusive.
* @param exec - call name, parsed arguments, and optional agent scope.
* @returns the fail-closed scheduling mode.
*/
executionMode(exec: ToolExecutionInput): ToolExecutionMode
```
@@ -96,6 +141,15 @@ Classify a pending call through the caller's visible tool definition. Only an ex
### ctx.tools.execute(exec)
```ts website-api
/**
* Execute through pre-policy, guards, around-dispatch, post-policy, and final
* notification. Tool and listener failures resolve as materialized error
* results; an invisible tool reports `UNKNOWN_TOOL`. The returned outcome is
* the same lossless, frozen snapshot final observers receive.
* @param exec - the typed same-process call input. The registry assigns its
* correlation token before policy begins.
* @returns the materialized final result.
*/
async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
```

View File

@@ -11,6 +11,12 @@
### ctx.userInteraction.registerProvider(provider)
```ts website-api
/**
* Register the UI provider. Only one provider may be active in a context.
*
* @param provider UI-side implementation that collects answers.
* @returns Disposer that unregisters this provider.
*/
registerProvider(provider: UserInteractionProvider): () => void
```
@@ -25,6 +31,12 @@ Register the UI provider. Only one provider may be active in a context.
### ctx.userInteraction.ask(request)
```ts website-api
/**
* Ask the active UI provider and wait for the user's answer.
*
* @param request Questions, owner agent, and abort signal.
* @returns The answer chosen or typed by the human.
*/
async ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>
```

View File

@@ -18,6 +18,13 @@ Selection semantics (resolved at execution time, never order-dependent):
### ctx.web.registerSearchProvider(provider)
```ts website-api
/**
* Register a search provider. Throws {@link WebError} `WEB_DUPLICATE_PROVIDER`
* if its id is already registered for search. Returns a disposer; disposed
* with the calling fiber.
* @param provider - the provider; its `id` is the registry key.
* @returns the disposer that unregisters the provider.
*/
registerSearchProvider(provider: WebSearchProvider): () => void
```
@@ -32,6 +39,13 @@ Register a search provider. Throws WebError `WEB_DUPLICATE_PROVIDER` if its id i
### ctx.web.registerFetchProvider(provider)
```ts website-api
/**
* Register a fetch provider. Throws {@link WebError} `WEB_DUPLICATE_PROVIDER`
* if its id is already registered for fetch. Returns a disposer; disposed
* with the calling fiber.
* @param provider - the provider; its `id` is the registry key.
* @returns the disposer that unregisters the provider.
*/
registerFetchProvider(provider: WebFetchProvider): () => void
```
@@ -46,6 +60,15 @@ Register a fetch provider. Throws WebError `WEB_DUPLICATE_PROVIDER` if its id is
### ctx.web.search(request, signal?)
```ts website-api
/**
* Run one search through the selected provider. Resolves the provider at call
* time with the selection rules above; throws {@link WebError} when the
* capability cannot run. The seam enforces `request.maxResults` on the result:
* if the provider over-returns, `sources[]` is truncated and `truncated` set.
* @param request - the query plus result-shaping options.
* @param signal - optional cancellation signal forwarded to the provider.
* @returns the provider's results, capped to `request.maxResults`.
*/
async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>
```
@@ -61,6 +84,14 @@ Run one search through the selected provider. Resolves the provider at call time
### ctx.web.fetch(request, signal?)
```ts website-api
/**
* Retrieve one URL through the selected provider. Resolves the provider at
* call time with the selection rules above; throws {@link WebError} when the
* capability cannot run. A non-2xx response is a result, not a throw.
* @param request - the URL plus retrieval options.
* @param signal - optional cancellation signal forwarded to the provider.
* @returns the retrieval outcome; non-2xx responses resolve descriptively.
*/
async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult>
```

View File

@@ -11,6 +11,12 @@ Workflow execution seam. Invalid requests throw before publication; a live run i
### ctx.workflows.start(request)
```ts website-api
/**
* Parse and execute a workflow script.
* @param request - the script, its `args`, the parent agent, and an
* optional cancel signal.
* @returns the live run; its `result` resolves when the script settles.
*/
abstract start(request: WorkflowStartRequest): WorkflowRun
```

View File

@@ -1,6 +1,6 @@
# API 参考
本节是 DeepSeek Harness 的 API 参考。除本页外,`cordis/` 与 `harness/` 下的所有页面**由脚本从源码生成**(`pnpm run gen-website-api`,CI 校验新鲜度),签名与说明永远与代码一致;生成页目前为英文,中文版将随统一翻译流程提供。
本节是 DeepSeek Harness 的 API 参考。除本页外,`cordis/` 与 `harness/` 下的所有页面**由脚本从源码生成**(`pnpm run gen-website-api`,CI 校验新鲜度);签名代码块保留源码的原始 JSDoc,签名与说明永远与代码一致。生成页目前为英文,中文版将随统一翻译流程提供。
## 框架 API