Skip to content

extensions

Present only inside a core-run read (projection, run tools, hooks).

  • Shape<"@fungi.computer/shiitake/ExtensionRead", Readonly<{ extensionId: string & Brand<"ExtensionId">; }>, this>

new ExtensionRead(_): ExtensionRead

never

ExtensionRead

Context.Service< ExtensionRead, Readonly<{ extensionId: ExtensionId }> >()("@fungi.computer/shiitake/ExtensionRead").constructor


Present only inside a core-run write transaction (hooks, commands, transact). Core runs these Effects synchronously inside the owner transaction; an asynchronous boundary is a defect that stops the extension.

  • Shape<"@fungi.computer/shiitake/ExtensionTx", Readonly<{ extensionId: string & Brand<"ExtensionId">; }>, this>

new ExtensionTx(_): ExtensionTx

never

ExtensionTx

Context.Service< ExtensionTx, Readonly<{ extensionId: ExtensionId }> >()("@fungi.computer/shiitake/ExtensionTx").constructor


Durable record failure: stored or supplied values broke their schema or bounds.

  • YieldableError<this> & object & Readonly<{ reason: "unavailable" | "decode" | "encode" | "bound"; message: string; }>

new ExtensionStateError(args): ExtensionStateError

"unavailable" | "decode" | "encode" | "bound"

string

ExtensionStateError

Data.TaggedError( “ExtensionStateError”, )<{ reason: “decode” | “encode” | “bound” | “unavailable”; message: string; }>.constructor

readonly reason: "unavailable" | "decode" | "encode" | "bound"

Data.TaggedError( "ExtensionStateError", ).reason

message: string

Data.TaggedError( "ExtensionStateError", ).message


The door refused an extension admission.

  • YieldableError<this> & object & Readonly<{ reason: "closed" | "conflict" | "invalid"; message: string; }>

new AdmissionError(args): AdmissionError

"closed" | "conflict" | "invalid"

string

AdmissionError

Data.TaggedError(“AdmissionError”)<{ reason: “invalid” | “conflict” | “closed”; message: string; }>.constructor

readonly reason: "closed" | "conflict" | "invalid"

Data.TaggedError("AdmissionError").reason

message: string

Data.TaggedError("AdmissionError").message


Typed rejection of one extension command, returned to its caller.

  • YieldableError<this> & object & Readonly<{ reason: "conflict" | "invalid" | "rejected" | "not_found"; message: string; }>

new ExtensionCommandError(args): ExtensionCommandError

"conflict" | "invalid" | "rejected" | "not_found"

string

ExtensionCommandError

Data.TaggedError( “ExtensionCommandError”, )<{ reason: “invalid” | “conflict” | “not_found” | “rejected”; message: string; }>.constructor

readonly reason: "conflict" | "invalid" | "rejected" | "not_found"

Data.TaggedError( "ExtensionCommandError", ).reason

message: string

Data.TaggedError( "ExtensionCommandError", ).message


Fail a hook with this (or die) to stop this extension with a visible reason.

  • YieldableError<this> & object & Readonly<{ reason: string; }>

new ExtensionStop(args): ExtensionStop

string

ExtensionStop

Data.TaggedError("ExtensionStop")<{ reason: string; }>.constructor

readonly reason: string

Data.TaggedError("ExtensionStop").reason


Typed activation failure; the extension is stopped with this message.

  • YieldableError<this> & object & Readonly<{ message: string; }>

new ExtensionActivationError(args): ExtensionActivationError

string

ExtensionActivationError

Data.TaggedError( "ExtensionActivationError", )<{ message: string }>.constructor

message: string

Data.TaggedError( "ExtensionActivationError", ).message


Configure typed metadata, then register callbacks against its actual values.

S extends CollectionsV0

Config extends Json

D extends DocumentsV0

static fromIdentity(identity): ExtensionBuilderV0<Readonly<Record<never, never>>>>, Readonly<Record<never, never>>>>, Readonly<Record<never, never>>>>>>

Begin with concrete empty metadata and no requested capability.

Readonly<{ id: ExtensionId; version: string; }>

ExtensionBuilderV0<Readonly<Record<never, never>>, Readonly<Record<never, never>>, Readonly<Record<never, never>>>

config<Next>>(value): ExtensionBuilderV0<S, Next, D>>

Hash this explicit JSON configuration with the extension revision.

Next extends Json

Next

ExtensionBuilderV0<S, Next, D>

state<Next>>(value): ExtensionBuilderV0<Next, Config, D>>

Request state and bind handles to each collection’s declared schema.

Next extends Readonly<Record<string, Readonly<{ schema: Codec<unknown>; bind: (port, name) => CollectionBindingV0; indexFromEncoded: (value) => Result<string | null, SchemaError>; key: (value) => string; index?: (value) => string | null; }>>>

StateSpecV0<Next>

ExtensionBuilderV0<Next, Config, D>

documents<Next>>(value): ExtensionBuilderV0<S, Config, Next>>

Request bounded Session documents under the state grant.

Next extends Readonly<Record<string, Readonly<{ schema: Codec<unknown>; initial: unknown; fork: DocumentForkPolicyV0; maxBytes: number; }>>>

Next

ExtensionBuilderV0<S, Config, Next>

define<C, P, PI, H>>(definition): Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> > & Readonly<{ contract: ExtensionContractV0<C, P, PI>>; client: Readonly<{ attach: (context) => Effect<void, Error, Scope>>; }>; }>

Register commands and an installed client entry.

C extends Readonly<Record<string, Readonly<{ scope: "session" | "agent"; input: Codec<unknown>; output: Codec<unknown>; }>>>

P

PI

H extends CommandHandlersV0<C> = CommandHandlersV0<C>

Omit<Readonly<{ catalog?: Json; commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<C>; }>; projection?: Readonly<{ schema: Codec<P, PI>; read: (context, sessionId) => Option<P>; }>; prompt?: (context, run) => readonly Readonly<{ name: string; text: string; }>[] | Promise<readonly Readonly<{ name: …; text: …; }>[]> | Effect<readonly Readonly<{ name: …; text: …; }>[], HookError, ExtensionRead>; tools?: (context, run) => Readonly<{ [moduleBrand]: true; }> | Promise<Readonly<{ [moduleBrand]: …; }> | null> | Effect<Readonly<{ [moduleBrand]: …; }> | Option<Readonly<…>> | null, HookError, ExtensionRead> | null; hooks?: Readonly<{ start?: (context) => void | Promise<…> | Effect<…, …, …>; onSettled?: (context, page) => void | Effect<…, …, …>; onTimer?: (context, timer) => void | Effect<…, …, …>; }>; timers?: true; compaction?: (context) => Readonly<{ consume: (view) => CompactionHandoffResultV0 | Promise<…> | Effect.Effect<…, …>; }>; client?: Readonly<{ attach: (context) => void | Effect<void, Error, Scope> | Promise<void>; }>; }>, "commands" | "client"> & Readonly<{ commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<NoInfer<C>> & H & CheckedCommandHandlers<H>; }>; }> & object

Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> & Readonly<{ contract: ExtensionContractV0<C, P, PI>; client: Readonly<{ attach: (context) => Effect<void, Error, Scope>; }>; }>

define<C, P, PI, H>>(definition): Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> > & Readonly<{ contract: ExtensionContractV0<C, P, PI>>; }>

Register commands without a client entry.

C extends Readonly<Record<string, Readonly<{ scope: "session" | "agent"; input: Codec<unknown>; output: Codec<unknown>; }>>>

P

PI

H extends CommandHandlersV0<C> = CommandHandlersV0<C>

Omit<Readonly<{ catalog?: Json; commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<C>; }>; projection?: Readonly<{ schema: Codec<P, PI>; read: (context, sessionId) => Option<P>; }>; prompt?: (context, run) => readonly Readonly<{ name: string; text: string; }>[] | Promise<readonly Readonly<{ name: …; text: …; }>[]> | Effect<readonly Readonly<{ name: …; text: …; }>[], HookError, ExtensionRead>; tools?: (context, run) => Readonly<{ [moduleBrand]: true; }> | Promise<Readonly<{ [moduleBrand]: …; }> | null> | Effect<Readonly<{ [moduleBrand]: …; }> | Option<Readonly<…>> | null, HookError, ExtensionRead> | null; hooks?: Readonly<{ start?: (context) => void | Promise<…> | Effect<…, …, …>; onSettled?: (context, page) => void | Effect<…, …, …>; onTimer?: (context, timer) => void | Effect<…, …, …>; }>; timers?: true; compaction?: (context) => Readonly<{ consume: (view) => CompactionHandoffResultV0 | Promise<…> | Effect.Effect<…, …>; }>; client?: Readonly<{ attach: (context) => void | Effect<void, Error, Scope> | Promise<void>; }>; }>, "commands" | "client"> & Readonly<{ commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<NoInfer<C>> & H & CheckedCommandHandlers<H>; }>; }> & object

Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> & Readonly<{ contract: ExtensionContractV0<C, P, PI>; }>

define<P, PI>>(definition): Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> > & Readonly<{ contract: ExtensionContractV0<EmptyExtensionFieldsV0, P, PI>>; client: Readonly<{ attach: (context) => Effect<void, Error, Scope>>; }>; }>

Register contributions without commands, with an installed client entry.

P

PI

Omit<Readonly<{ catalog?: Json; commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<C>; }>; projection?: Readonly<{ schema: Codec<P, PI>; read: (context, sessionId) => Option<P>; }>; prompt?: (context, run) => readonly Readonly<{ name: string; text: string; }>[] | Promise<readonly Readonly<{ name: …; text: …; }>[]> | Effect<readonly Readonly<{ name: …; text: …; }>[], HookError, ExtensionRead>; tools?: (context, run) => Readonly<{ [moduleBrand]: true; }> | Promise<Readonly<{ [moduleBrand]: …; }> | null> | Effect<Readonly<{ [moduleBrand]: …; }> | Option<Readonly<…>> | null, HookError, ExtensionRead> | null; hooks?: Readonly<{ start?: (context) => void | Promise<…> | Effect<…, …, …>; onSettled?: (context, page) => void | Effect<…, …, …>; onTimer?: (context, timer) => void | Effect<…, …, …>; }>; timers?: true; compaction?: (context) => Readonly<{ consume: (view) => CompactionHandoffResultV0 | Promise<…> | Effect.Effect<…, …>; }>; client?: Readonly<{ attach: (context) => void | Effect<void, Error, Scope> | Promise<void>; }>; }>, "commands" | "client"> & Readonly<{ commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<NoInfer<Readonly<…>>> & Readonly<Record<never, never>> & CheckedCommandHandlers<Readonly<Record<…, …>>>; }>; }> & object

Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> & Readonly<{ contract: ExtensionContractV0<EmptyExtensionFieldsV0, P, PI>; client: Readonly<{ attach: (context) => Effect<void, Error, Scope>; }>; }>

define<P, PI>>(definition): Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> > & Readonly<{ contract: ExtensionContractV0<EmptyExtensionFieldsV0, P, PI>>; }>

Register contributions without commands or a client entry.

P

PI

Omit<Readonly<{ catalog?: Json; commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<C>; }>; projection?: Readonly<{ schema: Codec<P, PI>; read: (context, sessionId) => Option<P>; }>; prompt?: (context, run) => readonly Readonly<{ name: string; text: string; }>[] | Promise<readonly Readonly<{ name: …; text: …; }>[]> | Effect<readonly Readonly<{ name: …; text: …; }>[], HookError, ExtensionRead>; tools?: (context, run) => Readonly<{ [moduleBrand]: true; }> | Promise<Readonly<{ [moduleBrand]: …; }> | null> | Effect<Readonly<{ [moduleBrand]: …; }> | Option<Readonly<…>> | null, HookError, ExtensionRead> | null; hooks?: Readonly<{ start?: (context) => void | Promise<…> | Effect<…, …, …>; onSettled?: (context, page) => void | Effect<…, …, …>; onTimer?: (context, timer) => void | Effect<…, …, …>; }>; timers?: true; compaction?: (context) => Readonly<{ consume: (view) => CompactionHandoffResultV0 | Promise<…> | Effect.Effect<…, …>; }>; client?: Readonly<{ attach: (context) => void | Effect<void, Error, Scope> | Promise<void>; }>; }>, "commands" | "client"> & Readonly<{ commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<NoInfer<Readonly<…>>> & Readonly<Record<never, never>> & CheckedCommandHandlers<Readonly<Record<…, …>>>; }>; }> & object

Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand<"RosteredExtensionV0"> & Readonly<{ contract: ExtensionContractV0<EmptyExtensionFieldsV0, P, PI>; }>


An outside handler rejected or threw before Shiitake could use its result.

  • YieldableError<this> & object & Readonly<{ cause: unknown; }>

new ExtensionHookError(args): ExtensionHookError

unknown

ExtensionHookError

Data.TaggedError("ExtensionHookError")<{ cause: unknown; }>.constructor

cause: unknown

Data.TaggedError("ExtensionHookError").cause

ShiitakeExtensionProtocolV0 = "shiitake.extension/v0"

The one extension protocol, shared by host and client entries.


ExtensionId = Schema.Schema.Type<typeof ExtensionId>>

ASCII extension identity shared by the server definition and its clients.


ExtensionManifestV0 = Readonly<{ protocol: ShiitakeExtensionProtocolV0; id: ExtensionId; version: string; requests: readonly ExtensionCapabilityV0[]; }>

Static identity and requested capabilities of one v0 extension.


CommandSpecV0<S, I, II, O, OI> > = Readonly<{ scope: S; input: Schema.Codec<I, II>>; output: Schema.Codec<O, OI>>; }>

One command’s scope and its encoded input and output schemas.

S extends "session" | "agent"

I

II

O

OI


AnyCommandSpecV0 = Readonly<{ scope: "session" | "agent"; input: Schema.Codec<unknown>>; output: Schema.Codec<unknown>>; }>

Existential command spec.


CommandsV0 = Readonly<Record<string, AnyCommandSpecV0>>>>

Commands declared by one extension contract.


ProjectionSpecV0<P, PI> > = Readonly<{ schema: Schema.Codec<P, PI>>; }>

The encoded Session projection slot.

P

PI


ExtensionContractV0<C, P, PI> > = Readonly<{ id: ExtensionId; commands: C; projection: ProjectionSpecV0<P, PI> > | null; }>

Shared by the host definition and the client binding: one schema set.

C extends CommandsV0

P

PI


ClientActivityV0 = "idle" | "working" | "blocked" | "unknown"

Activity already observed by the client, never an execution authority.


ClientExtensionContextV0 = Readonly<{ activity: Stream.Stream<ClientActivityV0>>; onError: (error) => void; }>

Borrowed client observation; no Session mutations, storage or credentials.


ClientEntryV0 = Readonly<{ manifest: ExtensionManifestV0; contract: Readonly<{ id: ExtensionId; commands: Readonly<Record<string, Readonly<{ scope: "session" | "agent"; input: Schema.Top; output: Schema.Top; }>>>; projection: Readonly<{ schema: Schema.Top; }> | null; }>; client: Readonly<{ attach: (context) => Effect.Effect<void, Error, Scope.Scope>>; }>; }>

Trusted installed entry; attaches for one selected client lifetime.


ExtensionRevision = typeof extensionRevisionSchema.Type

sha256:<64 hex> derived by core from a definition; never authored.


ExtensionFingerprint = typeof extensionFingerprintSchema.Type

sha256:<64 hex> over one revision and its sorted granted capabilities.


Json = null | boolean | number | string | readonly Json[] | Readonly<{[key: string]: Json; }>

JSON value accepted as hashed extension configuration.


ExtensionGrantV0 = Readonly<{ id: ExtensionId; capabilities: readonly ExtensionCapabilityV0[]; }>

Host decision: the exact subset of requested capabilities it grants.


HookError = ExtensionStop | ExtensionStateError | AdmissionError | ExtensionHookError

Failures a background hook may return; each one stops only its extension.


CollectionSpecV0<A, I> > = Readonly<{ schema: Schema.Codec<A, I>>; bind: (port, name) => Readonly<{ read: CollectionV0<A>>; update: UpdateCollectionV0<A>>; }>; indexFromEncoded: (value) => Result.Result<string | null, Schema.SchemaError>>; key: (value) => string; index?: (value) => string | null; }>

One namespaced collection: its row schema is the only stored-row decoder.

A

I


AnyCollectionSpecV0 = Readonly<{ schema: Schema.Codec<unknown>>; bind: (port, name) => CollectionBindingV0; indexFromEncoded: (value) => Result.Result<string | null, Schema.SchemaError>>; key: (value) => string; index?: (value) => string | null; }>

Existential collection spec stored by core.


CollectionsV0 = Readonly<Record<string, AnyCollectionSpecV0>>>>

Collections declared by one extension.


StoredRecordV0 = Readonly<{ collection: string; key: string; value: Json; }>

One stored record as seen by a pure migration.


StateSpecV0<C> > = Readonly<{ version: number; collections: C; migrations: Readonly<Record<number, (row) => readonly StoredRecordV0[]>>; }>

Versioned state declaration; core runs pure row migrations at activation.

C extends CollectionsV0


CollectionV0<A> > = Readonly<{ peek: (key) => Option.Option<A>>; peekPage: (query) => readonly A[]; get: (key) => Effect.Effect<Option.Option<A>>, ExtensionStateError, ExtensionRead>>; page: (query) => Effect.Effect<readonly A[], ExtensionStateError, ExtensionRead>>; put: (value) => Effect.Effect<void, ExtensionStateError, ExtensionTx>>; remove: (key) => Effect.Effect<void, ExtensionStateError, ExtensionTx>>; }>

Typed access to one collection inside a core transaction.

A


UpdateCollectionV0<A> > = Readonly<{ get: (key) => Option.Option<A>>; page: (query) => readonly A[]; put: (value) => void; remove: (key) => void; }>

The transaction-local interface used by plain synchronous state.update.

A


UpdateStateV0<C> > = { readonly [K in keyof C]: ReturnType<C[K]["bind"]>["update"] } & Readonly<{ observe: (sessionId) => void; }>

Transaction-scoped collections plus post-commit Session notification.

C extends CollectionsV0


StateHandleV0<C> > = { readonly [K in keyof C]: ReturnType<C[K]["bind"]>["read"] } & Readonly<{ update: StateUpdate<UpdateStateV0<C>>>>; }>

Typed handles for every declared collection.

C extends CollectionsV0


RunOutcomeV0 = "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown"

Watchdog settlement or exact Woodstock terminal of one run.


RunOriginV0 = Readonly<{ extensionId: ExtensionId; correlation: string | null; }>

Extension that admitted a run, with its stored correlation.


SettledRunV0 = Readonly<{ sequence: number; sessionId: string; workId: string; outcome: RunOutcomeV0; terminal: RunOutcomeV0 | "missing"; toolCalls: number; origin: RunOriginV0 | null; }>

One settled run joined by core with its terminal and admission origin.


SettledPageV0 = readonly SettledRunV0[]

1..64 records, ascending, each delivered to each running extension once.


SendInputV0 = Readonly<{ sessionId: string; prompt: Readonly<{ text: string; requestId: string; delivery: "followUp" | "steer"; }>; when: "now" | "idle"; correlation?: string; }>

One prompt sent through the accepted-command door.


SendResultV0 = Readonly<{ _tag: "Accepted"; commandId: string; delivery: "new" | "replay"; }> | Readonly<{ _tag: "NotReady"; }>

Door outcome for one extension admission.


TimersV0 = Readonly<{ set: (key, dueAt) => Effect.Effect<void, ExtensionStateError, ExtensionTx>>; cancel: (key) => Effect.Effect<void, ExtensionStateError, ExtensionTx>>; read: (key) => Effect.Effect<Option.Option<number>>, ExtensionStateError, ExtensionRead>>; }>

Durable per-extension wake timers (the scheduling substrate).


FiredTimerV0 = Readonly<{ key: string; dueAt: number; firedAt: number; }>

A fired timer; its row is consumed unless the handler sets it again.


CommandSessionIdsV0 = object

A command’s scope fixes whether its invocation names a Session.

agent: null

session: string


CommandHandlersV0<C> > = { readonly [K in keyof C]: (call: Readonly<{ sessionId: CommandSessionIdsV0[C[K][“scope”]]; input: C[K][“input”][“Type”] }>) => C[K][“output”][“Type”] | Effect.Effect<C[K][“output”][“Type”], ExtensionCommandError | ExtensionStateError | AdmissionError, ExtensionTx | ExtensionRead> }

Handlers for every declared command, run in one core transaction.

C extends CommandsV0


ExtensionContextV0<S, Config, D> > = Readonly<{ manifest: ExtensionManifestV0; revision: ExtensionRevision; grants: readonly ExtensionCapabilityV0[]; config: Config; state: StateHandleV0<S>>; documents: DocumentHandlesV0<D>>; send: (input) => Effect.Effect<SendResultV0, AdmissionError, ExtensionTx>>; timers: TimersV0; observe: (sessionId) => Effect.Effect<void, never, ExtensionTx>>; transact: <A, E>>(body) => Effect.Effect<A, E | ExtensionStop | ShiitakeError>>; }>

Everything core hands one activated extension.

S extends CollectionsV0

Config extends Json

D extends DocumentsV0 = DocumentsV0


RunIdentityV0 = Readonly<{ sessionId: string; workId: string; origin: RunOriginV0 | null; }>

One run the extension may attach tools to.


PromptSectionV0 = Readonly<{ name: string; text: string; }>

A named, bounded system-prompt section; core orders by extension and name.


AgentHooksV0<C, P> > = Readonly<{ onSettled?: (page) => Effect.Effect<void, HookError, ExtensionTx | ExtensionRead>>; onTimer?: (timer) => Effect.Effect<void, HookError, ExtensionTx | ExtensionRead>>; moduleForRun?: (run) => Effect.Effect<Option.Option<ModuleRegistration>>, HookError, ExtensionRead>>; prompt?: (run) => readonly PromptSectionV0[] | Promise<readonly PromptSectionV0[]> | Effect.Effect<readonly PromptSectionV0[], HookError, ExtensionRead>>; project?: (sessionId) => Option.Option<P>>; compactionHandoff?: CompactionHandoffV0; commands: CommandHandlersV0<C>>; }>

Hooks returned by one activation; each runs in its own isolation boundary.

C extends CommandsV0

P


RosteredExtensionV0 = Readonly<{ manifest: ExtensionManifestV0; [definitionReader]?: () => AnyExtensionDefinitionV0; }> & Brand.Brand<"RosteredExtensionV0">>

Opaque rostered value; core reads the definition existentially.


ExtensionClientV0 = Readonly<{ attach: (context) => void | Promise<void> > | Effect.Effect<void, Error, Scope.Scope>>; }>

Optional installed client entry; lifecycle setup may await network work.


ExtensionDefinitionV0<S, C, P, PI, Config, D> > = Readonly<{ catalog?: Json; commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<C>>; }>; projection?: Readonly<{ schema: Schema.Codec<P, PI>>; read: (context, sessionId) => Option.Option<P>>; }>; prompt?: (context, run) => readonly PromptSectionV0[] | Promise<readonly PromptSectionV0[]> | Effect.Effect<readonly PromptSectionV0[], HookError, ExtensionRead>>; tools?: (context, run) => ModuleRegistration | null | Promise<ModuleRegistration | null> > | Effect.Effect<ModuleRegistration | null | Option.Option<ModuleRegistration>>, HookError, ExtensionRead>>; hooks?: Readonly<{ start?: (context) => void | Promise<void> > | Effect.Effect<void, ExtensionActivationError, Scope.Scope>>; onSettled?: (context, page) => void | Effect.Effect<void, HookError, ExtensionTx | ExtensionRead>>; onTimer?: (context, timer) => void | Effect.Effect<void, HookError, ExtensionTx | ExtensionRead>>; }>; timers?: true; compaction?: (context) => Readonly<{ consume: (view) => CompactionHandoffResultV0 | Promise<CompactionHandoffResultV0> > | Effect.Effect<CompactionHandoffResultV0, CompactionHandoffErrorV0 | ExtensionHookError>>; }>; client?: ExtensionClientV0; }>

Contributions registered against the builder’s captured metadata.

S extends CollectionsV0

C extends CommandsV0

P

PI

Config extends Json

D extends DocumentsV0 = DocumentsV0


CheckedCommandHandlers<H> > = { readonly [K in keyof H]: H[K] extends (args: never[]) => infer Result ? Result extends Promise<unknown> ? never : H[K] : never }

Reject Promise-returning transactional commands even when output is {}.

H


ExtensionAuthorDefinitionV0<S, C, P, PI, Config, D, H> > = Omit<ExtensionDefinitionV0<S, C, P, PI, Config, D>>, "commands" | "client"> > & Readonly<{ commands?: Readonly<{ specs: C; handlers: (context) => CommandHandlersV0<NoInfer<C>> >> & H & CheckedCommandHandlers<H>>; }>; }>

Caller-owned extension metadata and handlers accepted by the v0 builder.

S extends CollectionsV0

C extends CommandsV0

P

PI

Config extends Json

D extends DocumentsV0

H extends CommandHandlersV0<C>


EmptyExtensionFieldsV0 = Readonly<Record<never, never>>>>

Concrete metadata with no declared fields.


AnyAgentHooksV0 = Readonly<{ onSettled?: NonNullable<AgentHooksV0<CommandsV0, never>>["onSettled"]>; onTimer?: NonNullable<AgentHooksV0<CommandsV0, never>>["onTimer"]>; moduleForRun?: NonNullable<AgentHooksV0<CommandsV0, never>>["moduleForRun"]>; prompt?: NonNullable<AgentHooksV0<CommandsV0, never>>["prompt"]>; project?: (sessionId) => Option.Option<unknown>>; compactionHandoff?: CompactionHandoffV0; commands: ReadonlyMap<string, RegisteredExtensionCommandV0>>; }>

Existential hooks as stored by core; each handler is re-typed by its schema.


AnyExtensionDefinitionV0 = Readonly<{ manifest: ExtensionManifestV0; contract: Readonly<{ id: ExtensionId; commands: CommandsV0; projection: Readonly<{ schema: Schema.Codec<unknown>>; }> | null; }>; config: Json; state: StateSpecV0<CollectionsV0>>; documents?: DocumentsV0; catalog?: Json; activate: (port) => Effect.Effect<AnyAgentHooksV0, ExtensionActivationError | ExtensionHookError, Scope.Scope>>; }>

Existential definition stored by core.


ExtensionRosterV0 = Readonly<{ roster: readonly RosteredExtensionV0[]; grants: readonly ExtensionGrantV0[]; gateRunTools?: (input) => OperationGate; }>

A host’s explicit roster and grants.


ExtensionStatusV0 = Readonly<{ id: string; version: string; revision: string; status: "running" | "stopped"; reason: string | null; stoppedAt: number | null; }>

Visible lifecycle of one rostered extension (wire representation).


ExtensionSlotV0 = Readonly<{ status: "running"; revision: string; value: Json; catalog?: Json; }> | Readonly<{ status: "stopped"; revision: string; reason: string; }>

One extension’s encoded slot in a Session snapshot or frame.


BorrowedCompactionViewV0 = Readonly<{ messagesToSummarize: readonly Message[]; turnPrefixMessages: readonly Message[]; result: Readonly<{ summary: string; firstKeptEntryId: string; tokensBefore: number; usage: Usage; details?: Readonly<{ readFiles: readonly string[]; modifiedFiles: readonly string[]; }>; }>; contextRevision: string; }>

Borrowed view of the exact objects already built for compaction.


CompactionHandoffResultV0 = Readonly<{ type: "accepted"; receipt: string; }> | Readonly<{ type: "discarded_by_policy"; }>

Result returned before a borrowed compaction view may be released.


CompactionHandoffErrorV0 = Readonly<{ _tag: "CompactionHandoffError"; message: string; }>

Typed failure returned by the compaction contribution.


CompactionHandoffV0 = Readonly<{ consume: (view) => Effect.Effect<CompactionHandoffResultV0, CompactionHandoffErrorV0 | ExtensionHookError>>; }>

The exclusive compaction handoff callable of one extension.


RegisteredExtensionCommandV0 = (frame) => Result.Result<() => Effect.Effect<Json, ExtensionCommandError | ExtensionStateError | AdmissionError, ExtensionTx | ExtensionRead>>, Schema.SchemaError>>

A parsed invocation retains its typed handler until the transaction runs.

Readonly<{ sessionId: string | null; input: Json; }>

Result.Result<() => Effect.Effect<Json, ExtensionCommandError | ExtensionStateError | AdmissionError, ExtensionTx | ExtensionRead>, Schema.SchemaError>


CollectionBindingV0 = Readonly<{ read: Omit<CollectionV0<unknown>>, "put"> > & Pick<CollectionV0<never>>, "put">>; update: Omit<UpdateCollectionV0<unknown>>, "put"> > & Pick<UpdateCollectionV0<never>>, "put">>; }>

Core retains only these erased results; the author retains each concrete factory.


ExtensionRuntimePortV0 = Readonly<{ context: Omit<ExtensionContextV0<EmptyExtensionFieldsV0, Json, EmptyExtensionFieldsV0>>, "config" | "state" | "documents">>; collection: <A, I>>(name, spec) => CollectionV0<A>>; updateCollection: <A, I>>(name, spec) => UpdateCollectionV0<A>>; document: <A, I>>(name, spec) => DocumentHandleV0<A>>; update: <A>>(body) => A; observeUpdate: (sessionId) => void; }>

State operations capture their typed declaration before entering core.


SyncResult<A> > = A extends Option.Option<unknown> > ? A : A extends Promise<unknown> > | Effect.Effect<unknown, unknown, unknown> > ? never : A

A write callback must resolve before the owner commits its SQLite transaction.

A


StateUpdate<Tx> > = <A>>(handler) => A

Public state-update shape: infer the return before rejecting async results.

Tx

A

(tx) => SyncResult<A>

A

const extensionIdentifier: String

ASCII extension identity shared by the host definition and its clients.


const extensionVersion: String

SemVer spelling used by both host admission and installed client entries.


const ExtensionId: brand<String, "ExtensionId">>

ASCII extension identity shared by the host definition and its clients.


const parseClientEntryV0: (input, options?) => Readonly<{ manifest: ExtensionManifestV0; contract: Readonly<{ id: ExtensionId; commands: Readonly<Record<string, Readonly<{ scope: "session" | "agent"; input: Schema.Top; output: Schema.Top; }>>>; projection: Readonly<{ schema: Schema.Top; }> | null; }>; client: Readonly<{ attach: (context) => Effect.Effect<void, Error, Scope.Scope>>; }>; }>

Decode an installed entry before attachment; it does not sandbox its code.

unknown

ParseOptions

Readonly<{ manifest: ExtensionManifestV0; contract: Readonly<{ id: ExtensionId; commands: Readonly<Record<string, Readonly<{ scope: "session" | "agent"; input: Schema.Top; output: Schema.Top; }>>>; projection: Readonly<{ schema: Schema.Top; }> | null; }>; client: Readonly<{ attach: (context) => Effect.Effect<void, Error, Scope.Scope>; }>; }>

parseExtensionJson(source): Json

Parse a serialized extension value into the finite JSON contract.

string

Json


defineExtension(identity): ExtensionBuilderV0<Readonly<Record<never, never>>>>, Readonly<Record<never, never>>>>, Readonly<Record<never, never>>>>>>

Begin with honest empty defaults; optional contributions are declared explicitly.

Readonly<{ id: ExtensionId; version: string; }>

ExtensionBuilderV0<Readonly<Record<never, never>>, Readonly<Record<never, never>>, Readonly<Record<never, never>>>


defineCollection<A, I>>(schema, keys): CollectionSpecV0<A, I>>

Declare one collection with its key inferred from the row schema.

A

I

Codec<A, I>

Readonly<{ key: (value) => string; index?: (value) => string | null; }>

CollectionSpecV0<A, I>

Re-exports ExtensionCapabilityV0