/** * DshAgentRegistrar — IAgentRegistrar adapter for the dsh (DeepSeek Harness) * subagent catalog. * * Translates rolebox `AgentDefinition` entries into `SubagentProvider` * registrations on the dsh `ctx.subagents` seam * (`SubagentRuntime.registerProvider`), using the API surface verified in * `docs/dsh-plugin-contract.md` (§4.2, §4.3). * * Mapping (AgentDefinition → SubagentProvider): * - `id` → provider `name` (the unique registry key, see `list()`) * - `systemPrompt` → prepended to the spawn request's `prompt` as a text * ContentBlock (`{type:'text', text}` per §3.4) * - `model` → split via the shared `splitModel` helper into the spawn * request's `agentOptions.provider` + `agentOptions.model`: * a resolved `"/"` sets BOTH fields * (provider = segment before the first slash; model = the * rest, so multi-segment ids survive), while a * bare/`"default"`/malformed model overrides `model` only * and leaves the base provider untouched. * (dsh-agent `AgentOptions` = `{provider?, model?, maxTokens?}`, §4.2) * * ── Provider-route safety path ────────────────────────────────────────────── * Emitting a split `provider` that dsh has NO registered llm adapter for would * turn a working spawn into a hard dispatch failure (`NO_ADAPTER`, * `dsh-llm/lib/index.js:965-966`; see `docs/dsh-provider-notes.md` §2/§4). * When a {@link DshProviderRouteProbe} is wired, `mergeAgentOptions` checks the * split provider against the routes `ctx.llm.listProviders()` reports and, on a * miss, logs ONE explicit warning and degrades to a model-only override — * leaving the base provider untouched so the spawn inherits the runtime * default route instead of failing. Absent a probe (no `ctx.llm` service), the * split is emitted unchanged (the pre-safety behavior). * - `tools` / `maxSteps` → CATALOG configuration only; deliberately NOT * mapped to dsh start-time capabilities. rc.6 requires all * four `SubagentCapabilities` booleans and this provider * advertises none — see `buildCapabilities`. * * ── Per-session active-role application ───────────────────────────────────── * When the registrar is constructed with an `activeRole` lookup (the * {@link DshRoleSwitcher}'s shared per-session holder), a provider's * `start()` consults it with the spawn request's `sessionId` (threaded by * {@link DshDispatchAdapter} from the parent/origin session) and, when a * role is active for that session, PREPENDS the active role's systemPrompt * to the spawned prompt and applies its model override — the seam that makes * a web-UI role switch actually reach the spawned agent. No active role (or * no sessionId on the request) falls back to the definition's own behavior; * spawning the active role's own definition skips the redundant prepend. * * ── Spawn-time context injection (the system-transform counterpart) ──────── * rolebox's `system-transform` hook (`src/hooks/system-transform.ts`) — which * injects the role's dynamic context blocks (available functions, memory, * graph state) into the agent prompt — remains a no-op at the HOOK level in * {@link DshHookProvider} (hook-provider.ts:15,21-24,178); session-level * injection now flows through {@link DshSystemPromptAdapter} (system-prompt.ts * — `rolebox:role` + `rolebox:context`, per-session via `context.agent.id`). * To keep dsh's context injection flowing into a spawned agent, the registrar * exposes a {@link DshSpawnContextProvider} seam: when an active role exists * for the spawn's session, `start()` prepends the provider's context blocks * AHEAD of the active role's complete materialized prompt, so the spawned * agent's prompt carries BOTH the injected context AND the role prompt. * Absent a provider (or active role) the spawn is unchanged — base behavior. * * This module does NOT import from any host SDK package — neither the opencode * plugin/SDK nor any dsh package. The dsh surface is consumed structurally * (duck typing) against the shapes verified in the contract, which keeps the * adapter SDK-free and unit-testable against a fake registry double. * * Platform-artifact cleanup: `registerProvider` returns a disposer that * removes the provider from the dsh registry. `unregister()` (and replacement * of a changed definition during `register()`/`sync()`) invokes that disposer * — that is the platform artifact this adapter cleans up. * * The live-agent side of dsh (`ctx.agents` AgentRegistry * `create`/`resume`/`register`, and `AgentFactory`) is out of scope here: * this registrar manages the *catalog* of spawnable definitions. Actual * spawning is delegated in order: to an optional `onSpawn` hook when wired, * otherwise to an already-registered host provider named by * {@link DshAgentRegistrarOptions.spawnProviderName} (default `"spawn"`). * When neither resolves, a provider's `start()` throws * `DshSpawnNotWiredError` while registration/sync still work fully. * * @module */ import type { Logger, ILogObj } from "tslog"; import type { IAgentRegistrar } from "../../ports/agent-registrar.ts"; import type { AgentDefinition } from "../../types.ts"; /** @internal Test seam — swap the module-level logger for a mock. */ export declare function __setLoggerForTest(mockLogger: Logger): void; /** * Structural mirror of the dsh-llm `ContentBlock` union (§3.4; * `dsh-llm/lib/types/types.d.ts:39-89`): text, reasoning, image, tool-call, * and tool-result. ONE loose structural declaration shared by the subagent * registrar (prompt/output), the session adapter (message content), and the * tool factory (render output) — the real `ContentBlockMap` is * merge-extensible, so unknown members and extra fields are preserved by the * index signature and rolebox reads only the members it maps. */ export interface DshContentBlock { readonly type: string; /** `text` / `reasoning` payload. */ readonly text?: string; /** Block id (`tool-call`). */ readonly id?: string; /** Tool name (`tool-call`). */ readonly name?: string; /** * Raw JSON string as produced by the model for a `tool-call` * (`dsh-llm/lib/types/types.d.ts:59-66`); parsed by the session adapter. * Absent for non-tool-call blocks. */ readonly arguments?: string; /** Correlates a `tool-result` with its `tool-call`. */ readonly toolCallId?: string; /** Nested blocks (`tool-result` content). */ readonly content?: unknown; /** Whether a `tool-result` is an error. */ readonly isError?: boolean; readonly [key: string]: unknown; } /** * dsh ToolRestriction — allow/deny mask used by subagent `toolFilter` (§4.3). */ export type DshToolRestriction = { allow?: string[]; deny?: string[]; }; /** * dsh AgentOptions — model/provider vocabulary from dsh-agent (§4.2). */ export type DshAgentOptions = { provider?: string; model?: string; maxTokens?: number; }; /** * dsh SubagentCapabilities — the provider's start-time feature flags * (`packages/subagent/subagent/src/types.ts:130-136`, dsh 0.1.5-rc.1). * dsh declares FIVE REQUIRED booleans — `agentOptions`, `outputSchema`, * `depthLimit`, `toolFilter`, `persona` — each corresponding one-to-one to a * `SubagentStartRequest` option that the service's `assertCapabilities` * truthy-checks before delegating to `start()` * (`packages/subagent/subagent/src/index.ts:641-657`). A start carrying an * option whose capability is falsy is rejected with `UNSUPPORTED_CAPABILITY`. * rolebox's provider honors only `agentOptions` (its `start()` forwards * `request.agentOptions` into the delegated start request), so it advertises * `agentOptions: true` and the remaining four as `false`. */ export type DshSubagentCapabilities = { agentOptions: boolean; outputSchema: boolean; depthLimit: boolean; toolFilter: boolean; persona: boolean; }; /** * dsh SubagentStartRequest — the resolved request a provider's `start()` * receives (§4.3). Structural subset; rolebox touches `prompt`/`agentOptions` * and forwards the rest untouched. */ export type DshSubagentStartRequest = { label?: string; prompt: DshContentBlock[]; parent: unknown; signal: AbortSignal; agentOptions?: DshAgentOptions; maxDepth?: number; toolFilter?: DshToolRestriction; persona?: unknown; /** * The detached durable child descriptor the dsh service resolves and stamps * onto the provider-facing request before dispatching to `start()` * (`ResolvedSubagentStartRequest = SubagentStartRequest & { descriptor }`, * `dsh-subagent/lib/types/types.d.ts:145-148`). OPTIONAL on this base type: * it is absent from the start requests rolebox composes itself * ({@link DshDispatchAdapter} — dsh, not rolebox, resolves the descriptor), * and present on the resolved request a provider's `start()` receives * ({@link DshResolvedSubagentStartRequest}). Typed `unknown` because rolebox * never reads it. */ descriptor?: unknown; /** * rolebox extension (NOT part of the dsh vocabulary): the session id whose * active role applies to this spawn. Threaded by {@link DshDispatchAdapter} * from the parent/origin session; read by `buildProvider().start()` to * apply the per-session active role (see the module docstring). Absent on * requests dsh itself composes → base-agent behavior. */ sessionId?: string; }; /** * dsh `ResolvedSubagentStartRequest` — the provider-facing request a * `SubagentProvider.start()` receives AFTER the service resolves and stamps * the durable child descriptor * (`ResolvedSubagentStartRequest = SubagentStartRequest & { descriptor: * SubagentDescriptorData }` — `dsh-subagent/src/types.ts:207-210`, `:373`; * dsh 0.1.5-rc.1). The descriptor is REQUIRED here: the service resolves it * before dispatching to `start()`, so a session-backed provider can append it * inside the child's initial turn. rolebox forwards the request losslessly * (`{...request}`) and types the descriptor `unknown` because it never reads * it. The compile-time guard below fails the build if `descriptor` regresses * to optional. */ export type DshResolvedSubagentStartRequest = DshSubagentStartRequest & { descriptor: unknown; }; /** * dsh `SubagentResult` — the terminal outcome a `SubagentRun.result` promise * resolves with (`dsh-subagent/lib/types/types.d.ts:204-223`): * `{ output, structured?, stopReason }` where stopReason ∈ * `{ completed, aborted, error, 'max-tokens', refusal }`. Modelled so the * dispatch adapter reads `run.result` without a cast. */ export interface DshSubagentResult { /** The child agent's output ContentBlocks (§3.4). */ output: DshContentBlock[]; /** Optional structured output (from `SubagentStartRequest.outputSchema`). */ structured?: unknown; /** Why the subagent run ended. */ stopReason: "completed" | "aborted" | "error" | "max-tokens" | "refusal"; } /** * dsh SubagentRun — the result object a provider's `start()` must return (§4.3). */ export type DshSubagentRun = { id: string; localAgent?: unknown; result: Promise; dispose(): Promise; }; /** * dsh `ContinuableCreateRequest` — what the continuation manager hands a * provider while materializing one continuable child's FIRST activation * (`packages/subagent/subagent/src/types.ts:219-229`, dsh 0.1.5-rc.1). The * manager has already reserved the durable child identity and owns every later * operation, so this carries only what distinguishes a fresh child from one * seeded with parent history: the reserved `sessionId` (for provider * diagnostics), the delegating `parent` (whose history a seeding provider * would read), and caller cancellation. * * rolebox reads NONE of these fields — its provider declares the FRESH-START * choice (see {@link DshSubagentProvider.prepareContinuable}) — but the shape * is mirrored so the provider's method signature matches dsh's exactly. */ export type DshContinuableCreateRequest = { /** The reserved durable child session id, for provider diagnostics. */ readonly sessionId: string; /** The delegating parent agent whose history a seeding provider reads. */ readonly parent: unknown; /** Caller cancellation, which owns preparation only until inbox acceptance. */ readonly signal: AbortSignal; }; /** * dsh `ContinuableCreateSpec` — a provider's detached contribution to one * continuable child's creation (`packages/subagent/subagent/src/types.ts: * 237-244`, dsh 0.1.5-rc.1). This is DATA, never a capability: it carries no * Agent, handle, prompt delivery, result, or disposal, because the continuation * manager owns the child's whole lifecycle after preparation. * * The ONLY field is `seed` — the completed-turn prefix of the parent's log to * seed the child session with. It is OPTIONAL and its ABSENCE is exactly the * FRESH-START declaration: `continuation.ts:144-145` reads `prepared.seed` * (`undefined` → no inherited events, `childSessionMeta(..., false)`), while a * present array is persisted through the child's `create.seed`. rolebox * deliberately omits it, matching its `inheritsParentContext: false` stance. * The `SessionEvent[]` element type is mirrored loosely (`unknown[]`) because * rolebox never constructs one — it only ever returns the absent field — and * this adapter stays free of any dsh package import. */ export type DshContinuableCreateSpec = { /** Completed-turn prefix of the parent's log, or absent for a fresh child. */ readonly seed?: readonly unknown[]; }; /** * dsh SubagentProvider — the catalog entry shape registered into * `ctx.subagents` (§4.3, `dsh-subagent/lib/types/types.d.ts:268-307`). */ export type DshSubagentProvider = { name: string; capabilities: DshSubagentCapabilities; inheritsParentContext: boolean; /** * dsh `SubagentProvider.agentRouteDefaults` — an optional static * provider/model route for one-shot Agent options * (`dsh-subagent/src/types.ts:355-361`, dsh 0.1.5-rc.1): detached immutable * data that consumers merge tool/model overrides over before preflight, and * whose presence requires `agentOptions` support. rolebox deliberately does * NOT set it — its route derives per-definition at spawn time via * {@link mergeAgentOptions} (the dynamic `providerRoutes` behavior), and * dsh's contract says a provider whose route derives from the parent omits * it. */ agentRouteDefaults?: Readonly<{ provider: string; model: string; }>; /** * Establish a ONE-SHOT child. The request is the RESOLVED form — the dsh * service has already validated the requested capabilities and stamped the * detached child descriptor, so a session-backed provider appends it inside * the child's initial turn. */ start(request: DshResolvedSubagentStartRequest): Promise; /** * OPTIONAL (continuable-creation capability) — dsh's analogue of rolebox's * opencode `Task(task_id=…)` resumption. Method PRESENCE IS the capability: * the dsh service rejects a continuable start on a provider without it with * `UNSUPPORTED_CAPABILITY` (`packages/subagent/subagent/src/index.ts:593-606`, * `:598`), so a rolebox provider that implements it becomes eligible for * continuable children while still serving ordinary one-shot delegations. * * This is the provider's ONLY participation in a continuable child. The * continuation manager owns identity reservation, composition, Agent * creation, prompt delivery, cold resume, ownership, and disposal — the * provider never sees the child's Agent, handle, turns, or teardown, and * must NOT construct or touch the child itself. It contributes a detached * {@link DshContinuableCreateSpec} only. * * rolebox declares the FRESH-START choice (human decision Q1): the returned * spec OMITS `seed`, so the child session starts fresh rather than being * seeded with the parent's completed-turn history. This matches the * provider's `inheritsParentContext: false`. Implemented unconditionally in * {@link DshAgentRegistrar.buildProvider}. */ prepareContinuable?(request: DshContinuableCreateRequest): Promise; }; /** * dsh SubagentRuntime seam — the minimal `ctx.subagents` surface this * adapter depends on (§4.3, * `dsh-subagent/lib/types/index.d.ts:237,243,248,259` — registerProvider / * getProvider / list / start). * Consumed structurally so the real service can be injected in a dsh profile * and a fake double can be injected in tests. */ export type DshSubagentRuntime = { registerProvider(provider: DshSubagentProvider): () => void; getProvider(name: string): DshSubagentProvider | undefined; list(): string[]; }; /** * Spawn delegate invoked by a registered provider's `start()`. * A host supplies it via {@link DshAgentRegistrarOptions.onSpawn}; when absent, * `start()` delegates to the host provider named by * {@link DshAgentRegistrarOptions.spawnProviderName} (default `"spawn"`), and * only throws `DshSpawnNotWiredError` when that provider is not registered. */ export type DshSpawnDelegate = (definition: AgentDefinition, request: DshSubagentStartRequest) => Promise; /** * Structural per-session active-role lookup consumed at spawn time. * * Deliberately a minimal structural subset (only `get`) of the switcher's * {@link ActiveRoleRef} — agent-registrar must NOT import from * role-switcher.ts (the switcher imports the registrar type, so a value-level * cycle would form). Any object with `get(sessionId): string | null` * satisfies it; `DshRoleSwitcher.activeRole` does, and so does a test double. */ export type DshActiveRoleLookup = { /** Return the active role id for a session, or `null` for the base agent. */ get(sessionId: string): string | null; }; /** * Spawn-time context provider — the dsh counterpart of the rolebox * `system-transform` hook (a documented no-op on dsh, hook-provider.ts:178). * * Given the spawn request's session id, return the rolebox context blocks * (available functions / memory / references — the "context injection" that * reaches a spawned agent on the non-dsh path) to prepend AHEAD of the * active role's prompt. `undefined` (or an empty array) → no context * injection, and the spawn stays unchanged. Wired by the dsh plugin with a * real implementation; tests inject a fake double. */ export type DshSpawnContextProvider = (sessionId: string) => DshContentBlock[] | undefined; /** * Spawn-time probe for the dsh llm service's registered provider routes. * * Returns the route ids currently registered on `ctx.llm` * (`LlmRuntime.listProviders()` → `LlmProviderInfo.id`, the "Provider route key * used by `GenerateOptions.provider`" — `dsh-llm/lib/types/types.d.ts:131-138`, * `index.d.ts:234`). Wired by the dsh plugin from the mounted llm service; * absent when no `ctx.llm` service exists (headless/test doubles), in which * case the registrar emits the split unchanged. A throw is treated as "no * routes registered" so a probe failure degrades safely instead of failing the * spawn. Tests inject a fake. */ export type DshProviderRouteProbe = () => readonly string[]; /** * Thrown by a registered provider's `start()` when neither an `onSpawn` * delegate is wired nor a host provider named by `spawnProviderName` is * registered. Registration/sync/list are unaffected — only actual spawning * fails, with a clear message naming the agent, the missing host provider, and * the currently registered provider names. */ export declare class DshSpawnNotWiredError extends Error { /** The agent id whose provider attempted to spawn. */ readonly agentId: string; /** The host provider name delegation targeted (see `spawnProviderName`). */ readonly hostName: string; constructor(agentId: string, hostName: string, registered: string[]); } /** * Thrown by a registered provider's `start()` when the configured * `spawnProviderName` collides with one of this registrar's own registered * agent ids. Delegating to that host provider would re-enter this same * `start()` (the provider is registered under the agent id), so the registrar * refuses before delegating rather than recursing. */ export declare class DshSpawnRecursionError extends Error { /** The agent id whose provider attempted to spawn. */ readonly agentId: string; /** The colliding host provider name (also a registered agent id). */ readonly hostName: string; constructor(agentId: string, hostName: string); } /** Options for constructing a DshAgentRegistrar. */ export interface DshAgentRegistrarOptions { /** * The dsh `ctx.subagents` seam (SubagentRuntime). Injected so the adapter * stays SDK-free; tests inject a fake double. */ subagents: DshSubagentRuntime; /** * Optional spawn delegate invoked by registered providers' `start()`. * A host supplies it here (the dsh plugin threads its own `onSpawn` config * through — dsh-plugin.ts). When omitted, `start()` delegates to the host * provider named by {@link spawnProviderName} (default `"spawn"`); only when * that provider is not registered does `start()` throw * `DshSpawnNotWiredError`. Registration, sync, and listing remain fully * functional either way. */ onSpawn?: DshSpawnDelegate; /** * Name of the already-registered dsh `ctx.subagents` provider that rolebox * delegates real spawning to when no `onSpawn` delegate is wired. Defaults * to `"spawn"` — the provider `@deepseek-ai/dsh-subagent-spawn-in-process` * registers under its default `providerName`. Point this at any other * registered provider (e.g. `"fork"`). A value colliding with a rolebox * agent id is refused at spawn time with `DshSpawnRecursionError`. */ spawnProviderName?: string; /** * Optional per-session active-role lookup (the {@link DshRoleSwitcher}'s * shared `activeRole` holder). When present, a provider's `start()` * consults it with the request's `sessionId` and prepends the active * role's systemPrompt (applying its model override) — the seam that makes * a web-UI role switch reach the spawned agent. Absent → base behavior. */ activeRole?: DshActiveRoleLookup; /** * Optional spawn-time context provider — the dsh counterpart of the * `system-transform` hook (a documented no-op on dsh). When present, a * provider's `start()` consults it with the request's `sessionId` and, * when an active role exists for that session, prepends the returned * rolebox context blocks ahead of the active role's complete materialized * prompt — so dsh's context injection reaches the spawned role. Absent → * no context injection (spawn unchanged). */ contextProvider?: DshSpawnContextProvider; /** * Optional spawn-time probe for the dsh llm service's registered provider * routes (`ctx.llm.listProviders()`). When wired, a split definition model * whose provider has no registered adapter is logged once and degraded to a * model-only override (see the provider-route safety path in the module * docstring) instead of failing the spawn with `NO_ADAPTER`. Absent → the * split is emitted unchanged. */ providerRoutes?: DshProviderRouteProbe; } /** * IAgentRegistrar implementation that translates rolebox AgentDefinitions * into dsh SubagentProvider registrations on `ctx.subagents`. * * All operations are idempotent: * - `register()` with an identical definition is a no-op; a changed definition * disposes the previous registration before re-registering. * - `unregister()` of unknown ids is a no-op; known ids dispose their dsh * registration (artifact cleanup) and are dropped from the local catalog. * - `sync()` diffs against the current catalog and applies only the delta. */ export declare class DshAgentRegistrar implements IAgentRegistrar { private readonly entries; private readonly subagents; private readonly onSpawn?; private readonly spawnProviderName?; private readonly activeRole?; private readonly contextProvider?; private readonly providerRoutes?; constructor(options: DshAgentRegistrarOptions); /** * Register (or update) a batch of agent definitions. * * Idempotent: registering an identical definition is a no-op. Registering a * changed definition for an existing id disposes the previous dsh * registration first, so the dsh registry never holds duplicates. * * @param agentDefs - Agent definitions to register. */ register(agentDefs: AgentDefinition[]): Promise; /** * Unregister agents by their IDs. * * Disposes each dsh registration (removing the provider from the dsh * registry) and drops the local catalog entry. Silently skips ids that are * not currently registered. * * @param agentIds - IDs of agents to unregister. */ unregister(agentIds: string[]): Promise; /** * Sync the catalog with a new complete set of agent definitions. * * Computes the diff against the current catalog: * - **added**: ids that are new, or whose definition changed (re-registered * after disposing the stale dsh registration) * - **removed**: ids in the current catalog absent from the new set * (disposed) * - **unchanged**: ids present in both with identical definitions (untouched) * * @param agentDefs - The complete new set of agent definitions. * @returns A diff summary with added, removed, and unchanged IDs. */ sync(agentDefs: AgentDefinition[]): Promise<{ added: string[]; removed: string[]; unchanged: string[]; }>; /** * List currently registered agent IDs (the provider names registered into * the dsh subagent catalog). * * @returns A sorted array of registered agent IDs. */ list(): Promise; /** * Retrieve all currently registered agent definitions from the internal * catalog, sorted by agent id. * * Mirrors `PiAgentRegistrar.getRegisteredAgents()`: an extra accessor (the * `IAgentRegistrar` port only exposes id listing) for consumers that need * the resolved definitions — e.g. a role-switcher reading the current * catalog. The returned objects are the definitions stored at registration * time; registration, sync, and unregister semantics are unaffected. * * @returns An array of all currently registered AgentDefinitions, sorted * by id. */ getRegisteredAgents(): AgentDefinition[]; /** * Translate an AgentDefinition into a dsh SubagentProvider. * * The provider's `start()` prepends the definition's system prompt to the * request prompt (§3.4), merges the definition's model into * `agentOptions.provider` + `agentOptions.model` (§4.2; split via the shared * `splitModel` helper), and — when the request carries a sessionId * and the registrar holds an activeRole lookup — additionally prepends the * ACTIVE role's system prompt and applies its model override (the * per-session role-switch seam; see the module docstring). A split provider * with no registered dsh llm adapter degrades to a model-only override with * ONE warning when a `providerRoutes` probe is wired (the provider-route * safety path; see {@link mergeAgentOptions}). It then delegates * in order: the configured `onSpawn` hook when wired, otherwise the host * provider named by `spawnProviderName` (default `"spawn"`). It throws * `DshSpawnRecursionError` when that name collides with a registered agent * id, and `DshSpawnNotWiredError` when no such host provider is registered. * * @param definition - The rolebox agent definition to translate. * @returns A SubagentProvider ready for `ctx.subagents.registerProvider`. */ readonly buildProvider: (definition: AgentDefinition) => DshSubagentProvider; /** * Resolve the active-role override for a spawn request, or `undefined`. * * Returns the active role's AgentDefinition when ALL of these hold: * - the request carries a `sessionId` and the registrar holds an * `activeRole` lookup * - that session has an active role id * - the id resolves to a registered definition OTHER than the spawned * one (spawning the active role's own definition already carries its * system prompt — a redundant prepend would duplicate it) * * Otherwise `undefined` → base behavior (definition's own prompt/model). */ private resolveActiveOverride; /** * Resolve the spawn-time context blocks for a request, or `undefined`. * * The context flows ONLY when an active role exists for the session (the * reported bug: after a web-UI role switch, dsh's context injection never * reached the role) — no active role (or no provider wired) leaves the * spawn unchanged. Note this deliberately does NOT skip the active role's * own definition spawn: its context still applies even when the redundant * prompt prepend is skipped by {@link resolveActiveOverride}. */ private resolveSpawnContext; } //# sourceMappingURL=agent-registrar.d.ts.map