7.0 KiB
ctx.agents
AgentRegistry — provided by @deepseek-ai/dsh-agent.
Agent registry (ctx.agents): tracks live agents so UI, hook, and orchestrator plugins can find them without depending on the concrete loop package. Agent creation is provided by whichever plugin implements the AgentFactory (@deepseek-ai/dsh-agent-loop), registered via setFactory.
ctx.agents.setFactory(factory)
setFactory(factory: AgentFactory): () => void
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.
factory— the loop-owned factorycreate/resumedelegate 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.
ctx.agents.create(options)
async create(options: CreateAgentOptions): Promise<AgentHandle>
Create and publish a new agent through the registered factory. Distinct from 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 AgentHandle lets the owner tear down exactly this agent.
options— shared identity, session seed/metadata, and agent options.
Returns the handle after setup, rollback-covered publication, and loop start complete.
ctx.agents.resume(options)
async resume(options: ResumeAgentOptions): Promise<AgentHandle>
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.
options— persisted identity, configuration, and optional setup.
Returns the handle after setup, rollback-covered publication, and loop start complete.
ctx.agents.register(agent)
register(agent: Agent): () => void
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.
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.
ctx.agents.enter(agent, owner)
enter(agent: Agent, owner: Agent | undefined): () => void
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 announce. Ordinary callers use register.
agent— the prepared, unpublished agent.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.
ctx.agents.announce(agent)
announce(agent: Agent): void
Announce an agent previously inserted with enter.
agent— the live inserted agent to announce.
ctx.agents.get(id)
get(id: SessionId): Agent | undefined
Look up a live agent.
id— the shared agent/session id to look up.
Returns the agent, or undefined when no live agent has that id.
ctx.agents.isOwnedBy(id, owner)
isOwnedBy(id: SessionId, owner: Agent): boolean
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.
id— the candidate child agent's shared agent/session id.owner— the expected runtime creator agent.
Returns true only while the exact child entry is live under that owner.
ctx.agents.list()
list(): Agent[]
All live agents, in registration order.
Returns a fresh array; mutating it does not affect the registry.
ctx.agents.roots()
roots(): Agent[]
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.