diff options
Diffstat (limited to 'packages/kernel/src/contracts/extension.ts')
| -rw-r--r-- | packages/kernel/src/contracts/extension.ts | 338 |
1 files changed, 169 insertions, 169 deletions
diff --git a/packages/kernel/src/contracts/extension.ts b/packages/kernel/src/contracts/extension.ts index 4d6cf07..fd1594b 100644 --- a/packages/kernel/src/contracts/extension.ts +++ b/packages/kernel/src/contracts/extension.ts @@ -9,11 +9,11 @@ import type { AuthContract } from "./auth.js"; import type { - EventHandler, - EventHookDescriptor, - FilterDescriptor, - FilterHandler, - ServiceHandle, + EventHandler, + EventHookDescriptor, + FilterDescriptor, + FilterHandler, + ServiceHandle, } from "./hooks.js"; import type { Logger } from "./logging.js"; @@ -32,16 +32,16 @@ export type TrustLevel = "bundled" | "local" | "external"; * discovery, dependency resolution, and the capability gate. */ export interface ManifestContributions { - readonly tools?: readonly string[]; - readonly providers?: readonly string[]; - readonly auth?: readonly string[]; - readonly hooks?: readonly string[]; - readonly routes?: readonly string[]; - readonly commands?: readonly string[]; - readonly services?: readonly string[]; - readonly migrations?: readonly string[]; - readonly scheduledJobs?: readonly string[]; - readonly settings?: readonly string[]; + readonly tools?: readonly string[]; + readonly providers?: readonly string[]; + readonly auth?: readonly string[]; + readonly hooks?: readonly string[]; + readonly routes?: readonly string[]; + readonly commands?: readonly string[]; + readonly services?: readonly string[]; + readonly migrations?: readonly string[]; + readonly scheduledJobs?: readonly string[]; + readonly settings?: readonly string[]; } /** @@ -50,12 +50,12 @@ export interface ManifestContributions { * declared capability for. */ export interface ManifestCapabilities { - readonly fs?: boolean; - readonly shell?: boolean; - readonly network?: boolean; - readonly secrets?: boolean; - readonly db?: boolean; - readonly spawn?: boolean; + readonly fs?: boolean; + readonly shell?: boolean; + readonly network?: boolean; + readonly secrets?: boolean; + readonly db?: boolean; + readonly spawn?: boolean; } /** @@ -64,32 +64,32 @@ export interface ManifestCapabilities { * compatibility, and enforce the capability gate. */ export interface Manifest { - /** Unique extension identifier (e.g. "tools-fs", "provider-anthropic"). */ - readonly id: string; + /** Unique extension identifier (e.g. "tools-fs", "provider-anthropic"). */ + readonly id: string; - /** Human-readable display name. */ - readonly name: string; + /** Human-readable display name. */ + readonly name: string; - /** Extension's own version (semver). */ - readonly version: string; + /** Extension's own version (semver). */ + readonly version: string; - /** Semver range of kernel API versions this extension is compatible with. */ - readonly apiVersion: string; + /** Semver range of kernel API versions this extension is compatible with. */ + readonly apiVersion: string; - /** Ids of extensions this one depends on (resolved topologically). */ - readonly dependsOn?: readonly string[]; + /** Ids of extensions this one depends on (resolved topologically). */ + readonly dependsOn?: readonly string[]; - /** Activation strategy: "eager" (on boot) or lazy event triggers. */ - readonly activation?: "eager" | string; + /** Activation strategy: "eager" (on boot) or lazy event triggers. */ + readonly activation?: "eager" | string; - /** What this extension contributes to the system. */ - readonly contributes?: ManifestContributions; + /** What this extension contributes to the system. */ + readonly contributes?: ManifestContributions; - /** Capabilities this extension requires from the host. */ - readonly capabilities?: ManifestCapabilities; + /** Capabilities this extension requires from the host. */ + readonly capabilities?: ManifestCapabilities; - /** Trust level — bundled (first-party), local (project), or external. */ - readonly trust: TrustLevel; + /** Trust level — bundled (first-party), local (project), or external. */ + readonly trust: TrustLevel; } // --- Storage interface --- @@ -100,40 +100,40 @@ export interface Manifest { * only the contract. Supports key-value and simple query operations. */ export interface StorageNamespace { - readonly get: (key: string) => Promise<string | null>; - readonly set: (key: string, value: string) => Promise<void>; - readonly delete: (key: string) => Promise<void>; - readonly has: (key: string) => Promise<boolean>; - readonly keys: (prefix?: string) => Promise<readonly string[]>; + readonly get: (key: string) => Promise<string | null>; + readonly set: (key: string, value: string) => Promise<void>; + readonly delete: (key: string) => Promise<void>; + readonly has: (key: string) => Promise<boolean>; + readonly keys: (prefix?: string) => Promise<readonly string[]>; } // --- Permission --- /** The outcome of a permission check. */ export interface PermissionDecision { - readonly allowed: boolean; - readonly reason?: string; + readonly allowed: boolean; + readonly reason?: string; } /** A request to check whether an action is permitted. */ export interface PermissionRequest { - readonly tool: string; - readonly action: string; - readonly context?: Readonly<Record<string, unknown>>; + readonly tool: string; + readonly action: string; + readonly context?: Readonly<Record<string, unknown>>; } /** Permission gate exposed through the Host API. */ export interface PermissionGate { - readonly check: (request: PermissionRequest) => Promise<PermissionDecision>; + readonly check: (request: PermissionRequest) => Promise<PermissionDecision>; } // --- Scheduler --- /** A scheduled job definition an extension can register with the host. */ export interface ScheduledJob { - readonly id: string; - readonly cron: string; - readonly execute: () => void | Promise<void>; + readonly id: string; + readonly cron: string; + readonly execute: () => void | Promise<void>; } // --- Logger is re-exported from logging.ts (structured, correlated) --- @@ -142,24 +142,24 @@ export interface ScheduledJob { /** Read-only config access for an extension's own settings namespace. */ export interface ConfigAccess { - readonly get: <T = unknown>(key: string) => T | undefined; - readonly getAll: () => Readonly<Record<string, unknown>>; + readonly get: <T = unknown>(key: string) => T | undefined; + readonly getAll: () => Readonly<Record<string, unknown>>; } // --- Secrets --- /** Capability-gated access to the secret/credential vault. */ export interface SecretsAccess { - readonly get: (key: string) => Promise<string | null>; - readonly set: (key: string, value: string) => Promise<void>; - readonly delete: (key: string) => Promise<void>; + readonly get: (key: string) => Promise<string | null>; + readonly set: (key: string, value: string) => Promise<void>; + readonly delete: (key: string) => Promise<void>; } // --- Events emitter --- /** Outward event emitter available to extensions via the Host API. */ export interface EventsEmitter { - readonly emit: (event: { readonly type: string; readonly [key: string]: unknown }) => void; + readonly emit: (event: { readonly type: string; readonly [key: string]: unknown }) => void; } // --- Host API --- @@ -175,102 +175,102 @@ export interface EventsEmitter { * module (not the kernel contracts). */ export interface HostAPI { - /** Register a tool with the kernel's tool registry. */ - readonly defineTool: (tool: ToolContract) => void; - - /** Register a provider with the kernel's provider registry. */ - readonly defineProvider: (provider: ProviderContract) => void; - - /** Register an auth provider with the kernel's auth registry. */ - readonly defineAuth: (auth: AuthContract) => void; - - /** Subscribe to an event hook. Handlers are error-isolated per call. */ - readonly on: <TPayload>( - hook: EventHookDescriptor<TPayload>, - handler: EventHandler<TPayload>, - ) => () => void; - - /** - * Emit an event hook: fire-and-forget dispatch to every `on` subscriber, - * error-isolated per handler (a thrown handler is caught + logged, never - * breaks the caller). The counterpart of `on`. - * - * This lets a core extension that OWNS a lifecycle publish typed events that - * standard extensions react to — e.g. the session-orchestrator emitting - * per-turn start/settle events a cache-warming extension subscribes to. The - * kernel owns the mechanism; the owner declares the typed `EventHookDescriptor`. - */ - readonly emit: <TPayload>(hook: EventHookDescriptor<TPayload>, payload: TPayload) => void; - - /** Add a filter to a filter hook chain. Filters are awaited in-band. */ - readonly addFilter: <TValue>( - hook: FilterDescriptor<TValue>, - fn: FilterHandler<TValue>, - ) => () => void; - - /** - * Run a filter chain: thread `value` through every filter registered for - * `hook` in priority/registration order and return the final value. The - * single-value-in/value-out counterpart to `addFilter`. Awaited in-band. - * - * Fail-open by default (a thrown filter is logged and the value passes - * through unchanged); pass `{ failClosed: true }` to make a thrown filter - * reject. With no registered filters the input value is returned as-is. - * - * This is what lets a core extension expose a contribution point (e.g. the - * session-orchestrator running a per-turn tool/context-assembly chain) that - * standard extensions plug into via `addFilter` — the kernel owns the - * mechanism, the owner declares the typed `FilterDescriptor`. - */ - readonly applyFilters: <TValue>( - hook: FilterDescriptor<TValue>, - value: TValue, - opts?: { readonly failClosed?: boolean }, - ) => Promise<TValue>; - - /** Provide an implementation for a typed service handle. */ - readonly provideService: <T>(handle: ServiceHandle<T>, impl: T) => void; - - /** Retrieve the implementation for a typed service handle. */ - readonly getService: <T>(handle: ServiceHandle<T>) => T; - - /** Get a namespaced storage interface for this extension. */ - readonly storage: (namespace: string) => StorageNamespace; - - /** Read-only access to merged config (global → project → extension). */ - readonly config: ConfigAccess; - - /** Capability-gated access to the secret/credential vault. */ - readonly secrets: SecretsAccess; - - /** Permission gate — check whether an action is allowed. */ - readonly permissions: PermissionGate; - - /** Emit outward events (transport pushes these to clients). */ - readonly events: EventsEmitter; - - /** Logger — always available, even before other extensions activate. */ - readonly logger: Logger; - - /** Read-only view of all registered providers. */ - readonly getProviders: () => ReadonlyMap<string, ProviderContract>; - - /** Read-only view of all registered tools. */ - readonly getTools: () => ReadonlyMap<string, ToolContract>; - - /** Read-only view of all registered auth providers. */ - readonly getAuthProviders: () => ReadonlyMap<string, AuthContract>; - - /** Look up a single auth provider by id. */ - readonly getAuthProvider: (id: string) => AuthContract | undefined; - - /** Read-only view of all activated extensions' manifests (what is loaded). */ - readonly getExtensions: () => readonly Manifest[]; - - /** Register a scheduled job with the host's scheduler. */ - readonly scheduler: { - readonly register: (job: ScheduledJob) => void; - }; + /** Register a tool with the kernel's tool registry. */ + readonly defineTool: (tool: ToolContract) => void; + + /** Register a provider with the kernel's provider registry. */ + readonly defineProvider: (provider: ProviderContract) => void; + + /** Register an auth provider with the kernel's auth registry. */ + readonly defineAuth: (auth: AuthContract) => void; + + /** Subscribe to an event hook. Handlers are error-isolated per call. */ + readonly on: <TPayload>( + hook: EventHookDescriptor<TPayload>, + handler: EventHandler<TPayload>, + ) => () => void; + + /** + * Emit an event hook: fire-and-forget dispatch to every `on` subscriber, + * error-isolated per handler (a thrown handler is caught + logged, never + * breaks the caller). The counterpart of `on`. + * + * This lets a core extension that OWNS a lifecycle publish typed events that + * standard extensions react to — e.g. the session-orchestrator emitting + * per-turn start/settle events a cache-warming extension subscribes to. The + * kernel owns the mechanism; the owner declares the typed `EventHookDescriptor`. + */ + readonly emit: <TPayload>(hook: EventHookDescriptor<TPayload>, payload: TPayload) => void; + + /** Add a filter to a filter hook chain. Filters are awaited in-band. */ + readonly addFilter: <TValue>( + hook: FilterDescriptor<TValue>, + fn: FilterHandler<TValue>, + ) => () => void; + + /** + * Run a filter chain: thread `value` through every filter registered for + * `hook` in priority/registration order and return the final value. The + * single-value-in/value-out counterpart to `addFilter`. Awaited in-band. + * + * Fail-open by default (a thrown filter is logged and the value passes + * through unchanged); pass `{ failClosed: true }` to make a thrown filter + * reject. With no registered filters the input value is returned as-is. + * + * This is what lets a core extension expose a contribution point (e.g. the + * session-orchestrator running a per-turn tool/context-assembly chain) that + * standard extensions plug into via `addFilter` — the kernel owns the + * mechanism, the owner declares the typed `FilterDescriptor`. + */ + readonly applyFilters: <TValue>( + hook: FilterDescriptor<TValue>, + value: TValue, + opts?: { readonly failClosed?: boolean }, + ) => Promise<TValue>; + + /** Provide an implementation for a typed service handle. */ + readonly provideService: <T>(handle: ServiceHandle<T>, impl: T) => void; + + /** Retrieve the implementation for a typed service handle. */ + readonly getService: <T>(handle: ServiceHandle<T>) => T; + + /** Get a namespaced storage interface for this extension. */ + readonly storage: (namespace: string) => StorageNamespace; + + /** Read-only access to merged config (global → project → extension). */ + readonly config: ConfigAccess; + + /** Capability-gated access to the secret/credential vault. */ + readonly secrets: SecretsAccess; + + /** Permission gate — check whether an action is allowed. */ + readonly permissions: PermissionGate; + + /** Emit outward events (transport pushes these to clients). */ + readonly events: EventsEmitter; + + /** Logger — always available, even before other extensions activate. */ + readonly logger: Logger; + + /** Read-only view of all registered providers. */ + readonly getProviders: () => ReadonlyMap<string, ProviderContract>; + + /** Read-only view of all registered tools. */ + readonly getTools: () => ReadonlyMap<string, ToolContract>; + + /** Read-only view of all registered auth providers. */ + readonly getAuthProviders: () => ReadonlyMap<string, AuthContract>; + + /** Look up a single auth provider by id. */ + readonly getAuthProvider: (id: string) => AuthContract | undefined; + + /** Read-only view of all activated extensions' manifests (what is loaded). */ + readonly getExtensions: () => readonly Manifest[]; + + /** Register a scheduled job with the host's scheduler. */ + readonly scheduler: { + readonly register: (job: ScheduledJob) => void; + }; } // --- Extension lifecycle --- @@ -281,18 +281,18 @@ export interface HostAPI { * `deactivate` is optional and called on shutdown or reload. */ export interface Extension { - /** The extension's manifest — its declaration of identity and capabilities. */ - readonly manifest: Manifest; - - /** - * Called by the host to activate the extension. The extension registers - * its contributions (tools, providers, hooks, services) through the Host API. - */ - readonly activate: (host: HostAPI) => void | Promise<void>; - - /** - * Optional cleanup called when the extension is deactivated (shutdown, - * reload, or auto-disable). Should dispose resources the extension owns. - */ - readonly deactivate?: () => void | Promise<void>; + /** The extension's manifest — its declaration of identity and capabilities. */ + readonly manifest: Manifest; + + /** + * Called by the host to activate the extension. The extension registers + * its contributions (tools, providers, hooks, services) through the Host API. + */ + readonly activate: (host: HostAPI) => void | Promise<void>; + + /** + * Optional cleanup called when the extension is deactivated (shutdown, + * reload, or auto-disable). Should dispose resources the extension owns. + */ + readonly deactivate?: () => void | Promise<void>; } |
