Skip to content

Extensions ​

The extensions subsystem lets an agent define versioned Cordis packages, run their host and browser halves, and query approved runtime metadata before writing code. It also owns the shared ctx.importedPlugins service, which stages and lifecycle-manages immutable OpenAI/Codex plugin bundles for every Hydra profile, plus the two user-declared record registries that extend the agent from settings rather than from a bundle: ctx.mcpServers mounts each enabled MCP server record as an mcp-client fiber, and ctx.hookRecords mounts each enabled hook record on its Claude Code or Codex bridge. Package lifecycle and sandbox behavior belong to the packages/extensions package group.

Cordis API ​

Generated from source by scripts/gen-cordis-catalog.ts (verified fresh by pnpm run verify-cordis-catalog in doc-sync; regenerate with pnpm run gen-cordis-catalog) — the language sides differ only in locale-specific paired document paths. Signature blocks use a ts cordis-catalog fence and keep the original source JSDoc; dispatch modes are defined in the primer, and the framework-inherited ctx API lives in cordis-api/inherited.md.

ctx.cordisInspect — CordisInspectRegistryService ​

Registry and cross-page router behind the two model-facing inspect tools.

ts
/**
 * Register one Host provider.
 * @param registration - manifest and local query handler.
 * @returns idempotent disposer.
 */
register(registration: HostCordisInspectProviderRegistration): () => void

/**
 * Replace the mirrored Client provider directory.
 * @param providers - complete Client manifest snapshot.
 */
syncClientManifest(providers: readonly CordisInspectProviderManifest[]): void

/**
 * Return the complete known Host and Client provider directory.
 * @returns Host providers followed by the Client providers.
 */
list(): CordisInspectProviderView[]

/**
 * Execute one provider query on its owning platform.
 * @param platform - Host or Client runtime.
 * @param providerId - provider selected from {@link list}.
 * @param methodName - declared method name.
 * @param input - optional lossless JSON input.
 * @param agent - requesting Agent and scope.
 * @param signal - tool-call cancellation.
 * @returns provider JSON data.
 */
async query( platform: CordisInspectPlatform, providerId: string, methodName: string, input: JsonValue | undefined, agent: Agent, signal: AbortSignal, ): Promise<JsonValue>

/**
 * Accept the first valid Client response for a pending query.
 * @param agent - Agent whose Session owns the query.
 * @param requestId - Pending Client query identity.
 * @param resolution - Client provider result or failure.
 * @returns whether this response settled the still-pending query.
 */
resolveClientQuery( agent: Agent, requestId: CordisInspectRequestId, resolution: CordisInspectQueryResolution, ): CordisInspectResolveAck

Types: Agent

Source: packages/extensions/cordis-host-runner/src/inspect-registry.ts

ctx.dynamicCordisRunner — DynamicCordisRunnerService ​

Dynamic Plugin registry and Host-half lifecycle.

ts
/**
 * Define a new Plugin's first Package or append a Package to an existing Plugin.
 * @param request - Session ownership, Plugin selection, metadata, and source code.
 * @returns Host-minted Plugin and Package identities with declared-half metadata.
 */
define(request: DynamicCordisDefineRequest): DynamicCordisDefineReceipt

/**
 * Remove a Plugin, its active run, and all immutable Packages.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity to remove.
 * @returns Whether removal succeeded and whether it stopped an active run.
 */
async undefine(agent: Agent, pluginId: CordisDynamicPluginId): Promise<DynamicCordisUndefineReceipt>

/**
 * Remove a Plugin from the user panel and queue the resulting state change for the model's next step.
 * @param agent - Agent whose Session owns the Plugin and receives the context.
 * @param pluginId - Stable Plugin identity to remove.
 * @returns Whether removal succeeded and whether it stopped an active run.
 */
@Remote('undefineFromPanel') async undefineFromPanel(agent: Agent, pluginId: CordisDynamicPluginId): Promise<DynamicCordisUndefineReceipt>

/**
 * Start or update one Package for a model tool call. An unauthorized Client
 * Package waits for approval; Plugin-wide authorization covers later versions.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity to activate.
 * @param packageId - Immutable Package version to activate.
 * @param mode - Whether to run the current version or switch versions.
 * @param signal - Tool-call cancellation signal while the activation request is being created.
 * @returns The successful activation identity or an actionable refusal.
 */
async run( agent: Agent, pluginId: CordisDynamicPluginId, packageId: CordisDynamicPackageId, mode: CordisDynamicRunMode, signal?: AbortSignal, ): Promise<DynamicCordisRunResponse>

/**
 * Start Host code for an approved request or a direct panel gesture.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity to activate.
 * @param packageId - Immutable Package version to activate.
 * @param mode - Whether to run the current version or switch versions.
 * @param requestId - Model-driven request identity, or null for a direct user gesture.
 * @param approveFutureVersions - Whether this approval covers later Packages of the same Plugin.
 * @returns The exact Host activation or a failure message.
 */
@Remote('runHostHalf') async runHostHalf( agent: Agent, pluginId: CordisDynamicPluginId, packageId: CordisDynamicPackageId, mode: CordisDynamicRunMode, requestId: ApprovalRequestId | null, approveFutureVersions: boolean, ): Promise<DynamicCordisHostHalfResult>

/**
 * Fetch Client code for the exact active run.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity to read.
 * @param pluginRunId - Exact active run authorized to receive source.
 * @returns Client source and its Plugin, Package, and run identities.
 */
@Remote('getClientCode') getClientCode( agent: Agent, pluginId: CordisDynamicPluginId, pluginRunId: CordisDynamicPluginRunId, ): DynamicCordisClientSource

/**
 * Resolve one model-driven Client activation request.
 * @param requestId - Request identity to settle once.
 * @param resolution - Browser refusal or exact Client activation result.
 * @returns Whether the still-pending request accepted this resolution.
 */
@Remote('resolveRequestRun') async resolveRequestRun( requestId: ApprovalRequestId, resolution: DynamicCordisRunResolution, ): Promise<DynamicCordisResolveAck>

/**
 * Settle a direct panel run after this page loaded or failed its Client half.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity being settled.
 * @param resolution - Exact Client activation result from the acting page.
 * @returns The committed activation or its failure.
 */
@Remote('settleUserRun') async settleUserRun( agent: Agent, pluginId: CordisDynamicPluginId, resolution: DynamicCordisRunResolution, ): Promise<DynamicCordisRunResponse>

/**
 * Stop the active run while retaining every Package version.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity to stop.
 * @returns Success or the reason no run was stopped.
 */
async stop(agent: Agent, pluginId: CordisDynamicPluginId): Promise<DynamicCordisStopResponse>

/**
 * Stop a Plugin from the user panel and queue the resulting state change for the model's next step.
 * @param agent - Agent whose Session owns the Plugin and receives the context.
 * @param pluginId - Stable Plugin identity to stop.
 * @returns Success or the reason no run was stopped.
 */
@Remote('stopFromPanel') async stopFromPanel(agent: Agent, pluginId: CordisDynamicPluginId): Promise<DynamicCordisStopResponse>

/**
 * Replace the Host mirror of the Client inspect provider directory.
 * @param providers - complete Client provider manifest.
 * @returns null after accepting the manifest.
 */
@Remote('syncInspectManifest') syncInspectManifest(providers: readonly CordisInspectProviderManifest[]): null

/**
 * Claim one pending Client inspect query with its live result.
 * @param agent - Session that owns the query.
 * @param requestId - exact pending query identity.
 * @param resolution - provider result or structured refusal.
 * @returns whether this answer won the query.
 */
@Remote('resolveInspectQuery') resolveInspectQuery( agent: Agent, requestId: CordisInspectRequestId, resolution: CordisInspectQueryResolution, ): CordisInspectResolveAck

/**
 * Frame-wide inventory, grouped as one row per stable Plugin.
 * @returns Source-free metadata for every process-local Plugin.
 */
@Remote('inventory') inventory(): DynamicCordisInventoryRow[]

/**
 * Read one Session's Host-rich state for inspection and result rendering.
 * @param agent - Agent whose Session selects visible Plugins.
 * @returns Plugin versions, active runs, Host fibers, and render failures.
 */
snapshot(agent: Agent): DynamicCordisSnapshotRow[]

/**
 * Read source-free context for an explicit `@pluginId` user gesture.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity referenced by the user.
 * @returns The preferred modification base, or undefined when unavailable.
 */
reference(agent: Agent, pluginId: CordisDynamicPluginId): DynamicCordisReference | undefined

/**
 * List source-free Plugin summaries owned by one Session.
 * @param agent - Agent whose Session selects visible Plugins.
 * @returns one summary per Plugin in creation order.
 */
listPlugins(agent: Agent): DynamicCordisPluginInspection[]

/**
 * Inspect one Plugin without returning Package source.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - stable Plugin identity.
 * @returns version pointers, latest run, and all Package summaries.
 */
inspectPlugin(agent: Agent, pluginId: CordisDynamicPluginId): DynamicCordisPluginInspection

/**
 * Read one exact immutable Package and its Host and Client source.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity that owns the Package.
 * @param packageId - Exact immutable Package identity to inspect.
 * @returns Package metadata, source, and the Plugin's lifecycle pointers.
 */
inspectPackage( agent: Agent, pluginId: CordisDynamicPluginId, packageId: CordisDynamicPackageId, ): DynamicCordisPackageInspection

/**
 * Record a post-load render failure for the exact active run.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity that rendered.
 * @param pluginRunId - Exact active run that produced the failure.
 * @param failure - Slot, message, and entry-retirement result.
 * @returns Null after recording or ignoring a stale report.
 */
@Remote('reportRenderFailure') async reportRenderFailure( agent: Agent, pluginId: CordisDynamicPluginId, pluginRunId: CordisDynamicPluginRunId, failure: DynamicCordisRenderFailure, ): Promise<null>

/**
 * Report a Client guard rejection that happened after the Package completed activation.
 * @param agent - Agent whose Session must own the Plugin.
 * @param pluginId - Stable Plugin identity whose Client code was rejected.
 * @param pluginRunId - Exact active run that produced the rejection.
 * @param failure - Original guard message and stack.
 * @returns Null after reporting or ignoring a stale/startup failure.
 */
@Remote('reportClientGuardFailure') async reportClientGuardFailure( agent: Agent, pluginId: CordisDynamicPluginId, pluginRunId: CordisDynamicPluginRunId, failure: CordisErrorDetails, ): Promise<null>

/**
 * Invoke an active Host method while rejecting stale Client runs.
 * @param pluginId - Stable Plugin identity that owns the method.
 * @param pluginRunId - Exact active run authorizing the call.
 * @param method - Registered Host handler name.
 * @param args - JSON argument delivered to the handler.
 * @returns The JSON result or a typed invocation failure.
 */
@Remote('invoke') async invoke( pluginId: CordisDynamicPluginId, pluginRunId: CordisDynamicPluginRunId, method: string, args: JsonValue, ): Promise<DynamicCordisInvokeResult>

Types: Agent

Source: packages/extensions/cordis-host-runner/src/index.ts

ctx.hookRecords — HookRecordRegistry ​

Settings-backed hook records with their live bridge mounts. Reconciliation is idempotent and runs on one serialized chain, so a document commit from any source — this service's own write, another process, or a hand edit — converges the mounted set on the stored one. Mutations reject with SettingsConflictError if another writer changes the stored section after the read; retry uses the refreshed projection.

ts
/**
 * Project every stored record with its live state.
 * @param settings - optional layer whose desired records to project.
 * @returns the current record projection, in stored order.
 */
list(settings?: SettingsProvider): HookRecordSnapshot

/**
 * Reconcile the current effective settings after a layer or trust change.
 * @returns completion after earlier queued work and the current mounts settle.
 */
settle(): Promise<void>

/**
 * Create or replace one complete definition as requested, then
 * converge the mounted set. A definition this registry could not mount is
 * refused before anything persists.
 * @param request - complete record definition.
 * @param settings - selected write layer; omitted uses this registry's provider.
 * @returns the refreshed projection.
 * @throws If create names an existing record or replace names a missing record.
 */
define(request: HookRecordDefinitionRequest, settings: SettingsProvider = this.owner.settings): Promise<HookRecordSnapshot>

/**
 * Change one stored record's desired state.
 * @param request - target record and desired state.
 * @param settings - selected write layer; omitted uses this registry's provider.
 * @returns the refreshed projection.
 */
setEnabled(request: HookRecordEnablementRequest, settings: SettingsProvider = this.owner.settings): Promise<HookRecordSnapshot>

/**
 * Remove one stored record, unmount it, and delete any document this registry
 * materialized for it.
 * @param name - stored record name.
 * @param settings - selected write layer; omitted uses this registry's provider.
 * @returns the refreshed projection.
 */
remove(name: string, settings: SettingsProvider = this.owner.settings): Promise<HookRecordSnapshot>

Types: SettingsProvider

Source: packages/hooks/hooks-registry/src/index.ts

ctx.importedPlugins — ImportedPluginRuntime ​

Shared @hydraharness/harness-base service for every imported bundle, not a Web-only facility.

ts
/**
 * Return every imported plugin's current source-qualified runtime view.
 * @returns Current installed-plugin projection.
 */
async list(): Promise<ImportedPluginSnapshot>

/**
 * Return one installed plugin view.
 * @param identityOrName - Source-qualified identity or an unambiguous plugin name.
 * @returns Current installed-plugin projection.
 */
async info(identityOrName: string): Promise<ImportedPluginEntry>

/**
 * Stage one local, Git, or marketplace source.
 * @param source - Source to import.
 * @returns Refreshed installed-plugin projection.
 */
import(source: PluginImportSource): Promise<ImportedPluginSnapshot>

/**
 * Enable and load one plugin.
 * @param identityOrName - Plugin identity or unambiguous name.
 * @returns Refreshed installed-plugin projection.
 */
enable(identityOrName: string): Promise<ImportedPluginSnapshot>

/**
 * Disable and unload one plugin.
 * @param identityOrName - Plugin identity or unambiguous name.
 * @returns Refreshed installed-plugin projection.
 */
disable(identityOrName: string): Promise<ImportedPluginSnapshot>

/**
 * Trust one plugin's current hook definition.
 * @param identityOrName - Plugin identity or unambiguous name.
 * @returns Refreshed installed-plugin projection.
 */
trustHooks(identityOrName: string): Promise<ImportedPluginSnapshot>

/**
 * Revoke one plugin's hook trust.
 * @param identityOrName - Plugin identity or unambiguous name.
 * @returns Refreshed installed-plugin projection.
 */
untrustHooks(identityOrName: string): Promise<ImportedPluginSnapshot>

/**
 * Unload and remove one plugin with its owned store paths.
 * @param identityOrName - Plugin identity or unambiguous name.
 * @returns Refreshed installed-plugin projection.
 */
remove(identityOrName: string): Promise<ImportedPluginSnapshot>

/**
 * Set one plugin MCP server's lifecycle state.
 * @param identityOrName - Owning plugin identity or unambiguous name.
 * @param server - Manifest MCP server name.
 * @param enabled - Desired server state.
 * @returns Refreshed installed-plugin projection.
 */
async setMcpServerEnabled(identityOrName: string, server: string, enabled: boolean): Promise<ImportedPluginSnapshot>

/**
 * Set one MCP tool's approval mode.
 * @param identityOrName - Owning plugin identity or unambiguous name.
 * @param server - Manifest MCP server name.
 * @param tool - Raw MCP tool name or host-qualified public tool name.
 * @param approval - Independent per-tool approval mode.
 * @returns Refreshed installed-plugin projection.
 */
async setMcpToolApproval( identityOrName: string, server: string, tool: string, approval: 'ask' | 'allow' | 'deny', ): Promise<ImportedPluginSnapshot>

/**
 * Unload every live component owned by one plugin.
 * @param identity - Installed plugin identity.
 * @returns After skills, hooks, and MCP fibers quiesce.
 */
async unload(identity: string): Promise<void>

Source: packages/host/plugin-runtime/src/index.ts

ctx.mcpServers — McpServerRegistry ​

Settings-backed MCP server records with their live mcp-client mounts. Reconciliation is idempotent and runs on one serialized chain, so a document commit from any source — this service's own write, another process, or a hand edit — converges the mounted set on the stored one. Mutations reject with SettingsConflictError if another writer changes the stored section after the read; retry uses the refreshed projection.

ts
/**
 * Project every stored record with its live state.
 * @param settings - optional layer whose desired records to project.
 * @returns the current record projection, in stored order.
 */
list(settings?: SettingsProvider): McpServerSnapshot

/**
 * Reconcile the current effective settings after a layer or trust change.
 * @returns completion after earlier queued work and the current mounts settle.
 */
settle(): Promise<void>

/**
 * Create or replace one complete definition as requested, then
 * converge the mounted set. A definition this registry could not mount is
 * refused before anything persists.
 * @param request - complete server definition.
 * @param settings - selected write layer; omitted uses this registry's provider.
 * @returns the refreshed projection.
 * @throws If create names an existing record or replace names a missing record.
 */
define(request: McpServerDefinitionRequest, settings: SettingsProvider = this.owner.settings): Promise<McpServerSnapshot>

/**
 * Change one stored record's desired state.
 * @param request - target record and desired state.
 * @param settings - selected write layer; omitted uses this registry's provider.
 * @returns the refreshed projection.
 */
setEnabled(request: McpServerEnablementRequest, settings: SettingsProvider = this.owner.settings): Promise<McpServerSnapshot>

/**
 * Remove one stored record and unmount it.
 * @param name - stored record name.
 * @param settings - selected write layer; omitted uses this registry's provider.
 * @returns the refreshed projection.
 */
remove(name: string, settings: SettingsProvider = this.owner.settings): Promise<McpServerSnapshot>

Types: SettingsProvider

Source: packages/mcp/mcp-registry/src/index.ts

ctx.optionalPlugins — OptionalPluginPolicy ​

Immediate disablement and leases for operations that may already be running.

ts
/** Rejects new optional work while disabled and tracks work already admitted.
 * @returns an idempotent completion lease; rejects a new operation immediately while disabled.
 */
acquire(): () => void

/** Waits for owned work before a contribution can be removed.
 * @returns settlement when existing optional operations finish, or the user enables plugins again.
 */
drain(): Promise<void>

/** Observes accepted common-policy changes.
 * @param listener - callback after an accepted policy change.
 * @returns subscription disposer.
 */
subscribe(listener: (enabled: boolean) => void): () => void

Source: packages/host/optional-plugins/src/index.ts

cordis/* events ​

cordis/dynamic-package — emit ​

One exact Plugin/Package activation is now live in the Host.

ts
/**
 * One exact Plugin/Package activation is now live in the Host.
 * @param pkg - stable plugin, immutable package, run identity, and label.
 * @mode emit
 */
'cordis/dynamic-package'(pkg: DynamicCordisPackage): void

Source: packages/extensions/cordis-host-runner/src/types.ts

cordis/dynamic-retract — emit ​

One exact activation was withdrawn.

ts
/**
 * One exact activation was withdrawn.
 * @param retracted - plugin, package, and run identity.
 * @mode emit
 */
'cordis/dynamic-retract'(retracted: DynamicCordisRetracted): void

Source: packages/extensions/cordis-host-runner/src/types.ts

cordis/inspect-query — emit ​

Request a live read-only query from the Client inspect registry.

ts
/**
 * Request a live read-only query from the Client inspect registry.
 * @param request - correlation, Session, provider, method, and JSON input.
 * @mode emit
 */
'cordis/inspect-query'(request: CordisInspectQueryRequest): void

Source: packages/extensions/cordis-host-runner/src/types.ts

cordis/inspect-query-resolved — emit ​

Notify every Client that an inspect query has settled or been cancelled.

ts
/**
 * Notify every Client that an inspect query has settled or been cancelled.
 * @param resolved - exact query identity that is no longer answerable.
 * @mode emit
 */
'cordis/inspect-query-resolved'(resolved: CordisInspectQueryResolved): void

Source: packages/extensions/cordis-host-runner/src/types.ts

cordis/request-run — emit ​

A Client-bearing activation needs a browser page, and may require a user decision.

ts
/**
 * A Client-bearing activation needs a browser page, and may require a user decision.
 * @param request - correlation identity, owner, target version, mode, and approval requirement.
 * @mode emit
 */
'cordis/request-run'(request: DynamicCordisRunRequest): void

Source: packages/extensions/cordis-host-runner/src/types.ts

cordis/request-run-resolved — emit ​

A pending Client activation request left the answerable state.

ts
/**
 * A pending Client activation request left the answerable state.
 * @param resolved - request identity and outcome.
 * @mode emit
 */
'cordis/request-run-resolved'(resolved: DynamicCordisRequestResolved): void

Source: packages/extensions/cordis-host-runner/src/types.ts

hooks-registry/* events ​

hooks-registry/reconciled — emit ​

The mounted bridge set now matches the stored records. Emitted after each reconciliation settles — including the one at startup and the ones a document change triggers — so an observer never reads the projection between a committed record change and the mount that follows it.

ts
/**
 * The mounted bridge set now matches the stored records. Emitted after each
 * reconciliation settles — including the one at startup and the ones a
 * document change triggers — so an observer never reads the projection
 * between a committed record change and the mount that follows it.
 * @param snapshot - the projection as of this reconciliation.
 * @mode emit
 */
'hooks-registry/reconciled'(snapshot: HookRecordSnapshot): void

Source: packages/hooks/hooks-registry/src/types.ts

mcp-servers/* events ​

mcp-servers/reconciled — emit ​

The mounted server set now matches the stored records. Emitted after each reconciliation settles — including the one at startup and the ones a document change triggers — so an observer never reads the projection between a committed record change and the mount that follows it.

ts
/**
 * The mounted server set now matches the stored records. Emitted after each
 * reconciliation settles — including the one at startup and the ones a
 * document change triggers — so an observer never reads the projection
 * between a committed record change and the mount that follows it.
 * @param snapshot - the projection as of this reconciliation.
 * @mode emit
 */
'mcp-servers/reconciled'(snapshot: McpServerSnapshot): void

Source: packages/mcp/mcp-registry/src/types.ts