import { ModuleComponentType, ModuleUISlot, SmrtModuleMeta } from '@happyvertical/smrt-types'; /** * UI type definitions for SMRT Agents * * These types allow agents to declare admin panel UI slots * that can be implemented as Svelte components in agent packages. * * @example * ```typescript * import { AgentUIRegistry, type AdminPanelBaseProps } from '@happyvertical/smrt-agents/ui'; * * // In agent package: register components at import time * AgentUIRegistry.register('MyAgent', 'settings', SettingsPanel); * * // In host app: use registered components * const Component = AgentUIRegistry.get('MyAgent', 'settings'); * ``` */ /** * Svelte component type for agent admin-panel slots. * * Re-exported from the canonical {@link ModuleComponentType} in * `@happyvertical/smrt-types` — the single shared definition that owns the * irreducible `any` (see its inline note: the placeholder must be assignable * both FROM arbitrary concrete components and TO Svelte's render union, which * no non-`any` type satisfies under `strictFunctionTypes`). Aliased here so * this package's public UI surface keeps the local `ComponentType` name. */ export type ComponentType = ModuleComponentType; /** * Base props that all admin panel components receive */ export interface AdminPanelBaseProps { /** Current configuration from the agent (merged file + db) */ config: TConfig; /** Callback to save configuration changes */ onSave: (config: TConfig) => Promise; /** Whether the panel is in read-only mode */ readonly?: boolean; /** CSS class for styling integration */ class?: string; /** * Read-only file-based configuration defaults (from smrt.config.js) * Use this to display which values come from the config file */ fileConfig?: TConfig; /** * Editable database-persisted configuration overrides * Use this to display which values have been customized in the DB */ dbConfig?: TConfig; } export type AgentSettingFieldType = 'string' | 'number' | 'boolean' | 'select' | 'textarea' | 'json'; export interface AgentSettingOption { value: string; label: string; } /** A non-secret setting that a host app can render without custom UI code. */ export interface AgentSettingField { id: string; label: string; type: AgentSettingFieldType; description?: string; required?: boolean; default?: unknown; placeholder?: string; options?: AgentSettingOption[]; min?: number; max?: number; } /** Versioned contract for a schema-rendered agent settings panel. */ export interface AgentSettingsSchema { version: number; fields: AgentSettingField[]; } /** * Definition of a UI slot that an agent declares * * Agents define slots they support; UI packages implement them. */ export interface AgentUISlot { /** Unique identifier for this slot (e.g., 'sources', 'reports', 'settings') */ id: string; /** Human-readable label for the slot */ label: string; /** Description of what this panel configures */ description?: string; /** Icon identifier (e.g., 'settings', 'database', 'users') */ icon?: string; /** Display order (lower numbers first) */ order?: number; /** Whether the slot is currently unavailable in the admin UI */ disabled?: boolean; /** Durable owner for settings written through this slot. */ scope?: 'agent' | 'persona'; /** Optional fallback form when the agent does not register a custom panel. */ settingsSchema?: AgentSettingsSchema; } /** * Map of slot IDs to their definitions * Used as static property on Agent subclasses */ export type AgentUISlots = Record; /** * A route an agent provides for its admin UI * * Agents declare these so that host applications or tooling * (for example, a Vite plugin) can wire them into a SvelteKit app. * * @example * ```typescript * static adminRoutes: AgentAdminRoute[] = [ * { path: 'sources', component: 'SourcesPanel', load: 'loadSources' }, * { path: 'sources/[sourceId]', component: 'SourceDetail', load: 'loadSourceDetail' }, * ]; * ``` */ export interface AgentAdminRoute { /** Route path relative to agent root (e.g., 'sources/[sourceId]') */ path: string; /** Component export name from the agent's admin entry point */ component: string; /** Optional: export name for server load function */ load?: string; } /** * Context passed to agent route load functions * * A normalized subset of SvelteKit's ServerLoadEvent, * so agent load functions don't need a direct SvelteKit dependency. */ export interface AgentRouteLoadContext { params: Record; parent: () => Promise>; fetch: typeof fetch; url: URL; } /** * Agent route load function signature * * Returned data is spread into the page's `data` prop. */ export type AgentRouteLoadFn = (context: AgentRouteLoadContext) => Promise> | Record; /** * Agent manifest type (re-exported from smrt-core scanner types) * Duplicated here to avoid hard dependency on scanner internals */ export interface AgentManifestInfo { name: string; slug: string; icon?: string; tier: 'free' | 'standard' | 'premium'; description?: string; uiSlots: Record; adminRoutes?: AgentAdminRoute[]; /** Default signal subscriptions declared by this agent */ signalSubscriptions?: string[]; permissions: Array<{ id: string; label: string; category: string; defaultGranted?: boolean; }>; features: Array<{ id: string; label: string; description?: string; type: string; }>; menuItems: Array<{ id: string; label: string; icon?: string; order: number; path: string; requiredPermission?: string; }>; components: Array<{ exportPath: string; type: string; }>; } /** * Registry of UI component implementations * Maps agent class name + slot ID to Svelte component */ export interface AgentUIComponentRegistry { /** Register a component for an agent's slot */ register(agentClass: string, slotId: string, component: ComponentType): void; /** Get a component for an agent's slot */ get(agentClass: string, slotId: string): ComponentType | undefined; /** Get all registered slot IDs for an agent */ getSlots(agentClass: string): string[]; /** Check if a component is registered */ has(agentClass: string, slotId: string): boolean; /** Get all registered agent class names */ getAgents(): string[]; /** Unregister a component (useful for testing) */ unregister(agentClass: string, slotId: string): boolean; /** Clear all registrations (useful for testing) */ clear(): void; /** Register a component by composite key (e.g., 'praeco:sources') */ registerByKey(key: string, component: ComponentType): void; /** Get a component by composite key */ getByKey(key: string): ComponentType | undefined; /** Register an agent manifest for runtime access */ registerManifest(agentClass: string, manifest: AgentManifestInfo): void; /** Get a registered agent manifest */ getManifest(agentClass: string): AgentManifestInfo | undefined; /** Get all registered manifests */ getAllManifests(): Map; /** Register a route component for an agent */ registerRouteComponent(agentClass: string, path: string, component: ComponentType): void; /** Get a route component for an agent */ getRouteComponent(agentClass: string, path: string): ComponentType | undefined; /** Register a route load function for an agent */ registerRouteLoad(agentClass: string, path: string, loadFn: AgentRouteLoadFn): void; /** Get a route load function for an agent */ getRouteLoad(agentClass: string, path: string): AgentRouteLoadFn | undefined; } /** * Create a new UI component registry * * @example * ```typescript * const registry = createUIRegistry(); * registry.register('MyAgent', 'settings', SettingsPanel); * * const Component = registry.get('MyAgent', 'settings'); * if (Component) { * // Render component * } * ``` */ export declare function createUIRegistry(): AgentUIComponentRegistry; /** * Global UI registry singleton * * Agent UI packages register their components here at import time, * enabling discovery by host applications. * * Uses a `globalThis.__smrtAgentUIRegistry` property to guarantee a * single registry instance per JavaScript runtime, even when bundlers * (Vite, webpack) duplicate this module across optimized dependency * chunks or package versions. * * @example * ```typescript * // In agent package (e.g., @happyvertical/praeco/admin) * import { AgentUIRegistry } from '@happyvertical/smrt-agents/ui'; * import SourcesPanel from './SourcesPanel.svelte'; * * AgentUIRegistry.register('Praeco', 'sources', SourcesPanel); * * // In host SvelteKit app * import { AgentUIRegistry } from '@happyvertical/smrt-agents/ui'; * import '@happyvertical/praeco/admin'; // Registers components * * const Component = AgentUIRegistry.get('Praeco', 'sources'); * ``` */ declare global { var __smrtAgentUIRegistry: AgentUIComponentRegistry | undefined; } export declare const AgentUIRegistry: AgentUIComponentRegistry; /** * What an agent's `./admin` entry point must export. * * This is the contract between agent packages and host apps. * Instead of registering individual slot components, agents export * a single root component that handles its own sub-navigation. * * @example * ```typescript * // In agent package: histrio/src/ui/admin/index.ts * export { default } from './AdminRoot.svelte'; * export { createAPIClient } from '../types.js'; * export const navItems: AgentAdminNavItem[] = [ * { id: 'characters', label: 'Characters', icon: 'users', order: 1 }, * { id: 'performers', label: 'Performers', icon: 'mic', order: 2 }, * ]; * ``` */ export interface AgentAdminExport { /** Root admin component — renders all panels, handles its own sub-navigation */ default?: ComponentType; /** Create a typed API client for this agent */ createAPIClient?: (baseUrl: string) => unknown; /** Navigation items for tabs/sidebar within the agent admin */ navItems?: AgentAdminNavItem[]; } /** * Props passed to the root admin component */ export interface AgentAdminRootProps { /** Typed API client created by the agent's own factory */ apiClient: unknown; /** Which panel to show (from URL hash, e.g., 'sources') */ activePanel?: string; /** Called when user navigates within the agent */ onNavigate?: (panelId: string) => void; /** Whether admin is in read-only mode */ readonly?: boolean; } /** * Navigation item within an agent's admin UI */ export interface AgentAdminNavItem { /** Matches hash fragment and panel ID */ id: string; /** Display label */ label: string; /** Icon identifier */ icon?: string; /** Display order (lower numbers first) */ order?: number; } /** * Agents module UI slots (for ModuleUIRegistry) */ export declare const AGENTS_UI_SLOTS: Record; /** * Agents module metadata */ export declare const AGENTS_MODULE_META: SmrtModuleMeta; //# sourceMappingURL=ui.d.ts.map