@rizom/brain 0.2.0-alpha.205 → 0.2.0-alpha.207

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,7 +47,7 @@
47
47
  "'use strict';\n\nconst getEngine = require('./engine');\nconst defaults = require('./defaults');\n\nmodule.exports = function(language, str, options) {\n const opts = defaults(options);\n const engine = getEngine(language, opts);\n if (typeof engine.parse !== 'function') {\n throw new TypeError('expected \"' + language + '.parse\" to be a function');\n }\n return engine.parse(str, opts);\n};\n",
48
48
  "'use strict';\n\nconst fs = require('fs');\nconst sections = require('section-matter');\nconst defaults = require('./lib/defaults');\nconst stringify = require('./lib/stringify');\nconst excerpt = require('./lib/excerpt');\nconst engines = require('./lib/engines');\nconst toFile = require('./lib/to-file');\nconst parse = require('./lib/parse');\nconst utils = require('./lib/utils');\n\n/**\n * Takes a string or object with `content` property, extracts\n * and parses front-matter from the string, then returns an object\n * with `data`, `content` and other [useful properties](#returned-object).\n *\n * ```js\n * const matter = require('gray-matter');\n * console.log(matter('---\\ntitle: Home\\n---\\nOther stuff'));\n * //=> { data: { title: 'Home'}, content: 'Other stuff' }\n * ```\n * @param {Object|String} `input` String, or object with `content` string\n * @param {Object} `options`\n * @return {Object}\n * @api public\n */\n\nfunction matter(input, options) {\n if (input === '') {\n return { data: {}, content: input, excerpt: '', orig: input };\n }\n\n let file = toFile(input);\n const cached = matter.cache[file.content];\n\n if (!options) {\n if (cached) {\n file = Object.assign({}, cached);\n file.orig = cached.orig;\n return file;\n }\n\n // only cache if there are no options passed. if we cache when options\n // are passed, we would need to also cache options values, which would\n // negate any performance benefits of caching\n matter.cache[file.content] = file;\n }\n\n return parseMatter(file, options);\n}\n\n/**\n * Parse front matter\n */\n\nfunction parseMatter(file, options) {\n const opts = defaults(options);\n const open = opts.delimiters[0];\n const close = '\\n' + opts.delimiters[1];\n let str = file.content;\n\n if (opts.language) {\n file.language = opts.language;\n }\n\n // get the length of the opening delimiter\n const openLen = open.length;\n if (!utils.startsWith(str, open, openLen)) {\n excerpt(file, opts);\n return file;\n }\n\n // if the next character after the opening delimiter is\n // a character from the delimiter, then it's not a front-\n // matter delimiter\n if (str.charAt(openLen) === open.slice(-1)) {\n return file;\n }\n\n // strip the opening delimiter\n str = str.slice(openLen);\n const len = str.length;\n\n // use the language defined after first delimiter, if it exists\n const language = matter.language(str, opts);\n if (language.name) {\n file.language = language.name;\n str = str.slice(language.raw.length);\n }\n\n // get the index of the closing delimiter\n let closeIndex = str.indexOf(close);\n if (closeIndex === -1) {\n closeIndex = len;\n }\n\n // get the raw front-matter block\n file.matter = str.slice(0, closeIndex);\n\n const block = file.matter.replace(/^\\s*#[^\\n]+/gm, '').trim();\n if (block === '') {\n file.isEmpty = true;\n file.empty = file.content;\n file.data = {};\n } else {\n\n // create file.data by parsing the raw file.matter block\n file.data = parse(file.language, file.matter, opts);\n }\n\n // update file.content\n if (closeIndex === len) {\n file.content = '';\n } else {\n file.content = str.slice(closeIndex + close.length);\n if (file.content[0] === '\\r') {\n file.content = file.content.slice(1);\n }\n if (file.content[0] === '\\n') {\n file.content = file.content.slice(1);\n }\n }\n\n excerpt(file, opts);\n\n if (opts.sections === true || typeof opts.section === 'function') {\n sections(file, opts.section);\n }\n return file;\n}\n\n/**\n * Expose engines\n */\n\nmatter.engines = engines;\n\n/**\n * Stringify an object to YAML or the specified language, and\n * append it to the given string. By default, only YAML and JSON\n * can be stringified. See the [engines](#engines) section to learn\n * how to stringify other languages.\n *\n * ```js\n * console.log(matter.stringify('foo bar baz', {title: 'Home'}));\n * // results in:\n * // ---\n * // title: Home\n * // ---\n * // foo bar baz\n * ```\n * @param {String|Object} `file` The content string to append to stringified front-matter, or a file object with `file.content` string.\n * @param {Object} `data` Front matter to stringify.\n * @param {Object} `options` [Options](#options) to pass to gray-matter and [js-yaml].\n * @return {String} Returns a string created by wrapping stringified yaml with delimiters, and appending that to the given string.\n * @api public\n */\n\nmatter.stringify = function(file, data, options) {\n if (typeof file === 'string') file = matter(file, options);\n return stringify(file, data, options);\n};\n\n/**\n * Synchronously read a file from the file system and parse\n * front matter. Returns the same object as the [main function](#matter).\n *\n * ```js\n * const file = matter.read('./content/blog-post.md');\n * ```\n * @param {String} `filepath` file path of the file to read.\n * @param {Object} `options` [Options](#options) to pass to gray-matter.\n * @return {Object} Returns [an object](#returned-object) with `data` and `content`\n * @api public\n */\n\nmatter.read = function(filepath, options) {\n const str = fs.readFileSync(filepath, 'utf8');\n const file = matter(str, options);\n file.path = filepath;\n return file;\n};\n\n/**\n * Returns true if the given `string` has front matter.\n * @param {String} `string`\n * @param {Object} `options`\n * @return {Boolean} True if front matter exists.\n * @api public\n */\n\nmatter.test = function(str, options) {\n return utils.startsWith(str, defaults(options).delimiters[0]);\n};\n\n/**\n * Detect the language to use, if one is defined after the\n * first front-matter delimiter.\n * @param {String} `string`\n * @param {Object} `options`\n * @return {Object} Object with `raw` (actual language string), and `name`, the language with whitespace trimmed\n */\n\nmatter.language = function(str, options) {\n const opts = defaults(options);\n const open = opts.delimiters[0];\n\n if (matter.test(str)) {\n str = str.slice(open.length);\n }\n\n const language = str.slice(0, str.search(/\\r?\\n/));\n return {\n raw: language,\n name: language ? language.trim() : ''\n };\n};\n\n/**\n * Expose `matter`\n */\n\nmatter.cache = {};\nmatter.clearCache = function() {\n matter.cache = {};\n};\nmodule.exports = matter;\n",
49
49
  "import { z } from \"@brains/utils/zod\";\n\nconst canonicalContentVisibilitySchema: z.ZodEnum<{\n public: \"public\";\n shared: \"shared\";\n restricted: \"restricted\";\n}> = z.enum([\"public\", \"shared\", \"restricted\"]);\n\nexport type ContentVisibility = z.infer<\n typeof canonicalContentVisibilitySchema\n>;\nexport type RawContentVisibility = ContentVisibility | \"private\";\n\nexport const contentVisibilitySchema: z.ZodPipe<\n z.ZodOptional<\n z.ZodUnion<\n readonly [\n typeof canonicalContentVisibilitySchema,\n z.ZodLiteral<\"private\">,\n ]\n >\n >,\n z.ZodTransform<ContentVisibility, RawContentVisibility | undefined>\n> = z\n .union([canonicalContentVisibilitySchema, z.literal(\"private\")])\n .optional()\n .transform((value): ContentVisibility => {\n if (value === undefined) return \"public\";\n if (value === \"private\") return \"restricted\";\n return value;\n });\n\nexport function normalizeContentVisibility(\n visibility: RawContentVisibility | undefined,\n): ContentVisibility {\n return contentVisibilitySchema.parse(visibility);\n}\n\nconst visibleContentVisibilitiesByScope: Record<\n ContentVisibility,\n ContentVisibility[]\n> = {\n public: [\"public\"],\n shared: [\"public\", \"shared\"],\n restricted: [\"public\", \"shared\", \"restricted\"],\n};\n\nexport function getVisibleContentVisibilities(\n scope: ContentVisibility,\n): ContentVisibility[] {\n return visibleContentVisibilitiesByScope[scope];\n}\n\nexport function isVisibleWithinScope(\n visibility: ContentVisibility | undefined,\n scope: ContentVisibility,\n): boolean {\n return getVisibleContentVisibilities(scope).includes(visibility ?? \"public\");\n}\n\n/**\n * Map a caller's permission level to the content-visibility scope they may see.\n * public → public (only public content)\n * trusted → shared (public + shared)\n * anchor → restricted (public + shared + restricted)\n *\n * Defaults to \"public\" when no permission level is provided, so missing\n * context fails closed.\n */\nexport function permissionToVisibilityScope(\n level: \"anchor\" | \"trusted\" | \"public\" | undefined,\n): ContentVisibility {\n if (level === \"anchor\") return \"restricted\";\n if (level === \"trusted\") return \"shared\";\n return \"public\";\n}\n\n/**\n * Whether a caller at `level` is allowed to author or update an entity at\n * `visibility`. A user may only write content at a visibility they themselves\n * can read — otherwise they could ghost-write content into a higher trust\n * level than their permission, which is a write-side escalation vector.\n *\n * public → may write \"public\"\n * trusted → may write \"public\" | \"shared\"\n * anchor → may write \"public\" | \"shared\" | \"restricted\"\n */\nexport function canWriteVisibility(\n level: \"anchor\" | \"trusted\" | \"public\" | undefined,\n visibility: ContentVisibility,\n): boolean {\n return isVisibleWithinScope(visibility, permissionToVisibilityScope(level));\n}\n",
50
- "import { z } from \"@brains/utils/zod\";\nimport {\n contentVisibilitySchema,\n type ContentVisibility,\n type RawContentVisibility,\n} from \"./visibility\";\n\n/**\n * Entity type for unstructured notes (the \"note\" entity type).\n * Used as a sentinel for the default catch-all markdown file shape —\n * no typed frontmatter schema required, content is the entire file body.\n */\nexport const NOTE_ENTITY_TYPE = \"note\";\n\n/**\n * Embedding job data - minimal data for job queue\n * Content is NOT stored to avoid large base64 data in job queue\n * (which would end up in dashboard hydration props JSON)\n * Handler fetches fresh content from entity when processing\n */\nexport interface EmbeddingJobData {\n id: string;\n entityType: string;\n /** Hash of content at job creation time - for staleness detection */\n contentHash: string;\n operation: \"create\" | \"update\";\n}\n\n/**\n * Options for entity mutation operations (create, update, upsert)\n */\nexport interface EntityMutationEventContext {\n conversationId?: string;\n channelId?: string;\n runId?: string;\n toolCallId?: string;\n}\n\nexport interface EntityJobOptions {\n priority?: number;\n maxRetries?: number;\n eventContext?: EntityMutationEventContext;\n}\n\nexport {\n contentVisibilitySchema,\n normalizeContentVisibility,\n getVisibleContentVisibilities,\n isVisibleWithinScope,\n permissionToVisibilityScope,\n canWriteVisibility,\n} from \"./visibility\";\nexport type { ContentVisibility, RawContentVisibility } from \"./visibility\";\n\n/**\n * Options for entity creation (extends EntityJobOptions with deduplication)\n */\nexport interface CreateEntityOptions extends EntityJobOptions {\n deduplicateId?: boolean;\n}\n\n/** Options for updating an existing entity. */\nexport interface UpdateEntityOptions extends EntityJobOptions {\n /** Apply only while the stored entity still has this content hash. */\n expectedContentHash?: string | undefined;\n}\n\n/**\n * Result of an entity mutation that triggers an embedding job.\n * When skipped is true, no DB write, event, or embedding job was produced.\n */\nexport interface EntityMutationResult {\n entityId: string;\n jobId: string;\n skipped: boolean;\n skipReason?: \"content-conflict\" | undefined;\n}\n\n/**\n * Input for adapter-validated direct creation from finalized markdown.\n */\nexport interface CreateEntityFromMarkdownInput {\n entityType: string;\n id: string;\n markdown: string;\n}\n\n/**\n * Data for storing an embedding for an entity\n */\nexport interface StoreEmbeddingData {\n entityId: string;\n entityType: string;\n embedding: Float32Array;\n contentHash: string;\n}\n\n/**\n * Base entity schema that all entities must extend\n */\nexport const baseEntitySchema: z.ZodObject<{\n id: z.ZodString;\n entityType: z.ZodString;\n content: z.ZodString;\n created: z.ZodString;\n updated: z.ZodString;\n visibility: typeof contentVisibilitySchema;\n metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;\n contentHash: z.ZodString;\n}> = z.object({\n id: z.string(),\n entityType: z.string(),\n content: z.string(),\n created: z.string().datetime(),\n updated: z.string().datetime(),\n visibility: contentVisibilitySchema,\n metadata: z.record(z.string(), z.unknown()),\n contentHash: z.string(),\n});\n\nconst canonicalContentVisibilityParserSchema: z.ZodEnum<{\n public: \"public\";\n shared: \"shared\";\n restricted: \"restricted\";\n}> = z.enum([\"public\", \"shared\", \"restricted\"]);\n\n/** Zod 4-owned parser base for entity schemas whose registration slot is structural. */\nexport const baseEntityParserSchema: z.ZodObject<{\n id: z.ZodString;\n entityType: z.ZodString;\n content: z.ZodString;\n created: z.ZodString;\n updated: z.ZodString;\n visibility: z.ZodPipe<\n z.ZodOptional<\n z.ZodUnion<\n readonly [\n typeof canonicalContentVisibilityParserSchema,\n z.ZodLiteral<\"private\">,\n ]\n >\n >,\n z.ZodTransform<ContentVisibility, RawContentVisibility | undefined>\n >;\n metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;\n contentHash: z.ZodString;\n}> = z.object({\n id: z.string(),\n entityType: z.string(),\n content: z.string(),\n created: z.string().datetime(),\n updated: z.string().datetime(),\n visibility: z\n .union([canonicalContentVisibilityParserSchema, z.literal(\"private\")])\n .optional()\n .transform((value): ContentVisibility => {\n if (value === undefined) return \"public\";\n if (value === \"private\") return \"restricted\";\n return value;\n }),\n metadata: z.record(z.string(), z.unknown()),\n contentHash: z.string(),\n});\n\n/** Shared empty frontmatter schema for entity types with no typed frontmatter. */\nexport const emptyFrontmatterSchema: z.ZodObject<Record<string, never>> =\n z.object({});\n\nexport type EntitySchema<T> = z.ZodType<T, unknown>;\n/** @deprecated Use EntitySchema<T>. */\nexport type EntitySchemaParser<T> = EntitySchema<T>;\n\nexport type UnknownEntitySchema = EntitySchema<unknown>;\nexport type FrontmatterSchema = z.ZodObject<z.ZodRawShape>;\n\n/**\n * Base entity type - generic to support typed metadata\n * TMetadata defaults to Record<string, unknown> for backward compatibility\n */\nexport interface BaseEntity<TMetadata = Record<string, unknown>> {\n id: string;\n entityType: string;\n content: string;\n created: string;\n updated: string;\n visibility: ContentVisibility;\n metadata: TMetadata;\n /** SHA256 hash of content for change detection */\n contentHash: string;\n}\n\n/**\n * Entity input type for creation - allows partial entities with optional system fields\n * contentHash is excluded because it's computed automatically by the entity service\n */\nexport type EntityInput<T extends BaseEntity> = Omit<\n T,\n \"id\" | \"created\" | \"updated\" | \"contentHash\" | \"visibility\"\n> & {\n id?: string;\n created?: string;\n updated?: string;\n visibility?: RawContentVisibility;\n};\n\n/**\n * Search result type\n */\nexport interface SearchResult<T extends BaseEntity = BaseEntity> {\n entity: T;\n score: number;\n excerpt: string;\n}\n\n/**\n * Normalized system_create input shape used by plugin create interceptors.\n */\nexport interface CreateCoverImageInput {\n generate?: boolean | undefined;\n prompt?: string | undefined;\n}\n\nexport interface CreateFromAttachmentInput {\n kind: \"entity-attachment\";\n sourceEntityType: string;\n sourceEntityId: string;\n attachmentType: string;\n}\n\nexport interface CreateFromUploadInput {\n kind: \"upload\";\n id: string;\n}\n\nexport interface CreateFromConversationMessageInput {\n kind: \"conversation-message\";\n messageId?: string | undefined;\n}\n\nexport type CreateFromInput =\n | CreateFromAttachmentInput\n | CreateFromUploadInput\n | CreateFromConversationMessageInput;\n\nexport type CreateTransform = \"extract-markdown\" | \"preserve\";\n\nexport interface CreateInput {\n entityType: string;\n prompt?: string;\n title?: string;\n content?: string;\n url?: string;\n from?: CreateFromInput;\n transform?: CreateTransform;\n replace?: boolean;\n sourceEntityType?: string;\n sourceEntityId?: string;\n sourceEntityIds?: string[];\n targetEntityType?: string;\n targetEntityId?: string;\n coverImage?: boolean | CreateCoverImageInput;\n}\n\n/**\n * Minimal caller context forwarded to plugin create interceptors.\n */\nexport interface CreateExecutionContext {\n interfaceType: string;\n userId: string;\n channelId?: string;\n channelName?: string;\n}\n\n/**\n * Result returned to system_create when a plugin fully handles creation.\n */\nexport const createResultAttachmentSchema: z.ZodObject<{\n mediaType: z.ZodString;\n url: z.ZodString;\n downloadUrl: z.ZodOptional<z.ZodString>;\n previewUrl: z.ZodOptional<z.ZodString>;\n filename: z.ZodOptional<z.ZodString>;\n sizeBytes: z.ZodOptional<z.ZodNumber>;\n source: z.ZodOptional<\n z.ZodObject<{\n entityType: z.ZodOptional<z.ZodString>;\n entityId: z.ZodOptional<z.ZodString>;\n attachmentType: z.ZodOptional<z.ZodString>;\n }>\n >;\n}> = z.object({\n mediaType: z.string(),\n url: z.string(),\n downloadUrl: z.string().optional(),\n previewUrl: z.string().optional(),\n filename: z.string().optional(),\n sizeBytes: z.number().optional(),\n source: z\n .object({\n entityType: z.string().optional(),\n entityId: z.string().optional(),\n attachmentType: z.string().optional(),\n })\n .optional(),\n});\n\nexport type CreateResultAttachment = z.infer<\n typeof createResultAttachmentSchema\n>;\n\nexport type CreateResult =\n | {\n success: true;\n data: {\n entityId?: string;\n jobId?: string;\n status: string;\n attachment?: CreateResultAttachment;\n };\n }\n | { success: false; error: string };\n\n/**\n * Plugin create interceptors can either fully handle creation,\n * or continue with a rewritten normalized input.\n */\nexport type CreateInterceptionResult =\n | { kind: \"handled\"; result: CreateResult }\n | { kind: \"continue\"; input: CreateInput };\n\nexport type CreateInterceptor = (\n input: CreateInput,\n executionContext: CreateExecutionContext,\n) => Promise<CreateInterceptionResult>;\n\nexport interface UploadSaveInput {\n upload: CreateFromUploadInput;\n title?: string;\n}\n\nexport type UploadSaveHandler = (\n input: UploadSaveInput,\n executionContext: CreateExecutionContext,\n) => Promise<CreateResult>;\n\nexport interface UploadSaveHandlerRegistration {\n entityType: string;\n mediaTypes: string[];\n handler: UploadSaveHandler;\n}\n\n/**\n * Called before an entity is persisted (on create or update). Throws to reject\n * the write with an operator-facing error. Use this for cross-entity invariants\n * the per-entity Zod schema cannot express.\n */\nexport type PersistValidator<T extends BaseEntity = BaseEntity> = (\n entity: T,\n context: { operation: \"create\" | \"update\" },\n) => Promise<void>;\n\n/**\n * Minimal event bus contract used by entity-service for lifecycle events.\n * Kept structural to avoid coupling this package to a concrete messaging service.\n */\nexport interface EntityEventBus {\n send(request: {\n type: string;\n payload: Record<string, unknown>;\n sender: string;\n target?: string;\n metadata?: Record<string, unknown>;\n broadcast?: boolean;\n }): Promise<unknown>;\n}\n\n/**\n * Interface for entity adapter - handles conversion between entities and markdown\n * following the hybrid storage model\n *\n * @template TEntity - The full entity type\n * @template TMetadata - The metadata type (defaults to Record<string, unknown>)\n */\nexport interface EntityAdapter<\n TEntity extends BaseEntity<TMetadata>,\n TMetadata = Record<string, unknown>,\n> {\n entityType: string;\n\n /**\n * One declarative sentence describing what this entity type is. This is the\n * data the model reads to select `entityType`, replacing hardcoded example\n * phrasings in system instructions. Required: every type must define itself.\n */\n purpose: string;\n\n schema: EntitySchema<TEntity>;\n\n // Convert entity to markdown content (may include frontmatter for entity-specific fields)\n toMarkdown(entity: TEntity): string;\n\n // Extract entity-specific fields from markdown\n // Returns Partial<TEntity> as core fields come from database\n fromMarkdown(markdown: string): Partial<TEntity>;\n\n // Extract metadata from entity for search/filtering - now strongly typed\n extractMetadata(entity: TEntity): TMetadata;\n\n // Parse frontmatter metadata from markdown\n parseFrontMatter<TFrontmatter>(\n markdown: string,\n schema: { parse(data: unknown): TFrontmatter },\n ): TFrontmatter;\n\n // Generate frontmatter for markdown\n generateFrontMatter(entity: TEntity): string;\n\n /** Optional: Zod schema for frontmatter fields. Used by CMS config generation. */\n frontmatterSchema?: z.ZodObject<z.ZodRawShape>;\n\n /** Optional: Declares this entity type is a singleton (one file, e.g., identity/identity.md). Used by CMS to generate files collection. */\n isSingleton?: boolean;\n\n /** Optional: Whether this entity has a free-form markdown body below frontmatter. Defaults to true. When false, CMS omits the body widget. */\n hasBody?: boolean;\n\n /** Returns a markdown body template with section headings for this entity type. Empty string for free-form entities. */\n getBodyTemplate(): string;\n\n /** Optional: Declares that this entity type supports cover images via coverImageId in frontmatter */\n supportsCoverImage?: boolean;\n\n /**\n * Optional: the `metadata.status` values that count as published for\n * `publishedOnly` queries (production site builds). Declaring this makes the\n * list exact — entities without a status are NOT published. When absent, the\n * default lifecycle semantics apply: status `published`, `active`, or no\n * status at all.\n */\n publishedStatuses?: string[];\n\n /** Optional: Extract coverImageId from entity content/frontmatter */\n getCoverImageId?(entity: TEntity): string | undefined;\n\n /**\n * Optional: build the markdown content and metadata for a queued-generation stub.\n * When undefined, this entity type does not support prompt-based queued creation\n * via system_create; the tool will reject the call rather than silently degrade.\n * The returned metadata must satisfy this entity's metadata schema (with\n * status set to \"generating\"); central code only stamps id/timestamps/visibility.\n */\n buildStub?(input: { id: string; title: string }): {\n content: string;\n metadata: TMetadata;\n };\n}\n\n/**\n * Sort field specification for multi-field sorting\n */\nexport interface SortField {\n /** Field to sort by - \"created\", \"updated\", or a metadata field name */\n field: string;\n /** Sort direction */\n direction: \"asc\" | \"desc\";\n /** Sort NULL values before non-NULL values (default: false / SQLite default) */\n nullsFirst?: boolean;\n}\n\n/**\n * List entities options\n * Generic over metadata type for type-safe filtering\n */\nexport interface ListOptions<TMetadata = Record<string, unknown>> {\n limit?: number;\n offset?: number;\n /** Multi-field sorting - supports system fields (created, updated) and metadata fields */\n sortFields?: SortField[];\n filter?: {\n // Typed metadata filter - partial match on metadata fields\n metadata?: Partial<TMetadata>;\n visibilityScope?: ContentVisibility;\n };\n /** Filter to only entities with metadata.status = \"published\" */\n publishedOnly?: boolean;\n}\n\n/**\n * Search options\n */\nexport interface SearchOptions {\n limit?: number;\n offset?: number;\n types?: string[];\n excludeTypes?: string[];\n sortBy?: \"relevance\" | \"created\" | \"updated\";\n sortDirection?: \"asc\" | \"desc\";\n /** Score multipliers per entity type - applied after initial search */\n weight?: Record<string, number>;\n visibilityScope?: ContentVisibility;\n /** Include queued/failed generation stubs in search results (default: false) */\n includeUngenerated?: boolean;\n /** Minimum relevance score to return. Omit for no score cutoff. */\n minScore?: number;\n}\n\n/**\n * Configuration for entity type registration\n */\nexport interface EntityTypeConfig {\n /** Score multiplier for search results (default: 1.0) */\n weight?: number;\n /** Whether to generate embeddings for this entity type (default: true).\n * Set to false for entity types with non-textual content (e.g., images). */\n embeddable?: boolean;\n /** Whether this entity type may be used as source material for derived projections (default: true).\n * Set to false for projection outputs that would create feedback loops. */\n projectionSource?: boolean;\n /** Publish semantics for status-bearing entity types. Statuses listed here\n * represent publication commitment/execution states and require the\n * `publish` entity action when entered or modified. */\n publish?: {\n publishStatuses: string[];\n };\n}\n\n/**\n * Core entity service interface for read-only operations\n * Used by core plugins that need entity access but shouldn't modify entities\n */\nexport interface GetEntityRequest {\n entityType: string;\n id: string;\n /**\n * Optional visibility scope. Undefined fails closed to \"public\" — callers\n * with elevated access must opt up explicitly.\n */\n visibilityScope?: ContentVisibility;\n}\n\nexport type GetEntityRawRequest = GetEntityRequest;\n\nexport interface ListEntitiesRequest {\n entityType: string;\n options?: ListOptions | undefined;\n}\n\nexport interface CountEntitiesRequest {\n entityType: string;\n options?: Pick<ListOptions, \"publishedOnly\" | \"filter\"> | undefined;\n}\n\nexport interface CreateEntityRequest<T extends BaseEntity> {\n entity: EntityInput<T>;\n options?: CreateEntityOptions | undefined;\n}\n\nexport interface CreateEntityFromMarkdownRequest {\n input: CreateEntityFromMarkdownInput;\n options?: CreateEntityOptions | undefined;\n}\n\nexport interface UpdateEntityRequest<T extends BaseEntity> {\n entity: T;\n options?: UpdateEntityOptions | undefined;\n}\n\nexport interface DeleteEntityRequest {\n entityType: string;\n id: string;\n}\n\nexport interface UpsertEntityRequest<T extends BaseEntity> {\n entity: T;\n options?: EntityJobOptions | undefined;\n}\n\nexport interface EntitySearchRequest {\n query: string;\n options?: SearchOptions | undefined;\n}\n\nexport interface SearchWithDistancesRequest {\n query: string;\n}\n\nexport interface SemanticEntityReference {\n entityId: string;\n entityType: string;\n}\n\nexport interface ProjectSemanticSpaceRequest {\n /** Entity types to include as projected points. Empty or omitted includes all types. */\n types?: string[];\n /** Optional entity used as the semantic origin. Missing origins fall back to the point centroid. */\n origin?: SemanticEntityReference;\n /** Include pairwise neighbors at or below this cosine distance. */\n maxNeighborDistance?: number;\n /** Undefined fails closed to public-only visibility. */\n visibilityScope?: ContentVisibility;\n}\n\nexport interface SemanticSpacePoint extends SemanticEntityReference {\n /** Coordinates on the first two principal components of the semantic space. */\n coordinates: [number, number];\n /** Cosine distance from the requested origin or the fallback centroid. */\n distanceToOrigin: number;\n}\n\nexport interface SemanticSpaceNeighbor {\n source: SemanticEntityReference;\n target: SemanticEntityReference;\n distance: number;\n}\n\nexport type SemanticSpaceOrigin =\n ({ kind: \"entity\" } & SemanticEntityReference) | { kind: \"centroid\" };\n\nexport interface SemanticSpaceDistanceRange {\n min: number;\n max: number;\n}\n\nexport interface SemanticSpaceProjection {\n origin: SemanticSpaceOrigin;\n points: SemanticSpacePoint[];\n neighbors: SemanticSpaceNeighbor[];\n /** Observed origin-distance extent for projection-independent scaling. */\n distanceRange: SemanticSpaceDistanceRange;\n}\n\n/**\n * Context passed to all DataSource operations\n * Contains internal state that should not be mixed with user query parameters\n */\nexport interface BaseDataSourceContext {\n /**\n * Whether to filter to only published/complete content\n * Set by site-builder: true for production, false for preview\n */\n publishedOnly?: boolean;\n\n /**\n * Scoped entity service that auto-applies publishedOnly filter\n * Datasources should use this instead of their injected entityService\n * to ensure consistent filtering behavior across environments\n */\n entityService: EntityService;\n}\n\nexport type DataSourceSchema<T> = z.ZodType<T, unknown>;\n\n/**\n * DataSource Interface\n *\n * Provides data for templates through fetch, generate, or transform operations.\n * DataSources are registered in the DataSourceRegistry and referenced by templates\n * via their dataSourceId property.\n */\nexport interface DataSource {\n /**\n * Unique identifier for this data source\n */\n id: string;\n\n /**\n * Human-readable name for this data source\n */\n name: string;\n\n /**\n * Optional description of what this data source provides\n */\n description?: string;\n\n /**\n * Optional: Fetch existing data\n * Used by data sources that aggregate or retrieve data (e.g., dashboard stats, API data)\n * DataSources validate output using the provided schema\n * @param query - Query parameters for fetching data\n * @param outputSchema - Schema for validating output data\n * @param context - Context with environment\n */\n fetch?: <T>(\n query: unknown,\n outputSchema: z.ZodSchema<T>,\n context: BaseDataSourceContext,\n ) => Promise<T>;\n\n /**\n * Optional: Generate new content\n * Used by data sources that create content (e.g., AI-generated content, reports)\n */\n generate?: <T>(request: unknown, schema: z.ZodSchema<T>) => Promise<T>;\n\n /**\n * Optional: Transform content between formats\n * Used by data sources that convert content (e.g., markdown to HTML, data formatting)\n */\n transform?: <T>(\n content: unknown,\n format: string,\n schema: z.ZodSchema<T>,\n ) => Promise<T>;\n}\n\n/**\n * DataSource capabilities for discovery and validation\n */\nexport interface DataSourceCapabilities {\n canFetch: boolean;\n canGenerate: boolean;\n canTransform: boolean;\n}\n\nexport interface ICoreEntityService {\n // Read-only operations\n getEntity<T extends BaseEntity>(request: GetEntityRequest): Promise<T | null>;\n\n /**\n * Get entity without content resolution (raw)\n * Used internally to avoid recursion when resolving image references\n */\n getEntityRaw<T extends BaseEntity>(\n request: GetEntityRawRequest,\n ): Promise<T | null>;\n\n listEntities<T extends BaseEntity>(\n request: ListEntitiesRequest,\n ): Promise<T[]>;\n\n search<T extends BaseEntity = BaseEntity>(\n request: EntitySearchRequest,\n ): Promise<SearchResult<T>[]>;\n\n /** Project visible entities into a provider-independent semantic space. */\n projectSemanticSpace(\n request: ProjectSemanticSpaceRequest,\n ): Promise<SemanticSpaceProjection>;\n\n // Entity type information\n getEntityTypes(): string[];\n hasEntityType(type: string): boolean;\n\n // Entity counts\n countEntities(request: CountEntitiesRequest): Promise<number>;\n /**\n * Group counts by entity type. Fails closed: undefined visibilityScope\n * filters to public-only counts so aggregate insights cannot reveal\n * non-public entity existence.\n */\n getEntityCounts(\n visibilityScope?: ContentVisibility,\n ): Promise<Array<{ entityType: string; count: number }>>;\n\n /** Get configuration for a specific entity type */\n getEntityTypeConfig(type: string): EntityTypeConfig;\n\n /** Get weight map for all registered entity types with non-default weights */\n getWeightMap(): Record<string, number>;\n}\n\n/**\n * Entity service interface for managing brain entities\n */\nexport interface IEntitiesNamespace {\n /** Register a new entity type with schema and adapter */\n register<TEntity extends BaseEntity>(\n entityType: string,\n schema: EntitySchema<TEntity>,\n adapter: EntityAdapter<TEntity>,\n config?: EntityTypeConfig,\n ): void;\n\n /**\n * Get the adapter for an entity type.\n *\n * Returns the structural `EntityAdapter<BaseEntity>` view — namespace\n * consumers don't narrow by entity type. For typed access tied to a\n * specific `TEntity`, use the underlying `EntityRegistry.getAdapter<T>`\n * directly (see `entity-serializer.ts`).\n */\n getAdapter(entityType: string): EntityAdapter<BaseEntity> | undefined;\n\n /** Extend an adapter's frontmatterSchema with additional fields */\n extendFrontmatterSchema(\n type: string,\n extension: z.ZodObject<z.ZodRawShape>,\n ): void;\n\n /** Get effective frontmatter schema (base + extensions) for an entity type */\n getEffectiveFrontmatterSchema(\n type: string,\n ): z.ZodObject<z.ZodRawShape> | undefined;\n\n /** Update an existing entity */\n update<TEntity extends BaseEntity>(\n entity: TEntity,\n ): Promise<{ entityId: string; jobId: string }>;\n\n /** Register a data source for dynamic content */\n registerDataSource(dataSource: DataSource): void;\n\n /** Register a create interceptor for this plugin's entity type */\n registerCreateInterceptor(\n entityType: string,\n interceptor: CreateInterceptor,\n ): void;\n\n /** Register a raw-upload durable save handler for this plugin's entity type */\n registerUploadSaveHandler(registration: UploadSaveHandlerRegistration): void;\n\n /** Look up the registered upload-save handler claiming a media type */\n getUploadSaveHandler(\n mediaType: string,\n ): UploadSaveHandlerRegistration | undefined;\n}\n\nexport interface EmbeddingBackfillResult {\n queued: number;\n skipped: number;\n}\n\nexport interface EmbeddingFailureReference {\n entityId: string;\n entityType: string;\n contentHash: string;\n}\n\nexport interface EmbeddingIndexStats {\n missingEmbeddings: number;\n staleEmbeddings: number;\n failedEmbeddings: number;\n /** Entities whose type generates embeddings (non-embeddable types excluded). */\n embeddableEntities: number;\n /** Embeddable entities whose embedding is present and current. */\n embeddedEntities: number;\n}\n\nexport interface IndexReadinessOptions {\n /** Stop polling after this duration. Omit for an owning runtime monitor. */\n timeoutMs?: number;\n intervalMs?: number;\n /** Cancels readiness polling when the owning runtime shuts down. */\n signal?: AbortSignal;\n}\n\nexport interface IndexReadinessStatus extends EmbeddingIndexStats {\n ready: boolean;\n degraded: boolean;\n activeEmbeddingJobs: number;\n}\n\nexport interface EntityService extends ICoreEntityService {\n // Mutations\n createEntity<T extends BaseEntity>(\n request: CreateEntityRequest<T>,\n ): Promise<EntityMutationResult>;\n createEntityFromMarkdown(\n request: CreateEntityFromMarkdownRequest,\n ): Promise<EntityMutationResult>;\n updateEntity<T extends BaseEntity>(\n request: UpdateEntityRequest<T>,\n ): Promise<EntityMutationResult>;\n deleteEntity(request: DeleteEntityRequest): Promise<boolean>;\n upsertEntity<T extends BaseEntity>(\n request: UpsertEntityRequest<T>,\n ): Promise<EntityMutationResult & { created: boolean }>;\n storeEmbedding(data: StoreEmbeddingData): Promise<void>;\n backfillMissingEmbeddings(): Promise<EmbeddingBackfillResult>;\n isIndexReady(): boolean;\n awaitIndexReady(\n options: IndexReadinessOptions,\n ): Promise<IndexReadinessStatus>;\n\n // Serialization\n serializeEntity(entity: BaseEntity): string;\n deserializeEntity(markdown: string, entityType: string): Partial<BaseEntity>;\n\n // Counts\n countEmbeddings(): Promise<number>;\n\n // Diagnostics\n searchWithDistances(\n request: SearchWithDistancesRequest,\n ): Promise<Array<{ entityId: string; entityType: string; distance: number }>>;\n\n // Lifecycle\n initialize(): Promise<void>;\n\n // Job status\n getAsyncJobStatus(jobId: string): Promise<{\n status: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n error?: string;\n } | null>;\n}\n\n/**\n * Entity Registry interface for managing entity types and their schemas/adapters\n */\nexport interface EntityRegistry {\n registerEntityType<\n TEntity extends BaseEntity<TMetadata>,\n TMetadata = Record<string, unknown>,\n >(\n type: string,\n schema: UnknownEntitySchema,\n adapter: EntityAdapter<TEntity, TMetadata>,\n config?: EntityTypeConfig,\n ): void;\n\n /** Remove an entity type after failed plugin registration or shell teardown. */\n unregisterEntityType(type: string): void;\n\n getSchema(type: string): UnknownEntitySchema;\n\n getAdapter<\n TEntity extends BaseEntity<TMetadata>,\n TMetadata = Record<string, unknown>,\n >(\n type: string,\n ): EntityAdapter<TEntity, TMetadata>;\n\n hasEntityType(type: string): boolean;\n\n validateEntity(type: string, entity: unknown): BaseEntity;\n\n getAllEntityTypes(): string[];\n\n /** Get configuration for a specific entity type */\n getEntityTypeConfig(type: string): EntityTypeConfig;\n\n /** Get weight map for all registered entity types with non-default weights */\n getWeightMap(): Record<string, number>;\n\n registerCreateInterceptor(type: string, interceptor: CreateInterceptor): void;\n\n getCreateInterceptor(type: string): CreateInterceptor | undefined;\n\n registerUploadSaveHandler(registration: UploadSaveHandlerRegistration): void;\n\n getUploadSaveHandler(\n mediaType: string,\n ): UploadSaveHandlerRegistration | undefined;\n\n registerPersistValidator(type: string, validator: PersistValidator): void;\n\n getPersistValidator(type: string): PersistValidator | undefined;\n\n /**\n * Extend an adapter's frontmatterSchema with additional fields.\n * Used by plugins to add domain-specific fields (e.g., professional-site adds tagline to profile).\n * Extensions are merged into the effective schema returned by getEffectiveFrontmatterSchema().\n */\n extendFrontmatterSchema(\n type: string,\n extension: z.ZodObject<z.ZodRawShape>,\n ): void;\n\n /**\n * Get the effective frontmatter schema for an entity type,\n * with all registered extensions merged in.\n * Returns undefined if the adapter has no frontmatterSchema.\n */\n getEffectiveFrontmatterSchema(\n type: string,\n ): z.ZodObject<z.ZodRawShape> | undefined;\n}\n\n/**\n * Database configuration for entity service\n */\nexport type { DbConfig as EntityDbConfig } from \"@brains/contracts\";\n",
50
+ "import { z } from \"@brains/utils/zod\";\nimport {\n contentVisibilitySchema,\n type ContentVisibility,\n type RawContentVisibility,\n} from \"./visibility\";\n\n/**\n * Entity type for unstructured notes (the \"note\" entity type).\n * Used as a sentinel for the default catch-all markdown file shape —\n * no typed frontmatter schema required, content is the entire file body.\n */\nexport const NOTE_ENTITY_TYPE = \"note\";\n\n/**\n * Embedding job data - minimal data for job queue\n * Content is NOT stored to avoid large base64 data in job queue\n * (which would end up in dashboard hydration props JSON)\n * Handler fetches fresh content from entity when processing\n */\nexport interface EmbeddingJobData {\n id: string;\n entityType: string;\n /** Hash of content at job creation time - for staleness detection */\n contentHash: string;\n operation: \"create\" | \"update\";\n}\n\n/**\n * Options for entity mutation operations (create, update, upsert)\n */\nexport interface EntityMutationEventContext {\n conversationId?: string;\n channelId?: string;\n runId?: string;\n toolCallId?: string;\n}\n\nexport interface EntityJobOptions {\n priority?: number;\n maxRetries?: number;\n eventContext?: EntityMutationEventContext;\n}\n\nexport {\n contentVisibilitySchema,\n normalizeContentVisibility,\n getVisibleContentVisibilities,\n isVisibleWithinScope,\n permissionToVisibilityScope,\n canWriteVisibility,\n} from \"./visibility\";\nexport type { ContentVisibility, RawContentVisibility } from \"./visibility\";\n\n/**\n * Options for entity creation (extends EntityJobOptions with deduplication)\n */\nexport interface CreateEntityOptions extends EntityJobOptions {\n deduplicateId?: boolean;\n}\n\n/** Options for updating an existing entity. */\nexport interface UpdateEntityOptions extends EntityJobOptions {\n /** Apply only while the stored entity still has this content hash. */\n expectedContentHash?: string | undefined;\n}\n\n/**\n * Result of an entity mutation that triggers an embedding job.\n * When skipped is true, no DB write, event, or embedding job was produced.\n */\nexport interface EntityMutationResult {\n entityId: string;\n jobId: string;\n skipped: boolean;\n skipReason?: \"content-conflict\" | undefined;\n}\n\n/**\n * Input for adapter-validated direct creation from finalized markdown.\n */\nexport interface CreateEntityFromMarkdownInput {\n entityType: string;\n id: string;\n markdown: string;\n}\n\n/**\n * Data for storing an embedding for an entity\n */\nexport interface StoreEmbeddingData {\n entityId: string;\n entityType: string;\n embedding: Float32Array;\n contentHash: string;\n}\n\n/**\n * Base entity schema that all entities must extend\n */\nexport const baseEntitySchema: z.ZodObject<{\n id: z.ZodString;\n entityType: z.ZodString;\n content: z.ZodString;\n created: z.ZodString;\n updated: z.ZodString;\n visibility: typeof contentVisibilitySchema;\n metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;\n contentHash: z.ZodString;\n}> = z.object({\n id: z.string(),\n entityType: z.string(),\n content: z.string(),\n created: z.string().datetime(),\n updated: z.string().datetime(),\n visibility: contentVisibilitySchema,\n metadata: z.record(z.string(), z.unknown()),\n contentHash: z.string(),\n});\n\nconst canonicalContentVisibilityParserSchema: z.ZodEnum<{\n public: \"public\";\n shared: \"shared\";\n restricted: \"restricted\";\n}> = z.enum([\"public\", \"shared\", \"restricted\"]);\n\n/** Zod 4-owned parser base for entity schemas whose registration slot is structural. */\nexport const baseEntityParserSchema: z.ZodObject<{\n id: z.ZodString;\n entityType: z.ZodString;\n content: z.ZodString;\n created: z.ZodString;\n updated: z.ZodString;\n visibility: z.ZodPipe<\n z.ZodOptional<\n z.ZodUnion<\n readonly [\n typeof canonicalContentVisibilityParserSchema,\n z.ZodLiteral<\"private\">,\n ]\n >\n >,\n z.ZodTransform<ContentVisibility, RawContentVisibility | undefined>\n >;\n metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;\n contentHash: z.ZodString;\n}> = z.object({\n id: z.string(),\n entityType: z.string(),\n content: z.string(),\n created: z.string().datetime(),\n updated: z.string().datetime(),\n visibility: z\n .union([canonicalContentVisibilityParserSchema, z.literal(\"private\")])\n .optional()\n .transform((value): ContentVisibility => {\n if (value === undefined) return \"public\";\n if (value === \"private\") return \"restricted\";\n return value;\n }),\n metadata: z.record(z.string(), z.unknown()),\n contentHash: z.string(),\n});\n\n/** Shared empty frontmatter schema for entity types with no typed frontmatter. */\nexport const emptyFrontmatterSchema: z.ZodObject<Record<string, never>> =\n z.object({});\n\nexport type EntitySchema<T> = z.ZodType<T, unknown>;\n/** @deprecated Use EntitySchema<T>. */\nexport type EntitySchemaParser<T> = EntitySchema<T>;\n\nexport type UnknownEntitySchema = EntitySchema<unknown>;\nexport type FrontmatterSchema = z.ZodObject<z.ZodRawShape>;\n\n/**\n * Base entity type - generic to support typed metadata\n * TMetadata defaults to Record<string, unknown> for backward compatibility\n */\nexport interface BaseEntity<TMetadata = Record<string, unknown>> {\n id: string;\n entityType: string;\n content: string;\n created: string;\n updated: string;\n visibility: ContentVisibility;\n metadata: TMetadata;\n /** SHA256 hash of content for change detection */\n contentHash: string;\n}\n\n/**\n * Entity input type for creation - allows partial entities with optional system fields\n * contentHash is excluded because it's computed automatically by the entity service\n */\nexport type EntityInput<T extends BaseEntity> = Omit<\n T,\n \"id\" | \"created\" | \"updated\" | \"contentHash\" | \"visibility\"\n> & {\n id?: string;\n created?: string;\n updated?: string;\n visibility?: RawContentVisibility;\n};\n\n/**\n * Search result type\n */\nexport interface SearchResult<T extends BaseEntity = BaseEntity> {\n entity: T;\n score: number;\n excerpt: string;\n}\n\n/**\n * Normalized system_create input shape used by plugin create interceptors.\n */\nexport interface CreateCoverImageInput {\n generate?: boolean | undefined;\n prompt?: string | undefined;\n}\n\nexport interface CreateFromAttachmentInput {\n kind: \"entity-attachment\";\n sourceEntityType: string;\n sourceEntityId: string;\n attachmentType: string;\n}\n\nexport interface CreateFromUploadInput {\n kind: \"upload\";\n id: string;\n}\n\nexport interface CreateFromConversationMessageInput {\n kind: \"conversation-message\";\n messageId?: string | undefined;\n}\n\nexport type CreateFromInput =\n | CreateFromAttachmentInput\n | CreateFromUploadInput\n | CreateFromConversationMessageInput;\n\nexport type CreateTransform = \"extract-markdown\" | \"preserve\";\n\nexport interface CreateInput {\n entityType: string;\n prompt?: string;\n title?: string;\n content?: string;\n url?: string;\n from?: CreateFromInput;\n transform?: CreateTransform;\n replace?: boolean;\n sourceEntityType?: string;\n sourceEntityId?: string;\n sourceEntityIds?: string[];\n targetEntityType?: string;\n targetEntityId?: string;\n coverImage?: boolean | CreateCoverImageInput;\n}\n\n/**\n * Minimal caller context forwarded to plugin create interceptors.\n */\nexport interface CreateExecutionContext {\n interfaceType: string;\n userId: string;\n channelId?: string;\n channelName?: string;\n}\n\n/**\n * Result returned to system_create when a plugin fully handles creation.\n */\nexport const createResultAttachmentSchema: z.ZodObject<{\n mediaType: z.ZodString;\n url: z.ZodString;\n downloadUrl: z.ZodOptional<z.ZodString>;\n previewUrl: z.ZodOptional<z.ZodString>;\n filename: z.ZodOptional<z.ZodString>;\n sizeBytes: z.ZodOptional<z.ZodNumber>;\n source: z.ZodOptional<\n z.ZodObject<{\n entityType: z.ZodOptional<z.ZodString>;\n entityId: z.ZodOptional<z.ZodString>;\n attachmentType: z.ZodOptional<z.ZodString>;\n }>\n >;\n}> = z.object({\n mediaType: z.string(),\n url: z.string(),\n downloadUrl: z.string().optional(),\n previewUrl: z.string().optional(),\n filename: z.string().optional(),\n sizeBytes: z.number().optional(),\n source: z\n .object({\n entityType: z.string().optional(),\n entityId: z.string().optional(),\n attachmentType: z.string().optional(),\n })\n .optional(),\n});\n\nexport type CreateResultAttachment = z.infer<\n typeof createResultAttachmentSchema\n>;\n\nexport type CreateResult =\n | {\n success: true;\n data: {\n entityId?: string;\n jobId?: string;\n status: string;\n attachment?: CreateResultAttachment;\n };\n }\n | { success: false; error: string };\n\n/**\n * Plugin create interceptors can either fully handle creation,\n * or continue with a rewritten normalized input.\n */\nexport type CreateInterceptionResult =\n | { kind: \"handled\"; result: CreateResult }\n | { kind: \"continue\"; input: CreateInput };\n\nexport type CreateInterceptor = (\n input: CreateInput,\n executionContext: CreateExecutionContext,\n) => Promise<CreateInterceptionResult>;\n\nexport interface UploadSaveInput {\n upload: CreateFromUploadInput;\n title?: string;\n}\n\nexport type UploadSaveHandler = (\n input: UploadSaveInput,\n executionContext: CreateExecutionContext,\n) => Promise<CreateResult>;\n\nexport interface UploadSaveHandlerRegistration {\n entityType: string;\n mediaTypes: string[];\n handler: UploadSaveHandler;\n}\n\n/**\n * Called before an entity is persisted (on create or update). Throws to reject\n * the write with an operator-facing error. Use this for cross-entity invariants\n * the per-entity Zod schema cannot express.\n */\nexport type PersistValidator<T extends BaseEntity = BaseEntity> = (\n entity: T,\n context: { operation: \"create\" | \"update\" },\n) => Promise<void>;\n\n/**\n * Minimal event bus contract used by entity-service for lifecycle events.\n * Kept structural to avoid coupling this package to a concrete messaging service.\n */\nexport interface EntityEventBus {\n send(request: {\n type: string;\n payload: Record<string, unknown>;\n sender: string;\n target?: string;\n metadata?: Record<string, unknown>;\n broadcast?: boolean;\n }): Promise<unknown>;\n}\n\n/**\n * Interface for entity adapter - handles conversion between entities and markdown\n * following the hybrid storage model\n *\n * @template TEntity - The full entity type\n * @template TMetadata - The metadata type (defaults to Record<string, unknown>)\n */\nexport interface EntityAdapter<\n TEntity extends BaseEntity<TMetadata>,\n TMetadata = Record<string, unknown>,\n> {\n entityType: string;\n\n /**\n * One declarative sentence describing what this entity type is. This is the\n * data the model reads to select `entityType`, replacing hardcoded example\n * phrasings in system instructions. Required: every type must define itself.\n */\n purpose: string;\n\n schema: EntitySchema<TEntity>;\n\n // Convert entity to markdown content (may include frontmatter for entity-specific fields)\n toMarkdown(entity: TEntity): string;\n\n // Extract entity-specific fields from markdown\n // Returns Partial<TEntity> as core fields come from database\n fromMarkdown(markdown: string): Partial<TEntity>;\n\n // Extract metadata from entity for search/filtering - now strongly typed\n extractMetadata(entity: TEntity): TMetadata;\n\n // Parse frontmatter metadata from markdown\n parseFrontMatter<TFrontmatter>(\n markdown: string,\n schema: { parse(data: unknown): TFrontmatter },\n ): TFrontmatter;\n\n // Generate frontmatter for markdown\n generateFrontMatter(entity: TEntity): string;\n\n /** Optional: Zod schema for frontmatter fields. Used by CMS config generation. */\n frontmatterSchema?: z.ZodObject<z.ZodRawShape>;\n\n /** Optional: Declares this entity type is a singleton (one file, e.g., identity/identity.md). Used by CMS to generate files collection. */\n isSingleton?: boolean;\n\n /** Optional: Whether this entity has a free-form markdown body below frontmatter. Defaults to true. When false, CMS omits the body widget. */\n hasBody?: boolean;\n\n /** Returns a markdown body template with section headings for this entity type. Empty string for free-form entities. */\n getBodyTemplate(): string;\n\n /** Optional: Declares that this entity type supports cover images via coverImageId in frontmatter */\n supportsCoverImage?: boolean;\n\n /**\n * Optional: the `metadata.status` values that count as published for\n * `publishedOnly` queries (production site builds). Declaring this makes the\n * list exact — entities without a status are NOT published. When absent, the\n * default lifecycle semantics apply: status `published`, `active`, or no\n * status at all.\n */\n publishedStatuses?: string[];\n\n /** Optional: Extract coverImageId from entity content/frontmatter */\n getCoverImageId?(entity: TEntity): string | undefined;\n\n /**\n * Optional: build the markdown content and metadata for a queued-generation stub.\n * When undefined, this entity type does not support prompt-based queued creation\n * via system_create; the tool will reject the call rather than silently degrade.\n * The returned metadata must satisfy this entity's metadata schema (with\n * status set to \"generating\"); central code only stamps id/timestamps/visibility.\n */\n buildStub?(input: { id: string; title: string }): {\n content: string;\n metadata: TMetadata;\n };\n}\n\n/**\n * Sort field specification for multi-field sorting\n */\nexport interface SortField {\n /** Field to sort by - \"created\", \"updated\", or a metadata field name */\n field: string;\n /** Sort direction */\n direction: \"asc\" | \"desc\";\n /** Sort NULL values before non-NULL values (default: false / SQLite default) */\n nullsFirst?: boolean;\n}\n\n/**\n * List entities options\n * Generic over metadata type for type-safe filtering\n */\nexport interface ListOptions<TMetadata = Record<string, unknown>> {\n limit?: number;\n offset?: number;\n /** Multi-field sorting - supports system fields (created, updated) and metadata fields */\n sortFields?: SortField[];\n filter?: {\n // Typed metadata filter - partial match on metadata fields\n metadata?: Partial<TMetadata>;\n visibilityScope?: ContentVisibility;\n };\n /** Filter to only entities with metadata.status = \"published\" */\n publishedOnly?: boolean;\n}\n\n/**\n * Search options\n */\nexport interface SearchOptions {\n limit?: number;\n offset?: number;\n types?: string[];\n excludeTypes?: string[];\n sortBy?: \"relevance\" | \"created\" | \"updated\";\n sortDirection?: \"asc\" | \"desc\";\n /** Score multipliers per entity type - applied after initial search */\n weight?: Record<string, number>;\n visibilityScope?: ContentVisibility;\n /** Include queued/failed generation stubs in search results (default: false) */\n includeUngenerated?: boolean;\n /** Minimum relevance score to return. Omit for no score cutoff. */\n minScore?: number;\n}\n\n/**\n * Configuration for entity type registration\n */\nexport interface EntityTypeConfig {\n /** Score multiplier for search results (default: 1.0) */\n weight?: number;\n /** Whether to generate embeddings for this entity type (default: true).\n * Set to false for entity types with non-textual content (e.g., images). */\n embeddable?: boolean;\n /** Whether this entity type may be used as source material for derived projections (default: true).\n * Set to false for projection outputs that would create feedback loops. */\n projectionSource?: boolean;\n /** Publish semantics for status-bearing entity types. Statuses listed here\n * represent publication commitment/execution states and require the\n * `publish` entity action when entered or modified. */\n publish?: {\n publishStatuses: string[];\n };\n}\n\n/**\n * Core entity service interface for read-only operations\n * Used by core plugins that need entity access but shouldn't modify entities\n */\nexport interface GetEntityRequest {\n entityType: string;\n id: string;\n /**\n * Optional visibility scope. Undefined fails closed to \"public\" — callers\n * with elevated access must opt up explicitly.\n */\n visibilityScope?: ContentVisibility;\n}\n\nexport type GetEntityRawRequest = GetEntityRequest;\n\nexport interface ListEntitiesRequest {\n entityType: string;\n options?: ListOptions | undefined;\n}\n\nexport interface CountEntitiesRequest {\n entityType: string;\n options?: Pick<ListOptions, \"publishedOnly\" | \"filter\"> | undefined;\n}\n\nexport interface CreateEntityRequest<T extends BaseEntity> {\n entity: EntityInput<T>;\n options?: CreateEntityOptions | undefined;\n}\n\nexport interface CreateEntityFromMarkdownRequest {\n input: CreateEntityFromMarkdownInput;\n options?: CreateEntityOptions | undefined;\n}\n\nexport interface UpdateEntityRequest<T extends BaseEntity> {\n entity: T;\n options?: UpdateEntityOptions | undefined;\n}\n\nexport interface DeleteEntityRequest {\n entityType: string;\n id: string;\n}\n\nexport interface UpsertEntityRequest<T extends BaseEntity> {\n entity: T;\n options?: EntityJobOptions | undefined;\n}\n\nexport interface EntitySearchRequest {\n query: string;\n options?: SearchOptions | undefined;\n}\n\nexport interface SearchWithDistancesRequest {\n query: string;\n}\n\nexport interface SemanticEntityReference {\n entityId: string;\n entityType: string;\n}\n\nexport interface ProjectSemanticSpaceRequest {\n /** Entity types to include as projected points. Empty or omitted includes all types. */\n types?: string[];\n /** Optional entity used as the semantic origin. Missing origins fall back to the point centroid. */\n origin?: SemanticEntityReference;\n /** Include pairwise neighbors at or below this cosine distance. */\n maxNeighborDistance?: number;\n /** Undefined fails closed to public-only visibility. */\n visibilityScope?: ContentVisibility;\n}\n\nexport interface SemanticSpacePoint extends SemanticEntityReference {\n /** Coordinates on the first two principal components of the semantic space. */\n coordinates: [number, number];\n /** Cosine distance from the requested origin or the fallback centroid. */\n distanceToOrigin: number;\n}\n\nexport interface SemanticSpaceNeighbor {\n source: SemanticEntityReference;\n target: SemanticEntityReference;\n distance: number;\n}\n\nexport type SemanticSpaceOrigin =\n ({ kind: \"entity\" } & SemanticEntityReference) | { kind: \"centroid\" };\n\nexport interface SemanticSpaceDistanceRange {\n min: number;\n max: number;\n}\n\nexport interface SemanticSpaceProjection {\n origin: SemanticSpaceOrigin;\n points: SemanticSpacePoint[];\n neighbors: SemanticSpaceNeighbor[];\n /** Observed origin-distance extent for projection-independent scaling. */\n distanceRange: SemanticSpaceDistanceRange;\n}\n\n/**\n * Context passed to all DataSource operations\n * Contains internal state that should not be mixed with user query parameters\n */\nexport interface BaseDataSourceContext {\n /**\n * Whether to filter to only published/complete content\n * Set by site-builder: true for production, false for preview\n */\n publishedOnly?: boolean;\n\n /**\n * Scoped entity service that auto-applies publishedOnly filter\n * Datasources should use this instead of their injected entityService\n * to ensure consistent filtering behavior across environments\n */\n entityService: EntityService;\n}\n\nexport type DataSourceSchema<T> = z.ZodType<T, unknown>;\n\n/**\n * DataSource Interface\n *\n * Provides data for templates through fetch, generate, or transform operations.\n * DataSources are registered in the DataSourceRegistry and referenced by templates\n * via their dataSourceId property.\n */\nexport interface DataSource {\n /**\n * Unique identifier for this data source\n */\n id: string;\n\n /**\n * Human-readable name for this data source\n */\n name: string;\n\n /**\n * Optional description of what this data source provides\n */\n description?: string;\n\n /**\n * Optional: Fetch existing data\n * Used by data sources that aggregate or retrieve data (e.g., dashboard stats, API data)\n * DataSources validate output using the provided schema\n * @param query - Query parameters for fetching data\n * @param outputSchema - Schema for validating output data\n * @param context - Context with environment\n */\n fetch?: <T>(\n query: unknown,\n outputSchema: z.ZodSchema<T>,\n context: BaseDataSourceContext,\n ) => Promise<T>;\n\n /**\n * Optional: Generate new content\n * Used by data sources that create content (e.g., AI-generated content, reports)\n */\n generate?: <T>(request: unknown, schema: z.ZodSchema<T>) => Promise<T>;\n\n /**\n * Optional: Transform content between formats\n * Used by data sources that convert content (e.g., markdown to HTML, data formatting)\n */\n transform?: <T>(\n content: unknown,\n format: string,\n schema: z.ZodSchema<T>,\n ) => Promise<T>;\n}\n\n/**\n * DataSource capabilities for discovery and validation\n */\nexport interface DataSourceCapabilities {\n canFetch: boolean;\n canGenerate: boolean;\n canTransform: boolean;\n}\n\nexport interface ICoreEntityService {\n // Read-only operations\n getEntity<T extends BaseEntity>(request: GetEntityRequest): Promise<T | null>;\n\n /**\n * Get entity without content resolution (raw)\n * Used internally to avoid recursion when resolving image references\n */\n getEntityRaw<T extends BaseEntity>(\n request: GetEntityRawRequest,\n ): Promise<T | null>;\n\n listEntities<T extends BaseEntity>(\n request: ListEntitiesRequest,\n ): Promise<T[]>;\n\n search<T extends BaseEntity = BaseEntity>(\n request: EntitySearchRequest,\n ): Promise<SearchResult<T>[]>;\n\n /** Return embedded entities with raw cosine distance to a query. */\n searchWithDistances(\n request: SearchWithDistancesRequest,\n ): Promise<Array<{ entityId: string; entityType: string; distance: number }>>;\n\n /** Project visible entities into a provider-independent semantic space. */\n projectSemanticSpace(\n request: ProjectSemanticSpaceRequest,\n ): Promise<SemanticSpaceProjection>;\n\n // Entity type information\n getEntityTypes(): string[];\n hasEntityType(type: string): boolean;\n\n // Entity counts\n countEntities(request: CountEntitiesRequest): Promise<number>;\n /**\n * Group counts by entity type. Fails closed: undefined visibilityScope\n * filters to public-only counts so aggregate insights cannot reveal\n * non-public entity existence.\n */\n getEntityCounts(\n visibilityScope?: ContentVisibility,\n ): Promise<Array<{ entityType: string; count: number }>>;\n\n /** Get configuration for a specific entity type */\n getEntityTypeConfig(type: string): EntityTypeConfig;\n\n /** Get weight map for all registered entity types with non-default weights */\n getWeightMap(): Record<string, number>;\n}\n\n/**\n * Entity service interface for managing brain entities\n */\nexport interface IEntitiesNamespace {\n /** Register a new entity type with schema and adapter */\n register<TEntity extends BaseEntity>(\n entityType: string,\n schema: EntitySchema<TEntity>,\n adapter: EntityAdapter<TEntity>,\n config?: EntityTypeConfig,\n ): void;\n\n /**\n * Get the adapter for an entity type.\n *\n * Returns the structural `EntityAdapter<BaseEntity>` view — namespace\n * consumers don't narrow by entity type. For typed access tied to a\n * specific `TEntity`, use the underlying `EntityRegistry.getAdapter<T>`\n * directly (see `entity-serializer.ts`).\n */\n getAdapter(entityType: string): EntityAdapter<BaseEntity> | undefined;\n\n /** Extend an adapter's frontmatterSchema with additional fields */\n extendFrontmatterSchema(\n type: string,\n extension: z.ZodObject<z.ZodRawShape>,\n ): void;\n\n /** Get effective frontmatter schema (base + extensions) for an entity type */\n getEffectiveFrontmatterSchema(\n type: string,\n ): z.ZodObject<z.ZodRawShape> | undefined;\n\n /** Update an existing entity */\n update<TEntity extends BaseEntity>(\n entity: TEntity,\n ): Promise<{ entityId: string; jobId: string }>;\n\n /** Register a data source for dynamic content */\n registerDataSource(dataSource: DataSource): void;\n\n /** Register a create interceptor for this plugin's entity type */\n registerCreateInterceptor(\n entityType: string,\n interceptor: CreateInterceptor,\n ): void;\n\n /** Register a raw-upload durable save handler for this plugin's entity type */\n registerUploadSaveHandler(registration: UploadSaveHandlerRegistration): void;\n\n /** Look up the registered upload-save handler claiming a media type */\n getUploadSaveHandler(\n mediaType: string,\n ): UploadSaveHandlerRegistration | undefined;\n}\n\nexport interface EmbeddingBackfillResult {\n queued: number;\n skipped: number;\n}\n\nexport interface EmbeddingFailureReference {\n entityId: string;\n entityType: string;\n contentHash: string;\n}\n\nexport interface EmbeddingIndexStats {\n missingEmbeddings: number;\n staleEmbeddings: number;\n failedEmbeddings: number;\n /** Entities whose type generates embeddings (non-embeddable types excluded). */\n embeddableEntities: number;\n /** Embeddable entities whose embedding is present and current. */\n embeddedEntities: number;\n}\n\nexport interface IndexReadinessOptions {\n /** Stop polling after this duration. Omit for an owning runtime monitor. */\n timeoutMs?: number;\n intervalMs?: number;\n /** Cancels readiness polling when the owning runtime shuts down. */\n signal?: AbortSignal;\n}\n\nexport interface IndexReadinessStatus extends EmbeddingIndexStats {\n ready: boolean;\n degraded: boolean;\n activeEmbeddingJobs: number;\n}\n\nexport interface EntityService extends ICoreEntityService {\n // Mutations\n createEntity<T extends BaseEntity>(\n request: CreateEntityRequest<T>,\n ): Promise<EntityMutationResult>;\n createEntityFromMarkdown(\n request: CreateEntityFromMarkdownRequest,\n ): Promise<EntityMutationResult>;\n updateEntity<T extends BaseEntity>(\n request: UpdateEntityRequest<T>,\n ): Promise<EntityMutationResult>;\n deleteEntity(request: DeleteEntityRequest): Promise<boolean>;\n upsertEntity<T extends BaseEntity>(\n request: UpsertEntityRequest<T>,\n ): Promise<EntityMutationResult & { created: boolean }>;\n storeEmbedding(data: StoreEmbeddingData): Promise<void>;\n backfillMissingEmbeddings(): Promise<EmbeddingBackfillResult>;\n isIndexReady(): boolean;\n awaitIndexReady(\n options: IndexReadinessOptions,\n ): Promise<IndexReadinessStatus>;\n\n // Serialization\n serializeEntity(entity: BaseEntity): string;\n deserializeEntity(markdown: string, entityType: string): Partial<BaseEntity>;\n\n // Counts\n countEmbeddings(): Promise<number>;\n\n // Diagnostics\n searchWithDistances(\n request: SearchWithDistancesRequest,\n ): Promise<Array<{ entityId: string; entityType: string; distance: number }>>;\n\n // Lifecycle\n initialize(): Promise<void>;\n\n // Job status\n getAsyncJobStatus(jobId: string): Promise<{\n status: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n error?: string;\n } | null>;\n}\n\n/**\n * Entity Registry interface for managing entity types and their schemas/adapters\n */\nexport interface EntityRegistry {\n registerEntityType<\n TEntity extends BaseEntity<TMetadata>,\n TMetadata = Record<string, unknown>,\n >(\n type: string,\n schema: UnknownEntitySchema,\n adapter: EntityAdapter<TEntity, TMetadata>,\n config?: EntityTypeConfig,\n ): void;\n\n /** Remove an entity type after failed plugin registration or shell teardown. */\n unregisterEntityType(type: string): void;\n\n getSchema(type: string): UnknownEntitySchema;\n\n getAdapter<\n TEntity extends BaseEntity<TMetadata>,\n TMetadata = Record<string, unknown>,\n >(\n type: string,\n ): EntityAdapter<TEntity, TMetadata>;\n\n hasEntityType(type: string): boolean;\n\n validateEntity(type: string, entity: unknown): BaseEntity;\n\n getAllEntityTypes(): string[];\n\n /** Get configuration for a specific entity type */\n getEntityTypeConfig(type: string): EntityTypeConfig;\n\n /** Get weight map for all registered entity types with non-default weights */\n getWeightMap(): Record<string, number>;\n\n registerCreateInterceptor(type: string, interceptor: CreateInterceptor): void;\n\n getCreateInterceptor(type: string): CreateInterceptor | undefined;\n\n registerUploadSaveHandler(registration: UploadSaveHandlerRegistration): void;\n\n getUploadSaveHandler(\n mediaType: string,\n ): UploadSaveHandlerRegistration | undefined;\n\n registerPersistValidator(type: string, validator: PersistValidator): void;\n\n getPersistValidator(type: string): PersistValidator | undefined;\n\n /**\n * Extend an adapter's frontmatterSchema with additional fields.\n * Used by plugins to add domain-specific fields (e.g., professional-site adds tagline to profile).\n * Extensions are merged into the effective schema returned by getEffectiveFrontmatterSchema().\n */\n extendFrontmatterSchema(\n type: string,\n extension: z.ZodObject<z.ZodRawShape>,\n ): void;\n\n /**\n * Get the effective frontmatter schema for an entity type,\n * with all registered extensions merged in.\n * Returns undefined if the adapter has no frontmatterSchema.\n */\n getEffectiveFrontmatterSchema(\n type: string,\n ): z.ZodObject<z.ZodRawShape> | undefined;\n}\n\n/**\n * Database configuration for entity service\n */\nexport type { DbConfig as EntityDbConfig } from \"@brains/contracts\";\n",
51
51
  "import matter from \"gray-matter\";\nimport { z } from \"@brains/utils/zod\";\nimport type { BaseEntity, ContentVisibility } from \"./types\";\n\n/**\n * Configuration for frontmatter handling\n */\nexport interface FrontmatterConfig<T extends BaseEntity> {\n /**\n * Fields to explicitly include in frontmatter\n * If not specified, includes all non-system fields\n */\n includeFields?: (keyof T)[];\n\n /**\n * Fields to exclude from frontmatter\n * By default excludes: id, entityType, content, created, updated\n */\n excludeFields?: (keyof T)[];\n\n /**\n * Custom serializers for complex fields\n */\n customSerializers?: {\n [K in keyof T]?: (value: T[K]) => unknown;\n };\n\n /**\n * Custom deserializers for complex fields\n */\n customDeserializers?: {\n [K in keyof T]?: (value: unknown) => T[K];\n };\n}\n\nexport interface FrontmatterValidationSchema<T> {\n parse(data: unknown): T;\n}\n\n// Default system fields that should not be in frontmatter\nconst DEFAULT_SYSTEM_FIELDS: Array<keyof BaseEntity> = [\n \"id\",\n \"entityType\",\n \"content\",\n \"contentHash\",\n \"created\",\n \"updated\",\n \"visibility\",\n];\n\n/**\n * Extract metadata fields from an entity for frontmatter\n * Returns only non-system fields by default\n */\nexport function extractMetadata<T extends BaseEntity>(\n entity: T,\n config?: FrontmatterConfig<T>,\n): Record<string, unknown> {\n const { includeFields, excludeFields = [], customSerializers } = config ?? {};\n const excludedFieldNames = new Set<string>([\n ...DEFAULT_SYSTEM_FIELDS.map(String),\n ...excludeFields.map(String),\n ]);\n\n const metadata: Record<string, unknown> = {};\n\n // Get all fields from the entity\n const allFields = Object.keys(entity) as Array<keyof T>;\n\n // Determine which fields to include\n let fieldsToProcess: Array<keyof T>;\n if (includeFields) {\n // If includeFields is specified, only include those\n fieldsToProcess = includeFields.filter(\n (field) => !excludedFieldNames.has(String(field)),\n );\n } else {\n // Otherwise include all fields except excluded ones\n fieldsToProcess = allFields.filter(\n (field) => !excludedFieldNames.has(String(field)),\n );\n }\n\n // Process each field\n for (const field of fieldsToProcess) {\n const value = entity[field];\n\n // Skip undefined values\n if (value === undefined) {\n continue;\n }\n\n // Use custom serializer if available\n if (customSerializers && field in customSerializers) {\n const serializer = customSerializers[field];\n if (serializer) {\n metadata[field as string] = serializer(value);\n }\n } else {\n metadata[field as string] = value;\n }\n }\n\n return metadata;\n}\n\n/**\n * Generate markdown with frontmatter from content and metadata\n */\nexport function generateMarkdownWithFrontmatter(\n content: string,\n metadata: Record<string, unknown>,\n): string {\n // Only add frontmatter if there's metadata\n if (Object.keys(metadata).length === 0) {\n return content;\n }\n\n const cleaned = Object.fromEntries(\n Object.entries(metadata).filter(([, v]) => v !== undefined),\n );\n return matter.stringify(content, cleaned);\n}\n\n/**\n * Helper to convert all Date objects to ISO strings recursively\n */\nfunction convertDatesToStrings(obj: unknown): unknown {\n if (obj instanceof Date) {\n return obj.toISOString();\n }\n if (Array.isArray(obj)) {\n return obj.map(convertDatesToStrings);\n }\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = convertDatesToStrings(value);\n }\n return result;\n }\n return obj;\n}\n\n/**\n * Parse markdown with frontmatter into content and metadata\n */\nexport function parseMarkdownWithFrontmatter<T>(\n markdown: string,\n schema: FrontmatterValidationSchema<T>,\n): {\n content: string;\n metadata: T;\n} {\n const { content, data } = matter(markdown);\n\n // Convert all Date objects to strings before parsing with Zod\n const normalizedData = convertDatesToStrings(data);\n\n return {\n content: content.trim(),\n metadata: schema.parse(normalizedData),\n };\n}\n\n/**\n * Apply custom deserializers to metadata\n */\nexport function deserializeMetadata<T extends BaseEntity>(\n metadata: Record<string, unknown>,\n config?: FrontmatterConfig<T>,\n): Record<string, unknown> {\n if (!config?.customDeserializers) {\n return metadata;\n }\n\n const result: Record<string, unknown> = { ...metadata };\n\n for (const [field, deserializer] of Object.entries(\n config.customDeserializers,\n )) {\n if (field in metadata) {\n result[field] = deserializer(metadata[field]);\n }\n }\n\n return result;\n}\n\n/**\n * Generate frontmatter string from metadata\n */\nexport function generateFrontmatter(metadata: Record<string, unknown>): string {\n if (Object.keys(metadata).length === 0) {\n return \"\";\n }\n\n // Use gray-matter to generate frontmatter\n const fullMarkdown = matter.stringify(\"\", metadata);\n\n // Extract just the frontmatter part\n const match = fullMarkdown.match(/^---\\n[\\s\\S]*?\\n---/);\n return match ? match[0] : \"\";\n}\n\nconst visibilityFrontmatterSchema = z.object({\n visibility: z\n .enum([\"public\", \"shared\", \"restricted\", \"private\"])\n .optional()\n .transform((value): ContentVisibility => {\n if (value === undefined) return \"public\";\n return value === \"private\" ? \"restricted\" : value;\n }),\n});\n\nexport function extractVisibilityFromMarkdown(\n markdown: string,\n): ContentVisibility {\n const parsed = matter(markdown);\n return visibilityFrontmatterSchema.parse(parsed.data).visibility;\n}\n\nexport function hasVisibilityFrontmatter(markdown: string): boolean {\n const frontmatterMatch = markdown.match(/^---\\r?\\n[\\s\\S]*?\\r?\\n---/);\n const visibilityMatch = frontmatterMatch?.[0].match(/^visibility:/m);\n return visibilityMatch !== null && visibilityMatch !== undefined;\n}\n\nexport function applyVisibilityToMarkdown(\n markdown: string,\n visibility: ContentVisibility,\n): string {\n if (visibility === \"public\" && !hasVisibilityFrontmatter(markdown)) {\n return markdown;\n }\n\n const parsed = matter(markdown);\n const frontmatter = Object.fromEntries(\n Object.entries(parsed.data).filter(([key]) => key !== \"visibility\"),\n );\n\n if (visibility !== \"public\") {\n frontmatter[\"visibility\"] = visibility;\n }\n\n return generateMarkdownWithFrontmatter(parsed.content.trim(), frontmatter);\n}\n",
52
52
  "/**\n * Extract a human-readable error message from an unknown error value.\n * Handles Error objects, strings, and other types.\n */\nexport function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Coerce an unknown thrown value to an Error instance, preserving the\n * original when it's already an Error so stack traces and subclasses\n * survive rethrow.\n */\nexport function toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n",
53
53
  "import { getErrorMessage } from \"@brains/utils/error\";\nimport { z } from \"@brains/utils/zod\";\n\nconst validationIssuesErrorSchema = z.looseObject({\n issues: z.array(\n z.looseObject({\n message: z.string(),\n }),\n ),\n});\n\nexport class EntityValidationError extends Error {\n public readonly entityType: string;\n public readonly originalError: unknown;\n\n constructor(entityType: string, originalError: unknown) {\n super(\n `Invalid entity data for ${entityType}: ${getErrorMessage(originalError)}`,\n );\n this.name = \"EntityValidationError\";\n this.entityType = entityType;\n this.originalError = originalError;\n }\n}\n\nexport function hasValidationIssues(error: unknown): boolean {\n return validationIssuesErrorSchema.safeParse(error).success;\n}\n\nexport function isEntityValidationError(error: unknown): boolean {\n return error instanceof EntityValidationError || hasValidationIssues(error);\n}\n\nexport function toEntityValidationError(\n entityType: string,\n error: unknown,\n): EntityValidationError | undefined {\n if (error instanceof EntityValidationError) {\n return error;\n }\n return hasValidationIssues(error)\n ? new EntityValidationError(entityType, error)\n : undefined;\n}\n",
@@ -490,6 +490,12 @@ interface ICoreEntityService {
490
490
  getEntityRaw<T extends BaseEntity>(request: GetEntityRawRequest): Promise<T | null>;
491
491
  listEntities<T extends BaseEntity>(request: ListEntitiesRequest): Promise<T[]>;
492
492
  search<T extends BaseEntity = BaseEntity>(request: EntitySearchRequest): Promise<SearchResult<T>[]>;
493
+ /** Return embedded entities with raw cosine distance to a query. */
494
+ searchWithDistances(request: SearchWithDistancesRequest): Promise<Array<{
495
+ entityId: string;
496
+ entityType: string;
497
+ distance: number;
498
+ }>>;
493
499
  /** Project visible entities into a provider-independent semantic space. */
494
500
  projectSemanticSpace(request: ProjectSemanticSpaceRequest): Promise<SemanticSpaceProjection>;
495
501
  getEntityTypes(): string[];
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{Pa as r,Qa as o}from"./chunks/index-wvwq0pm7.js";import"./chunks/index-gmfgjnnw.js";function t(i){return i}var e={name:"@rizom/brain",version:"0.2.0-alpha.205",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",zod:"^4.1.8"},devDependencies:{"@brains/app":"workspace:*","@brains/build-tools":"workspace:*","@brains/content-formatters":"workspace:*","@brains/deploy-support":"workspace:*","@brains/eslint-config":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/ranger":"workspace:*","@brains/relay":"workspace:*","@brains/rover":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-default":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@rizom/theme-default":"workspace:*","@types/bun":"^1.3.14",rolldown:"^1.0.0","rolldown-plugin-dts":"^0.27.4",typescript:"^7.0.2"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./themes":{types:"./dist/themes.d.ts",import:"./dist/themes.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var n=e.version;export{o as z,t as defineBrain,r as ZodError,n as PLUGIN_API_VERSION};
2
+ import{Pa as r,Qa as o}from"./chunks/index-wvwq0pm7.js";import"./chunks/index-gmfgjnnw.js";function t(i){return i}var e={name:"@rizom/brain",version:"0.2.0-alpha.207",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",zod:"^4.1.8"},devDependencies:{"@brains/app":"workspace:*","@brains/build-tools":"workspace:*","@brains/content-formatters":"workspace:*","@brains/deploy-support":"workspace:*","@brains/eslint-config":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/ranger":"workspace:*","@brains/relay":"workspace:*","@brains/rover":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-default":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@rizom/theme-default":"workspace:*","@types/bun":"^1.3.14",rolldown:"^1.0.0","rolldown-plugin-dts":"^0.27.4",typescript:"^7.0.2"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./themes":{types:"./dist/themes.d.ts",import:"./dist/themes.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var n=e.version;export{o as z,t as defineBrain,r as ZodError,n as PLUGIN_API_VERSION};
3
3
 
4
- //# debugId=A23EAE8CE6407C2C64756E2164756E21
4
+ //# debugId=D6348AFB138AF7FC64756E2164756E21
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -6,6 +6,6 @@
6
6
  "import packageJson from \"../package.json\" with { type: \"json\" };\n\n/**\n * Pre-v1 external plugin API marker.\n *\n * During alpha, the external plugin API compatibility marker tracks the\n * published @rizom/brain package version. Once the plugin API is declared\n * stable, this can move to an independent semver contract such as 1.0.0.\n */\nexport const PLUGIN_API_VERSION: string = packageJson.version;\n"
7
7
  ],
8
8
  "mappings": ";0FA0EO,UAAS,CAAW,CAAC,EAA8C,CACxE,OAAO,6yFClEF,IAAM,EAA6B,EAAY",
9
- "debugId": "A23EAE8CE6407C2C64756E2164756E21",
9
+ "debugId": "D6348AFB138AF7FC64756E2164756E21",
10
10
  "names": []
11
11
  }
package/dist/plugins.d.ts CHANGED
@@ -608,6 +608,12 @@ interface ICoreEntityService {
608
608
  getEntityRaw<T extends BaseEntity>(request: GetEntityRawRequest): Promise<T | null>;
609
609
  listEntities<T extends BaseEntity>(request: ListEntitiesRequest): Promise<T[]>;
610
610
  search<T extends BaseEntity = BaseEntity>(request: EntitySearchRequest): Promise<SearchResult<T>[]>;
611
+ /** Return embedded entities with raw cosine distance to a query. */
612
+ searchWithDistances(request: SearchWithDistancesRequest): Promise<Array<{
613
+ entityId: string;
614
+ entityType: string;
615
+ distance: number;
616
+ }>>;
611
617
  /** Project visible entities into a provider-independent semantic space. */
612
618
  projectSemanticSpace(request: ProjectSemanticSpaceRequest): Promise<SemanticSpaceProjection>;
613
619
  getEntityTypes(): string[];
@@ -1186,7 +1192,7 @@ interface Channel<TPayload, TResponse = unknown> {
1186
1192
  readonly _response?: TResponse;
1187
1193
  }
1188
1194
  declare function defineChannel<TPayload, TResponse = unknown>(name: string, schema: SafeParserSchema<TPayload>): Channel<TPayload, TResponse>;
1189
- type PublicEntityServiceMethods = "getEntity" | "listEntities" | "search" | "getEntityTypes" | "hasEntityType" | "countEntities" | "getEntityCounts" | "getEntityTypeConfig";
1195
+ type PublicEntityServiceMethods = "getEntity" | "listEntities" | "search" | "searchWithDistances" | "getEntityTypes" | "hasEntityType" | "countEntities" | "getEntityCounts" | "getEntityTypeConfig";
1190
1196
  type IEntityService = Pick<ICoreEntityService, PublicEntityServiceMethods>;
1191
1197
  interface IIdentityNamespace {
1192
1198
  get: () => BrainCharacter;
package/dist/plugins.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @bun
2
- import{p as N,q as A,r as D,s as U,u as c,v as l,w as y,x as P,y as B,z as O}from"./chunks/index-w9z1vrm1.js";import"./chunks/index-e2c4agdd.js";import{Aa as w,Ba as _,Ca as H,na as E,qa as b,ra as k}from"./chunks/index-3097wt56.js";import"./chunks/index-bs70092j.js";import"./chunks/index-9s5cwp2s.js";import{Qa as o}from"./chunks/index-wvwq0pm7.js";import"./chunks/index-gmfgjnnw.js";function v(e){return e}function R(e){return e}function C(e){return e===void 0?{success:!0}:{success:!0,data:e}}function S(e){return{success:!1,error:e}}var x=o.object({captureUrls:o.boolean().default(!1),blockedUrlDomains:o.array(o.string()).default(["meet.google.com","zoom.us","teams.microsoft.com","whereby.com","gather.town","calendly.com","cal.com","discord.com","discord.gg","cdn.discordapp.com","media.discordapp.net","giphy.com","tenor.com","wetransfer.com","file.io"])});function I(e,t){return{name:e,schema:t}}class p extends c{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}get entityType(){return this.hooks.getEntityType()}get schema(){return this.hooks.getSchema()}get adapter(){return this.hooks.getAdapter()}onRegister(e){return this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getEntityTypeConfig(){return this.hooks.getEntityTypeConfig()}getDataSources(){return this.hooks.getDataSources()}getInstructions(){return this.hooks.getInstructions()}interceptCreate(e,t,i){return this.hooks.interceptCreate(e,t,i)}}class u{type="entity";id;version;packageName;description;delegate;constructor(e,t,i,r){if(this.id=e,this.version=t.version,this.packageName=t.name,t.description!==void 0)this.description=t.description;this.delegate=new p(e,t,i,r,{getEntityType:()=>this.entityType,getSchema:()=>this.schema,getAdapter:()=>this.adapter,onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getEntityTypeConfig:()=>this.getEntityTypeConfig(),getDataSources:()=>this.getDataSources(),getInstructions:()=>this.getInstructions(),interceptCreate:(n,a,T)=>this.interceptCreate(n,a,T)})}register(e,t){return this.delegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getInstructions(){return}getEntityTypeConfig(){return}getDataSources(){return[]}async interceptCreate(e,t,i){return{kind:"continue",input:e}}ready(){return this.delegate.ready()}shutdown(){return this.delegate.shutdown?.()??Promise.resolve()}}class m extends l{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}onRegister(e){return this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getTools(){return this.hooks.getTools()}getResources(){return this.hooks.getResources()}getInstructions(){return this.hooks.getInstructions()}getWebRoutes(){return this.hooks.getWebRoutes()}requiresDaemonStartup(){return this.hooks.requiresDaemonStartup()}}class s{type="interface";id;version;packageName;description;delegate;constructor(e,t,i,r){if(this.id=e,this.version=t.version,this.packageName=t.name,t.description!==void 0)this.description=t.description;this.delegate=new m(e,t,i,r,{onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getTools:()=>this.getTools(),getResources:()=>this.getResources(),getInstructions:()=>this.getInstructions(),getWebRoutes:()=>this.getWebRoutes(),requiresDaemonStartup:()=>this.requiresDaemonStartup()})}register(e,t){return this.delegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getTools(){return[]}async getResources(){return[]}async getInstructions(){return}getWebRoutes(){return[]}requiresDaemonStartup(){return!1}ready(){return this.delegate.ready()}shutdown(){return this.delegate.shutdown?.()??Promise.resolve()}}class f extends y{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}async onRegister(e){await super.onRegister(e),await this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getTools(){return this.hooks.getTools()}getResources(){return this.hooks.getResources()}getInstructions(){return this.hooks.getInstructions()}getWebRoutes(){return this.hooks.getWebRoutes()}requiresDaemonStartup(){return this.hooks.requiresDaemonStartup()}sendMessageToChannel(e){this.hooks.sendMessageToChannel(e)}sendMessageWithId(e){return this.hooks.sendMessageWithId(e)}editMessage(e){return this.hooks.editMessage(e)}supportsMessageEditing(){return this.hooks.supportsMessageEditing()}onProgressUpdate(e){return this.hooks.onProgressUpdate(e)}trackAgentResponseForJobPublic(e,t,i){this.trackAgentResponseForJob(e,t,i)}captureUrlViaAgentPublic(e,t,i,r,n){return this.captureUrlViaAgent(e,t,i,r,n)}getCurrentChannelIdPublic(){return this.getCurrentChannelId()}}class d extends s{messageDelegate;constructor(e,t,i,r){super(e,t,i,r);this.messageDelegate=new f(e,t,i,r,{onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getTools:()=>this.getTools(),getResources:()=>this.getResources(),getInstructions:()=>this.getInstructions(),getWebRoutes:()=>this.getWebRoutes(),requiresDaemonStartup:()=>this.requiresDaemonStartup(),sendMessageToChannel:(n)=>this.sendMessageToChannel(n),sendMessageWithId:(n)=>this.sendMessageWithId(n),editMessage:(n)=>this.editMessage(n),supportsMessageEditing:()=>this.supportsMessageEditing(),onProgressUpdate:(n)=>this.onProgressUpdate(n)})}register(e,t){return this.messageDelegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getTools(){return[]}async getResources(){return[]}async getInstructions(){return}sendMessageWithId(e){return Promise.resolve(void 0)}editMessage(e){return Promise.resolve(!1)}supportsMessageEditing(){return!1}async onProgressUpdate(e){}isUploadableTextFile(e,t){let i=[".md",".txt",".markdown"];if(t&&["text/plain","text/markdown","text/x-markdown"].some((n)=>t.startsWith(n)))return!0;return i.some((n)=>e.toLowerCase().endsWith(n))}isFileSizeAllowed(e){return e<=1e5}formatFileUploadMessage(e,t){return`User uploaded a file "${e}":
2
+ import{p as N,q as D,r as A,s as U,u as g,v as l,w as y,x as P,y as B,z as O}from"./chunks/index-w9z1vrm1.js";import"./chunks/index-e2c4agdd.js";import{Aa as w,Ba as W,Ca as _,na as E,qa as b,ra as k}from"./chunks/index-3097wt56.js";import"./chunks/index-bs70092j.js";import"./chunks/index-9s5cwp2s.js";import{Qa as o}from"./chunks/index-wvwq0pm7.js";import"./chunks/index-gmfgjnnw.js";function v(e){return e}function R(e){return e}function C(e){return e===void 0?{success:!0}:{success:!0,data:e}}function S(e){return{success:!1,error:e}}var x=o.object({captureUrls:o.boolean().default(!1),blockedUrlDomains:o.array(o.string()).default(["meet.google.com","zoom.us","teams.microsoft.com","whereby.com","gather.town","calendly.com","cal.com","discord.com","discord.gg","cdn.discordapp.com","media.discordapp.net","giphy.com","tenor.com","wetransfer.com","file.io"])});function I(e,t){return{name:e,schema:t}}class p extends g{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}get entityType(){return this.hooks.getEntityType()}get schema(){return this.hooks.getSchema()}get adapter(){return this.hooks.getAdapter()}onRegister(e){return this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getEntityTypeConfig(){return this.hooks.getEntityTypeConfig()}getDataSources(){return this.hooks.getDataSources()}getInstructions(){return this.hooks.getInstructions()}interceptCreate(e,t,i){return this.hooks.interceptCreate(e,t,i)}}class u{type="entity";id;version;packageName;description;delegate;constructor(e,t,i,r){if(this.id=e,this.version=t.version,this.packageName=t.name,t.description!==void 0)this.description=t.description;this.delegate=new p(e,t,i,r,{getEntityType:()=>this.entityType,getSchema:()=>this.schema,getAdapter:()=>this.adapter,onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getEntityTypeConfig:()=>this.getEntityTypeConfig(),getDataSources:()=>this.getDataSources(),getInstructions:()=>this.getInstructions(),interceptCreate:(n,a,T)=>this.interceptCreate(n,a,T)})}register(e,t){return this.delegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getInstructions(){return}getEntityTypeConfig(){return}getDataSources(){return[]}async interceptCreate(e,t,i){return{kind:"continue",input:e}}ready(){return this.delegate.ready()}shutdown(){return this.delegate.shutdown?.()??Promise.resolve()}}class m extends l{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}onRegister(e){return this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getTools(){return this.hooks.getTools()}getResources(){return this.hooks.getResources()}getInstructions(){return this.hooks.getInstructions()}getWebRoutes(){return this.hooks.getWebRoutes()}requiresDaemonStartup(){return this.hooks.requiresDaemonStartup()}}class s{type="interface";id;version;packageName;description;delegate;constructor(e,t,i,r){if(this.id=e,this.version=t.version,this.packageName=t.name,t.description!==void 0)this.description=t.description;this.delegate=new m(e,t,i,r,{onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getTools:()=>this.getTools(),getResources:()=>this.getResources(),getInstructions:()=>this.getInstructions(),getWebRoutes:()=>this.getWebRoutes(),requiresDaemonStartup:()=>this.requiresDaemonStartup()})}register(e,t){return this.delegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getTools(){return[]}async getResources(){return[]}async getInstructions(){return}getWebRoutes(){return[]}requiresDaemonStartup(){return!1}ready(){return this.delegate.ready()}shutdown(){return this.delegate.shutdown?.()??Promise.resolve()}}class f extends y{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}async onRegister(e){await super.onRegister(e),await this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getTools(){return this.hooks.getTools()}getResources(){return this.hooks.getResources()}getInstructions(){return this.hooks.getInstructions()}getWebRoutes(){return this.hooks.getWebRoutes()}requiresDaemonStartup(){return this.hooks.requiresDaemonStartup()}sendMessageToChannel(e){this.hooks.sendMessageToChannel(e)}sendMessageWithId(e){return this.hooks.sendMessageWithId(e)}editMessage(e){return this.hooks.editMessage(e)}supportsMessageEditing(){return this.hooks.supportsMessageEditing()}onProgressUpdate(e){return this.hooks.onProgressUpdate(e)}trackAgentResponseForJobPublic(e,t,i){this.trackAgentResponseForJob(e,t,i)}captureUrlViaAgentPublic(e,t,i,r,n){return this.captureUrlViaAgent(e,t,i,r,n)}getCurrentChannelIdPublic(){return this.getCurrentChannelId()}}class d extends s{messageDelegate;constructor(e,t,i,r){super(e,t,i,r);this.messageDelegate=new f(e,t,i,r,{onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getTools:()=>this.getTools(),getResources:()=>this.getResources(),getInstructions:()=>this.getInstructions(),getWebRoutes:()=>this.getWebRoutes(),requiresDaemonStartup:()=>this.requiresDaemonStartup(),sendMessageToChannel:(n)=>this.sendMessageToChannel(n),sendMessageWithId:(n)=>this.sendMessageWithId(n),editMessage:(n)=>this.editMessage(n),supportsMessageEditing:()=>this.supportsMessageEditing(),onProgressUpdate:(n)=>this.onProgressUpdate(n)})}register(e,t){return this.messageDelegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getTools(){return[]}async getResources(){return[]}async getInstructions(){return}sendMessageWithId(e){return Promise.resolve(void 0)}editMessage(e){return Promise.resolve(!1)}supportsMessageEditing(){return!1}async onProgressUpdate(e){}isUploadableTextFile(e,t){let i=[".md",".txt",".markdown"];if(t&&["text/plain","text/markdown","text/x-markdown"].some((n)=>t.startsWith(n)))return!0;return i.some((n)=>e.toLowerCase().endsWith(n))}isFileSizeAllowed(e){return e<=1e5}formatFileUploadMessage(e,t){return`User uploaded a file "${e}":
3
3
 
4
- ${t}`}extractCaptureableUrls(e,t){let i=e.match(/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi)??[];return[...new Set(i)].filter((r)=>{try{let{hostname:n}=new URL(r);return!t.some((a)=>n===a||n.endsWith(`.${a}`))}catch{return!1}})}captureUrlViaAgent(e,t,i,r,n){return this.messageDelegate.captureUrlViaAgentPublic(e,t,i,r,n)}trackAgentResponseForJob(e,t,i){this.messageDelegate.trackAgentResponseForJobPublic(e,t,i)}registerProgressCallback(e){this.messageDelegate.registerProgressCallback(e)}unregisterProgressCallback(){this.messageDelegate.unregisterProgressCallback()}getProgressEvents(){return this.messageDelegate.getProgressEvents()}getActiveProgressEvents(){return this.messageDelegate.getActiveProgressEvents()}startProcessingInput(e=null){this.messageDelegate.startProcessingInput(e)}endProcessingInput(){this.messageDelegate.endProcessingInput()}getCurrentChannelId(){return this.messageDelegate.getCurrentChannelIdPublic()}ready(){return this.messageDelegate.ready()}shutdown(){return this.messageDelegate.shutdown?.()??Promise.resolve()}}class h extends P{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}onRegister(e){return this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getTools(){return this.hooks.getTools()}getResources(){return this.hooks.getResources()}getInstructions(){return this.hooks.getInstructions()}}class g{type="service";id;version;packageName;description;delegate;constructor(e,t,i,r){if(this.id=e,this.version=t.version,this.packageName=t.name,t.description!==void 0)this.description=t.description;this.delegate=new h(e,t,i,r,{onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getTools:()=>this.getTools(),getResources:()=>this.getResources(),getInstructions:()=>this.getInstructions()})}register(e,t){return this.delegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getTools(){return[]}async getResources(){return[]}async getInstructions(){return}ready(){return this.delegate.ready()}shutdown(){return this.delegate.shutdown?.()??Promise.resolve()}}export{x as urlCaptureConfigSchema,C as toolSuccess,S as toolError,I as defineChannel,v as createTool,R as createResource,b as ToolResultDataSchema,g as ServicePlugin,E as PendingConfirmationSchema,A as MessageSchema,_ as MessageResponseSchema,d as MessageInterfacePlugin,s as InterfacePlugin,w as ExtensionMetadataSchema,u as EntityPlugin,N as ConversationSchema,B as ChatContextSchema,D as BrainCharacterSchema,H as BaseMessageSchema,O as AppInfoSchema,U as AnchorProfileSchema,k as AgentResponseSchema};
4
+ ${t}`}extractCaptureableUrls(e,t){let i=e.match(/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi)??[];return[...new Set(i)].filter((r)=>{try{let{hostname:n}=new URL(r);return!t.some((a)=>n===a||n.endsWith(`.${a}`))}catch{return!1}})}captureUrlViaAgent(e,t,i,r,n){return this.messageDelegate.captureUrlViaAgentPublic(e,t,i,r,n)}trackAgentResponseForJob(e,t,i){this.messageDelegate.trackAgentResponseForJobPublic(e,t,i)}registerProgressCallback(e){this.messageDelegate.registerProgressCallback(e)}unregisterProgressCallback(){this.messageDelegate.unregisterProgressCallback()}getProgressEvents(){return this.messageDelegate.getProgressEvents()}getActiveProgressEvents(){return this.messageDelegate.getActiveProgressEvents()}startProcessingInput(e=null){this.messageDelegate.startProcessingInput(e)}endProcessingInput(){this.messageDelegate.endProcessingInput()}getCurrentChannelId(){return this.messageDelegate.getCurrentChannelIdPublic()}ready(){return this.messageDelegate.ready()}shutdown(){return this.messageDelegate.shutdown?.()??Promise.resolve()}}class h extends P{hooks;constructor(e,t,i,r,n){super(e,t,i,r);this.hooks=n}onRegister(e){return this.hooks.onRegister(e)}onReady(e){return this.hooks.onReady(e)}onShutdown(){return this.hooks.onShutdown()}getTools(){return this.hooks.getTools()}getResources(){return this.hooks.getResources()}getInstructions(){return this.hooks.getInstructions()}}class c{type="service";id;version;packageName;description;delegate;constructor(e,t,i,r){if(this.id=e,this.version=t.version,this.packageName=t.name,t.description!==void 0)this.description=t.description;this.delegate=new h(e,t,i,r,{onRegister:(n)=>this.onRegister(n),onReady:(n)=>this.onReady(n),onShutdown:()=>this.onShutdown(),getTools:()=>this.getTools(),getResources:()=>this.getResources(),getInstructions:()=>this.getInstructions()})}register(e,t){return this.delegate.register(e,t)}async onRegister(e){}async onReady(e){}async onShutdown(){}async getTools(){return[]}async getResources(){return[]}async getInstructions(){return}ready(){return this.delegate.ready()}shutdown(){return this.delegate.shutdown?.()??Promise.resolve()}}export{x as urlCaptureConfigSchema,C as toolSuccess,S as toolError,I as defineChannel,v as createTool,R as createResource,b as ToolResultDataSchema,c as ServicePlugin,E as PendingConfirmationSchema,D as MessageSchema,W as MessageResponseSchema,d as MessageInterfacePlugin,s as InterfacePlugin,w as ExtensionMetadataSchema,u as EntityPlugin,N as ConversationSchema,B as ChatContextSchema,A as BrainCharacterSchema,_ as BaseMessageSchema,O as AppInfoSchema,U as AnchorProfileSchema,k as AgentResponseSchema};
5
5
 
6
- //# debugId=DB5DF6AAFA5746AF64756E2164756E21
6
+ //# debugId=2CD50E0186B5245F64756E2164756E21
7
7
  //# sourceMappingURL=plugins.js.map
@@ -2,13 +2,13 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../shell/plugins/src/public/types.ts", "../../../shell/plugins/src/public/entity-plugin.ts", "../../../shell/plugins/src/public/interface-plugin.ts", "../../../shell/plugins/src/public/message-interface-plugin.ts", "../../../shell/plugins/src/public/service-plugin.ts"],
4
4
  "sourcesContent": [
5
- "import type {\n ContentVisibility,\n CountEntitiesRequest,\n EntitySearchRequest,\n GetEntityRequest,\n ICoreEntityService,\n IEntitiesNamespace,\n ProjectSemanticSpaceRequest,\n SemanticEntityReference,\n SemanticSpaceDistanceRange,\n SemanticSpaceNeighbor,\n SemanticSpaceOrigin,\n SemanticSpacePoint,\n SemanticSpaceProjection,\n ListEntitiesRequest,\n ListOptions,\n SearchOptions,\n SearchResult,\n} from \"@brains/entity-service\";\nimport type {\n EntityAction,\n OutputFormat,\n UserPermissionLevel,\n} from \"@brains/templates\";\nimport { z } from \"@brains/utils/zod\";\nimport type { AgentNamespace } from \"../contracts/agent\";\nimport type { AppInfo } from \"../contracts/app-info\";\nimport type { Conversation, Message } from \"../contracts/conversations\";\nimport type { AnchorProfile, BrainCharacter } from \"../contracts/identity\";\nimport type {\n MessageResponse,\n MessageSender,\n MessageWithPayload,\n} from \"../contracts/messaging\";\nimport type { IEntityAINamespace } from \"../entity/context\";\n\nexport type PluginConfig = Record<string, unknown>;\nexport type PluginConfigInput<T extends { _input: unknown }> = T[\"_input\"];\n\nexport interface SafeParserSchema<T> {\n safeParse(\n input: unknown,\n ):\n { success: true; data: T } | { success: false; error: { message: string } };\n}\n\nexport interface JudgeInput<T> {\n instruction: string;\n material: string;\n schema: z.ZodType<T, unknown>;\n}\n\nexport interface Plugin {\n readonly id: string;\n readonly version: string;\n readonly type: \"core\" | \"entity\" | \"service\" | \"interface\";\n readonly packageName: string;\n readonly description?: string;\n readonly dependencies?: string[];\n ready?(): Promise<void>;\n shutdown?(): Promise<void>;\n requiresDaemonStartup?(): boolean;\n}\n\nexport type PluginFactory = (config: PluginConfig) => Plugin | Plugin[];\n\nexport interface Logger {\n debug(message: string, data?: unknown): void;\n info(message: string, data?: unknown): void;\n warn(message: string, data?: unknown): void;\n error(message: string, data?: unknown): void;\n child(context: string): Logger;\n}\n\nexport interface ToolContext {\n progressToken?: string | number;\n sendProgress?: (notification: {\n progress?: number;\n total?: number;\n message?: string;\n }) => Promise<void>;\n interfaceType?: string;\n userId?: string;\n conversationId?: string;\n channelId?: string;\n channelName?: string;\n runId?: string;\n toolCallId?: string;\n userPermissionLevel?: UserPermissionLevel;\n}\n\nexport interface ToolResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\nexport type ToolVisibility = UserPermissionLevel;\n\nexport interface ToolConfirmation {\n required: boolean;\n message?: string;\n}\n\nexport type ToolSideEffects = \"none\" | \"writes\" | \"external\";\n\nexport interface Tool<TArgs = unknown, TResult = unknown> {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n handler: (args: TArgs, context: ToolContext) => Promise<TResult> | TResult;\n visibility?: ToolVisibility;\n confirmation?: ToolConfirmation;\n sideEffects?: ToolSideEffects;\n}\n\nexport interface Resource<TResult = unknown> {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n handler: () => Promise<TResult> | TResult;\n}\n\nexport interface ResourceTemplate<K extends string = string> {\n uriTemplate: K;\n name: string;\n description?: string;\n mimeType?: string;\n}\n\nexport interface Prompt {\n name: string;\n description?: string;\n arguments?: Array<{ name: string; description?: string; required?: boolean }>;\n}\n\nexport function createTool<TArgs = unknown, TResult = unknown>(\n tool: Tool<TArgs, TResult>,\n): Tool<TArgs, TResult> {\n return tool;\n}\n\nexport function createResource<TResult = unknown>(\n resource: Resource<TResult>,\n): Resource<TResult> {\n return resource;\n}\n\nexport function toolSuccess<T = unknown>(data?: T): ToolResponse<T> {\n return data === undefined ? { success: true } : { success: true, data };\n}\n\nexport function toolError(error: string): ToolResponse<never> {\n return { success: false, error };\n}\n\nexport interface BaseJobTrackingInfo {\n rootJobId: string;\n}\n\nexport interface MessageJobTrackingInfo extends BaseJobTrackingInfo {\n messageId?: string;\n channelId?: string;\n}\n\nexport type JobProgressStatus =\n \"pending\" | \"processing\" | \"completed\" | \"failed\";\n\nexport interface JobProgressContext {\n rootJobId: string;\n operationType:\n | \"file_operations\"\n | \"content_operations\"\n | \"data_processing\"\n | \"batch_processing\";\n pluginId?: string | undefined;\n progressToken?: string | number | undefined;\n operationTarget?: string | undefined;\n interfaceType?: string | undefined;\n conversationId?: string | undefined;\n channelId?: string | undefined;\n}\n\nexport interface JobProgressEvent {\n id: string;\n type: \"job\" | \"batch\";\n status: JobProgressStatus;\n message?: string | undefined;\n progress?:\n | {\n current: number;\n total: number;\n percentage: number;\n }\n | undefined;\n aggregationKey?: string | undefined;\n batchDetails?:\n | {\n totalOperations: number;\n completedOperations: number;\n failedOperations: number;\n currentOperation?: string | undefined;\n errors?: string[] | undefined;\n }\n | undefined;\n jobDetails?:\n | {\n jobType: string;\n priority: number;\n retryCount: number;\n }\n | undefined;\n metadata: JobProgressContext;\n}\n\nexport const urlCaptureConfigSchema: z.ZodObject<{\n captureUrls: z.ZodDefault<z.ZodBoolean>;\n blockedUrlDomains: z.ZodDefault<z.ZodArray<z.ZodString>>;\n}> = z.object({\n captureUrls: z.boolean().default(false),\n blockedUrlDomains: z\n .array(z.string())\n .default([\n \"meet.google.com\",\n \"zoom.us\",\n \"teams.microsoft.com\",\n \"whereby.com\",\n \"gather.town\",\n \"calendly.com\",\n \"cal.com\",\n \"discord.com\",\n \"discord.gg\",\n \"cdn.discordapp.com\",\n \"media.discordapp.net\",\n \"giphy.com\",\n \"tenor.com\",\n \"wetransfer.com\",\n \"file.io\",\n ]),\n});\n\nexport interface Channel<TPayload, TResponse = unknown> {\n readonly name: string;\n readonly schema: SafeParserSchema<TPayload>;\n readonly _response?: TResponse;\n}\n\nexport function defineChannel<TPayload, TResponse = unknown>(\n name: string,\n schema: SafeParserSchema<TPayload>,\n): Channel<TPayload, TResponse> {\n return { name, schema };\n}\n\ntype PublicEntityServiceMethods =\n | \"getEntity\"\n | \"listEntities\"\n | \"search\"\n | \"getEntityTypes\"\n | \"hasEntityType\"\n | \"countEntities\"\n | \"getEntityCounts\"\n | \"getEntityTypeConfig\";\n\nexport type IEntityService = Pick<\n ICoreEntityService,\n PublicEntityServiceMethods\n>;\n\nexport type {\n CountEntitiesRequest,\n EntitySearchRequest,\n GetEntityRequest,\n IEntitiesNamespace,\n ProjectSemanticSpaceRequest,\n SemanticEntityReference,\n SemanticSpaceDistanceRange,\n SemanticSpaceNeighbor,\n SemanticSpaceOrigin,\n SemanticSpacePoint,\n SemanticSpaceProjection,\n ListEntitiesRequest,\n ListOptions,\n SearchOptions,\n SearchResult,\n};\n\nexport interface IIdentityNamespace {\n get: () => BrainCharacter;\n getProfile: () => AnchorProfile;\n getAppInfo: () => Promise<AppInfo>;\n}\n\nexport interface IConversationsNamespace {\n get(conversationId: string): Promise<Conversation | null>;\n search(query: string): Promise<Conversation[]>;\n list(options?: {\n limit?: number;\n updatedAfter?: string;\n interfaceType?: string;\n sessionId?: string;\n channelId?: string;\n }): Promise<Conversation[]>;\n getMessages(\n conversationId: string,\n options?: { limit?: number; range?: { start: number; end: number } },\n ): Promise<Message[]>;\n}\n\nexport interface IMessagingNamespace {\n send: MessageSender;\n subscribe<T = unknown, R = unknown>(\n channel: string | Channel<T, R>,\n handler: (message: MessageWithPayload<T>) => Promise<MessageResponse<R>>,\n ): () => void;\n}\n\nexport type EvalHandler<TInput = unknown, TOutput = unknown> = (\n input: TInput,\n) => Promise<TOutput>;\n\nexport type InsightHandler = (\n entityService: IEntityService,\n visibilityScope: ContentVisibility,\n) => Promise<Record<string, unknown>>;\n\nexport interface IEvalNamespace {\n registerHandler(handlerId: string, handler: EvalHandler): void;\n}\n\nexport interface IInsightsNamespace {\n register(type: string, handler: InsightHandler): void;\n}\n\nexport interface ISemanticNamespace {\n project(\n request: ProjectSemanticSpaceRequest,\n ): Promise<SemanticSpaceProjection>;\n}\n\nexport interface IPermissionsNamespace {\n assertEntityActionAllowed(\n entityType: string,\n action: EntityAction,\n context: { userPermissionLevel?: UserPermissionLevel | undefined },\n ): void;\n}\n\nexport interface RuntimeUploadRecord {\n id: string;\n ref: { kind: string; id: string };\n filename: string;\n mediaType: string;\n sizeBytes: number;\n createdAt: string;\n metadata?: Record<string, unknown> | undefined;\n}\n\nexport interface RuntimeUploadResponseBody extends RuntimeUploadRecord {\n url: string;\n downloadUrl: string;\n}\n\nexport interface ResolvedRuntimeUpload {\n record: RuntimeUploadRecord;\n content: Buffer;\n}\n\nexport interface SaveRuntimeUploadInput {\n filename: string;\n mediaType: string;\n content: Buffer;\n metadata?: Record<string, unknown> | undefined;\n}\n\nexport interface RuntimeUploadScopeOptions {\n namespace: string;\n refKind: string;\n routePath: string;\n retentionMs?: number | undefined;\n maxCount?: number | undefined;\n}\n\nexport interface RuntimeUploadStore {\n save(input: SaveRuntimeUploadInput): Promise<RuntimeUploadRecord>;\n read(uploadId: string): Promise<ResolvedRuntimeUpload>;\n readRecord(uploadId: string): Promise<RuntimeUploadRecord>;\n toResponseBody(record: RuntimeUploadRecord): RuntimeUploadResponseBody;\n prune(): Promise<void>;\n getUploadDir(uploadId: string): string;\n}\n\nexport interface IRuntimeUploadsNamespace {\n scoped(options: RuntimeUploadScopeOptions): RuntimeUploadStore;\n}\n\nexport interface BasePluginContext {\n readonly pluginId: string;\n readonly logger: Logger;\n readonly dataDir: string;\n readonly domain: string | undefined;\n readonly siteUrl: string | undefined;\n readonly localSiteUrl: string | undefined;\n readonly previewUrl: string | undefined;\n readonly preferLocalUrls: boolean;\n readonly appInfo: () => Promise<AppInfo>;\n readonly judge: <T>(input: JudgeInput<T>) => Promise<{\n verdict: T;\n usage: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n }>;\n readonly entityService: IEntityService;\n readonly semantic: ISemanticNamespace;\n readonly identity: IIdentityNamespace;\n readonly messaging: IMessagingNamespace;\n readonly conversations: IConversationsNamespace;\n readonly eval: IEvalNamespace;\n readonly insights: IInsightsNamespace;\n readonly permissions: IPermissionsNamespace;\n readonly uploads: IRuntimeUploadsNamespace;\n}\n\nexport interface IPromptsNamespace {\n resolve(target: string, fallback: string): Promise<string>;\n}\n\nexport interface IServiceTemplatesNamespace {\n register(templates: unknown): void;\n}\n\nexport interface IViewsNamespace {\n get(name: string): unknown | undefined;\n list(): unknown[];\n hasRenderer(templateName: string, format?: OutputFormat): boolean;\n getRenderer(templateName: string, format?: OutputFormat): unknown | undefined;\n validate(templateName: string, content: unknown): boolean;\n}\n\nexport interface FrontmatterSchemaParser {\n parse(data: unknown): unknown;\n}\n\nexport interface EntityPluginEntitiesNamespace extends Omit<\n IEntitiesNamespace,\n \"getEffectiveFrontmatterSchema\"\n> {\n getEffectiveFrontmatterSchema(\n type: string,\n ): FrontmatterSchemaParser | undefined;\n}\n\nexport interface ServicePluginContext extends BasePluginContext {\n readonly entities: IEntitiesNamespace;\n readonly templates: IServiceTemplatesNamespace;\n readonly views: IViewsNamespace;\n readonly prompts: IPromptsNamespace;\n readonly ai: IEntityAINamespace;\n registerInstructions(instructions: string): void;\n}\n\nexport interface EntityPluginContext extends BasePluginContext {\n readonly entities: EntityPluginEntitiesNamespace;\n readonly prompts: IPromptsNamespace;\n}\n\nexport interface InterfacePluginContext extends BasePluginContext {\n readonly agent: AgentNamespace;\n}\n",
5
+ "import type {\n ContentVisibility,\n CountEntitiesRequest,\n EntitySearchRequest,\n SearchWithDistancesRequest,\n GetEntityRequest,\n ICoreEntityService,\n IEntitiesNamespace,\n ProjectSemanticSpaceRequest,\n SemanticEntityReference,\n SemanticSpaceDistanceRange,\n SemanticSpaceNeighbor,\n SemanticSpaceOrigin,\n SemanticSpacePoint,\n SemanticSpaceProjection,\n ListEntitiesRequest,\n ListOptions,\n SearchOptions,\n SearchResult,\n} from \"@brains/entity-service\";\nimport type {\n EntityAction,\n OutputFormat,\n UserPermissionLevel,\n} from \"@brains/templates\";\nimport { z } from \"@brains/utils/zod\";\nimport type { AgentNamespace } from \"../contracts/agent\";\nimport type { AppInfo } from \"../contracts/app-info\";\nimport type { Conversation, Message } from \"../contracts/conversations\";\nimport type { AnchorProfile, BrainCharacter } from \"../contracts/identity\";\nimport type {\n MessageResponse,\n MessageSender,\n MessageWithPayload,\n} from \"../contracts/messaging\";\nimport type { IEntityAINamespace } from \"../entity/context\";\n\nexport type PluginConfig = Record<string, unknown>;\nexport type PluginConfigInput<T extends { _input: unknown }> = T[\"_input\"];\n\nexport interface SafeParserSchema<T> {\n safeParse(\n input: unknown,\n ):\n { success: true; data: T } | { success: false; error: { message: string } };\n}\n\nexport interface JudgeInput<T> {\n instruction: string;\n material: string;\n schema: z.ZodType<T, unknown>;\n}\n\nexport interface Plugin {\n readonly id: string;\n readonly version: string;\n readonly type: \"core\" | \"entity\" | \"service\" | \"interface\";\n readonly packageName: string;\n readonly description?: string;\n readonly dependencies?: string[];\n ready?(): Promise<void>;\n shutdown?(): Promise<void>;\n requiresDaemonStartup?(): boolean;\n}\n\nexport type PluginFactory = (config: PluginConfig) => Plugin | Plugin[];\n\nexport interface Logger {\n debug(message: string, data?: unknown): void;\n info(message: string, data?: unknown): void;\n warn(message: string, data?: unknown): void;\n error(message: string, data?: unknown): void;\n child(context: string): Logger;\n}\n\nexport interface ToolContext {\n progressToken?: string | number;\n sendProgress?: (notification: {\n progress?: number;\n total?: number;\n message?: string;\n }) => Promise<void>;\n interfaceType?: string;\n userId?: string;\n conversationId?: string;\n channelId?: string;\n channelName?: string;\n runId?: string;\n toolCallId?: string;\n userPermissionLevel?: UserPermissionLevel;\n}\n\nexport interface ToolResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\nexport type ToolVisibility = UserPermissionLevel;\n\nexport interface ToolConfirmation {\n required: boolean;\n message?: string;\n}\n\nexport type ToolSideEffects = \"none\" | \"writes\" | \"external\";\n\nexport interface Tool<TArgs = unknown, TResult = unknown> {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n handler: (args: TArgs, context: ToolContext) => Promise<TResult> | TResult;\n visibility?: ToolVisibility;\n confirmation?: ToolConfirmation;\n sideEffects?: ToolSideEffects;\n}\n\nexport interface Resource<TResult = unknown> {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n handler: () => Promise<TResult> | TResult;\n}\n\nexport interface ResourceTemplate<K extends string = string> {\n uriTemplate: K;\n name: string;\n description?: string;\n mimeType?: string;\n}\n\nexport interface Prompt {\n name: string;\n description?: string;\n arguments?: Array<{ name: string; description?: string; required?: boolean }>;\n}\n\nexport function createTool<TArgs = unknown, TResult = unknown>(\n tool: Tool<TArgs, TResult>,\n): Tool<TArgs, TResult> {\n return tool;\n}\n\nexport function createResource<TResult = unknown>(\n resource: Resource<TResult>,\n): Resource<TResult> {\n return resource;\n}\n\nexport function toolSuccess<T = unknown>(data?: T): ToolResponse<T> {\n return data === undefined ? { success: true } : { success: true, data };\n}\n\nexport function toolError(error: string): ToolResponse<never> {\n return { success: false, error };\n}\n\nexport interface BaseJobTrackingInfo {\n rootJobId: string;\n}\n\nexport interface MessageJobTrackingInfo extends BaseJobTrackingInfo {\n messageId?: string;\n channelId?: string;\n}\n\nexport type JobProgressStatus =\n \"pending\" | \"processing\" | \"completed\" | \"failed\";\n\nexport interface JobProgressContext {\n rootJobId: string;\n operationType:\n | \"file_operations\"\n | \"content_operations\"\n | \"data_processing\"\n | \"batch_processing\";\n pluginId?: string | undefined;\n progressToken?: string | number | undefined;\n operationTarget?: string | undefined;\n interfaceType?: string | undefined;\n conversationId?: string | undefined;\n channelId?: string | undefined;\n}\n\nexport interface JobProgressEvent {\n id: string;\n type: \"job\" | \"batch\";\n status: JobProgressStatus;\n message?: string | undefined;\n progress?:\n | {\n current: number;\n total: number;\n percentage: number;\n }\n | undefined;\n aggregationKey?: string | undefined;\n batchDetails?:\n | {\n totalOperations: number;\n completedOperations: number;\n failedOperations: number;\n currentOperation?: string | undefined;\n errors?: string[] | undefined;\n }\n | undefined;\n jobDetails?:\n | {\n jobType: string;\n priority: number;\n retryCount: number;\n }\n | undefined;\n metadata: JobProgressContext;\n}\n\nexport const urlCaptureConfigSchema: z.ZodObject<{\n captureUrls: z.ZodDefault<z.ZodBoolean>;\n blockedUrlDomains: z.ZodDefault<z.ZodArray<z.ZodString>>;\n}> = z.object({\n captureUrls: z.boolean().default(false),\n blockedUrlDomains: z\n .array(z.string())\n .default([\n \"meet.google.com\",\n \"zoom.us\",\n \"teams.microsoft.com\",\n \"whereby.com\",\n \"gather.town\",\n \"calendly.com\",\n \"cal.com\",\n \"discord.com\",\n \"discord.gg\",\n \"cdn.discordapp.com\",\n \"media.discordapp.net\",\n \"giphy.com\",\n \"tenor.com\",\n \"wetransfer.com\",\n \"file.io\",\n ]),\n});\n\nexport interface Channel<TPayload, TResponse = unknown> {\n readonly name: string;\n readonly schema: SafeParserSchema<TPayload>;\n readonly _response?: TResponse;\n}\n\nexport function defineChannel<TPayload, TResponse = unknown>(\n name: string,\n schema: SafeParserSchema<TPayload>,\n): Channel<TPayload, TResponse> {\n return { name, schema };\n}\n\ntype PublicEntityServiceMethods =\n | \"getEntity\"\n | \"listEntities\"\n | \"search\"\n | \"searchWithDistances\"\n | \"getEntityTypes\"\n | \"hasEntityType\"\n | \"countEntities\"\n | \"getEntityCounts\"\n | \"getEntityTypeConfig\";\n\nexport type IEntityService = Pick<\n ICoreEntityService,\n PublicEntityServiceMethods\n>;\n\nexport type {\n CountEntitiesRequest,\n EntitySearchRequest,\n SearchWithDistancesRequest,\n GetEntityRequest,\n IEntitiesNamespace,\n ProjectSemanticSpaceRequest,\n SemanticEntityReference,\n SemanticSpaceDistanceRange,\n SemanticSpaceNeighbor,\n SemanticSpaceOrigin,\n SemanticSpacePoint,\n SemanticSpaceProjection,\n ListEntitiesRequest,\n ListOptions,\n SearchOptions,\n SearchResult,\n};\n\nexport interface IIdentityNamespace {\n get: () => BrainCharacter;\n getProfile: () => AnchorProfile;\n getAppInfo: () => Promise<AppInfo>;\n}\n\nexport interface IConversationsNamespace {\n get(conversationId: string): Promise<Conversation | null>;\n search(query: string): Promise<Conversation[]>;\n list(options?: {\n limit?: number;\n updatedAfter?: string;\n interfaceType?: string;\n sessionId?: string;\n channelId?: string;\n }): Promise<Conversation[]>;\n getMessages(\n conversationId: string,\n options?: { limit?: number; range?: { start: number; end: number } },\n ): Promise<Message[]>;\n}\n\nexport interface IMessagingNamespace {\n send: MessageSender;\n subscribe<T = unknown, R = unknown>(\n channel: string | Channel<T, R>,\n handler: (message: MessageWithPayload<T>) => Promise<MessageResponse<R>>,\n ): () => void;\n}\n\nexport type EvalHandler<TInput = unknown, TOutput = unknown> = (\n input: TInput,\n) => Promise<TOutput>;\n\nexport type InsightHandler = (\n entityService: IEntityService,\n visibilityScope: ContentVisibility,\n) => Promise<Record<string, unknown>>;\n\nexport interface IEvalNamespace {\n registerHandler(handlerId: string, handler: EvalHandler): void;\n}\n\nexport interface IInsightsNamespace {\n register(type: string, handler: InsightHandler): void;\n}\n\nexport interface ISemanticNamespace {\n project(\n request: ProjectSemanticSpaceRequest,\n ): Promise<SemanticSpaceProjection>;\n}\n\nexport interface IPermissionsNamespace {\n assertEntityActionAllowed(\n entityType: string,\n action: EntityAction,\n context: { userPermissionLevel?: UserPermissionLevel | undefined },\n ): void;\n}\n\nexport interface RuntimeUploadRecord {\n id: string;\n ref: { kind: string; id: string };\n filename: string;\n mediaType: string;\n sizeBytes: number;\n createdAt: string;\n metadata?: Record<string, unknown> | undefined;\n}\n\nexport interface RuntimeUploadResponseBody extends RuntimeUploadRecord {\n url: string;\n downloadUrl: string;\n}\n\nexport interface ResolvedRuntimeUpload {\n record: RuntimeUploadRecord;\n content: Buffer;\n}\n\nexport interface SaveRuntimeUploadInput {\n filename: string;\n mediaType: string;\n content: Buffer;\n metadata?: Record<string, unknown> | undefined;\n}\n\nexport interface RuntimeUploadScopeOptions {\n namespace: string;\n refKind: string;\n routePath: string;\n retentionMs?: number | undefined;\n maxCount?: number | undefined;\n}\n\nexport interface RuntimeUploadStore {\n save(input: SaveRuntimeUploadInput): Promise<RuntimeUploadRecord>;\n read(uploadId: string): Promise<ResolvedRuntimeUpload>;\n readRecord(uploadId: string): Promise<RuntimeUploadRecord>;\n toResponseBody(record: RuntimeUploadRecord): RuntimeUploadResponseBody;\n prune(): Promise<void>;\n getUploadDir(uploadId: string): string;\n}\n\nexport interface IRuntimeUploadsNamespace {\n scoped(options: RuntimeUploadScopeOptions): RuntimeUploadStore;\n}\n\nexport interface BasePluginContext {\n readonly pluginId: string;\n readonly logger: Logger;\n readonly dataDir: string;\n readonly domain: string | undefined;\n readonly siteUrl: string | undefined;\n readonly localSiteUrl: string | undefined;\n readonly previewUrl: string | undefined;\n readonly preferLocalUrls: boolean;\n readonly appInfo: () => Promise<AppInfo>;\n readonly judge: <T>(input: JudgeInput<T>) => Promise<{\n verdict: T;\n usage: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n }>;\n readonly entityService: IEntityService;\n readonly semantic: ISemanticNamespace;\n readonly identity: IIdentityNamespace;\n readonly messaging: IMessagingNamespace;\n readonly conversations: IConversationsNamespace;\n readonly eval: IEvalNamespace;\n readonly insights: IInsightsNamespace;\n readonly permissions: IPermissionsNamespace;\n readonly uploads: IRuntimeUploadsNamespace;\n}\n\nexport interface IPromptsNamespace {\n resolve(target: string, fallback: string): Promise<string>;\n}\n\nexport interface IServiceTemplatesNamespace {\n register(templates: unknown): void;\n}\n\nexport interface IViewsNamespace {\n get(name: string): unknown | undefined;\n list(): unknown[];\n hasRenderer(templateName: string, format?: OutputFormat): boolean;\n getRenderer(templateName: string, format?: OutputFormat): unknown | undefined;\n validate(templateName: string, content: unknown): boolean;\n}\n\nexport interface FrontmatterSchemaParser {\n parse(data: unknown): unknown;\n}\n\nexport interface EntityPluginEntitiesNamespace extends Omit<\n IEntitiesNamespace,\n \"getEffectiveFrontmatterSchema\"\n> {\n getEffectiveFrontmatterSchema(\n type: string,\n ): FrontmatterSchemaParser | undefined;\n}\n\nexport interface ServicePluginContext extends BasePluginContext {\n readonly entities: IEntitiesNamespace;\n readonly templates: IServiceTemplatesNamespace;\n readonly views: IViewsNamespace;\n readonly prompts: IPromptsNamespace;\n readonly ai: IEntityAINamespace;\n registerInstructions(instructions: string): void;\n}\n\nexport interface EntityPluginContext extends BasePluginContext {\n readonly entities: EntityPluginEntitiesNamespace;\n readonly prompts: IPromptsNamespace;\n}\n\nexport interface InterfacePluginContext extends BasePluginContext {\n readonly agent: AgentNamespace;\n}\n",
6
6
  "import { EntityPlugin as RuntimeEntityPlugin } from \"../entity/entity-plugin\";\nimport type { EntityPluginContext as RuntimeEntityPluginContext } from \"../entity/context\";\nimport type { PluginConfigSchema } from \"../config\";\nimport type {\n IShell,\n PluginCapabilities,\n PluginRegistrationContext,\n} from \"../interfaces\";\nimport type {\n BaseEntity,\n CreateExecutionContext,\n CreateInput,\n CreateInterceptionResult,\n DataSource,\n EntityAdapter,\n EntityTypeConfig,\n} from \"@brains/entity-service\";\nimport type { EntityPluginContext, Plugin } from \"./types\";\n\ntype EntitySchema<TEntity extends BaseEntity> =\n EntityAdapter<TEntity>[\"schema\"];\n\ninterface EntityPluginHooks<TEntity extends BaseEntity> {\n getEntityType(): string;\n getSchema(): EntitySchema<TEntity>;\n getAdapter(): EntityAdapter<TEntity>;\n onRegister(context: EntityPluginContext): Promise<void>;\n onReady(context: EntityPluginContext): Promise<void>;\n onShutdown(): Promise<void>;\n getEntityTypeConfig(): EntityTypeConfig | undefined;\n getDataSources(): DataSource[];\n getInstructions(): Promise<string | undefined>;\n interceptCreate(\n input: CreateInput,\n executionContext: CreateExecutionContext,\n context: EntityPluginContext,\n ): Promise<CreateInterceptionResult>;\n}\n\nclass EntityPluginDelegate<\n TEntity extends BaseEntity,\n TConfig,\n TConfigInput,\n> extends RuntimeEntityPlugin<TEntity, TConfig, TConfigInput> {\n private readonly hooks: EntityPluginHooks<TEntity>;\n constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n hooks: EntityPluginHooks<TEntity>,\n ) {\n super(id, packageJson, config, configSchema);\n this.hooks = hooks;\n }\n\n override get entityType(): string {\n return this.hooks.getEntityType();\n }\n\n override get schema(): EntitySchema<TEntity> {\n return this.hooks.getSchema();\n }\n\n override get adapter(): EntityAdapter<TEntity> {\n return this.hooks.getAdapter();\n }\n\n protected override onRegister(\n context: RuntimeEntityPluginContext,\n ): Promise<void> {\n return this.hooks.onRegister(context);\n }\n\n protected override onReady(\n context: RuntimeEntityPluginContext,\n ): Promise<void> {\n return this.hooks.onReady(context);\n }\n\n protected override onShutdown(): Promise<void> {\n return this.hooks.onShutdown();\n }\n\n protected override getEntityTypeConfig(): EntityTypeConfig | undefined {\n return this.hooks.getEntityTypeConfig();\n }\n\n protected override getDataSources(): DataSource[] {\n return this.hooks.getDataSources();\n }\n\n protected override getInstructions(): Promise<string | undefined> {\n return this.hooks.getInstructions();\n }\n\n protected override interceptCreate(\n input: CreateInput,\n executionContext: CreateExecutionContext,\n context: RuntimeEntityPluginContext,\n ): Promise<CreateInterceptionResult> {\n return this.hooks.interceptCreate(input, executionContext, context);\n }\n}\n\nexport abstract class EntityPlugin<\n TEntity extends BaseEntity,\n TConfig,\n TConfigInput,\n> implements Plugin {\n public readonly type = \"entity\" as const;\n public readonly id: string;\n public readonly version: string;\n public readonly packageName: string;\n public readonly description?: string;\n public abstract readonly entityType: string;\n public abstract readonly schema: EntitySchema<TEntity>;\n public abstract readonly adapter: EntityAdapter<TEntity>;\n private readonly delegate: EntityPluginDelegate<\n TEntity,\n TConfig,\n TConfigInput\n >;\n\n protected constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n ) {\n this.id = id;\n this.version = packageJson.version;\n this.packageName = packageJson.name;\n if (packageJson.description !== undefined) {\n this.description = packageJson.description;\n }\n this.delegate = new EntityPluginDelegate(\n id,\n packageJson,\n config,\n configSchema,\n {\n getEntityType: (): string => this.entityType,\n getSchema: (): EntitySchema<TEntity> => this.schema,\n getAdapter: (): EntityAdapter<TEntity> => this.adapter,\n onRegister: (context): Promise<void> => this.onRegister(context),\n onReady: (context): Promise<void> => this.onReady(context),\n onShutdown: (): Promise<void> => this.onShutdown(),\n getEntityTypeConfig: (): EntityTypeConfig | undefined =>\n this.getEntityTypeConfig(),\n getDataSources: (): DataSource[] => this.getDataSources(),\n getInstructions: (): Promise<string | undefined> =>\n this.getInstructions(),\n interceptCreate: (\n input,\n executionContext,\n context,\n ): Promise<CreateInterceptionResult> =>\n this.interceptCreate(input, executionContext, context),\n },\n );\n }\n\n /** @internal */\n register(\n shell: IShell,\n context?: PluginRegistrationContext,\n ): Promise<PluginCapabilities> {\n return this.delegate.register(shell, context);\n }\n\n protected async onRegister(_context: EntityPluginContext): Promise<void> {}\n protected async onReady(_context: EntityPluginContext): Promise<void> {}\n protected async onShutdown(): Promise<void> {}\n protected async getInstructions(): Promise<string | undefined> {\n return undefined;\n }\n protected getEntityTypeConfig(): EntityTypeConfig | undefined {\n return undefined;\n }\n protected getDataSources(): DataSource[] {\n return [];\n }\n protected async interceptCreate(\n input: CreateInput,\n _executionContext: CreateExecutionContext,\n _context: EntityPluginContext,\n ): Promise<CreateInterceptionResult> {\n return { kind: \"continue\", input };\n }\n\n ready(): Promise<void> {\n return this.delegate.ready();\n }\n\n shutdown(): Promise<void> {\n return this.delegate.shutdown?.() ?? Promise.resolve();\n }\n}\n",
7
7
  "import { InterfacePlugin as RuntimeInterfacePlugin } from \"../interface/interface-plugin\";\nimport type { InterfacePluginContext as RuntimeInterfacePluginContext } from \"../interface/context\";\nimport type { PluginConfigSchema } from \"../config\";\nimport type {\n IShell,\n PluginCapabilities,\n PluginRegistrationContext,\n} from \"../interfaces\";\nimport type { WebRouteDefinition } from \"../types/web-routes\";\nimport type {\n BaseJobTrackingInfo,\n InterfacePluginContext,\n Plugin,\n Resource,\n Tool,\n} from \"./types\";\n\ninterface InterfacePluginHooks {\n onRegister(context: InterfacePluginContext): Promise<void>;\n onReady(context: InterfacePluginContext): Promise<void>;\n onShutdown(): Promise<void>;\n getTools(): Promise<Tool[]>;\n getResources(): Promise<Resource[]>;\n getInstructions(): Promise<string | undefined>;\n getWebRoutes(): WebRouteDefinition[];\n requiresDaemonStartup(): boolean;\n}\n\nclass InterfacePluginDelegate<\n TConfig,\n TConfigInput,\n TTrackingInfo extends BaseJobTrackingInfo,\n> extends RuntimeInterfacePlugin<TConfig, TConfigInput, TTrackingInfo> {\n private readonly hooks: InterfacePluginHooks;\n constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n hooks: InterfacePluginHooks,\n ) {\n super(id, packageJson, config, configSchema);\n this.hooks = hooks;\n }\n\n protected override onRegister(\n context: RuntimeInterfacePluginContext,\n ): Promise<void> {\n return this.hooks.onRegister(context);\n }\n\n protected override onReady(\n context: RuntimeInterfacePluginContext,\n ): Promise<void> {\n return this.hooks.onReady(context);\n }\n\n protected override onShutdown(): Promise<void> {\n return this.hooks.onShutdown();\n }\n\n protected override getTools(): Promise<never[]> {\n return this.hooks.getTools() as Promise<never[]>;\n }\n\n protected override getResources(): Promise<never[]> {\n return this.hooks.getResources() as Promise<never[]>;\n }\n\n protected override getInstructions(): Promise<string | undefined> {\n return this.hooks.getInstructions();\n }\n\n override getWebRoutes(): WebRouteDefinition[] {\n return this.hooks.getWebRoutes();\n }\n\n override requiresDaemonStartup(): boolean {\n return this.hooks.requiresDaemonStartup();\n }\n}\n\nexport abstract class InterfacePlugin<\n TConfig,\n TConfigInput,\n TTrackingInfo extends BaseJobTrackingInfo = BaseJobTrackingInfo,\n> implements Plugin {\n public readonly type = \"interface\" as const;\n public readonly id: string;\n public readonly version: string;\n public readonly packageName: string;\n public readonly description?: string;\n private readonly delegate: InterfacePluginDelegate<\n TConfig,\n TConfigInput,\n TTrackingInfo\n >;\n\n protected constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n ) {\n this.id = id;\n this.version = packageJson.version;\n this.packageName = packageJson.name;\n if (packageJson.description !== undefined) {\n this.description = packageJson.description;\n }\n this.delegate = new InterfacePluginDelegate(\n id,\n packageJson,\n config,\n configSchema,\n {\n onRegister: (context): Promise<void> => this.onRegister(context),\n onReady: (context): Promise<void> => this.onReady(context),\n onShutdown: (): Promise<void> => this.onShutdown(),\n getTools: (): Promise<Tool[]> => this.getTools(),\n getResources: (): Promise<Resource[]> => this.getResources(),\n getInstructions: (): Promise<string | undefined> =>\n this.getInstructions(),\n getWebRoutes: (): WebRouteDefinition[] => this.getWebRoutes(),\n requiresDaemonStartup: (): boolean => this.requiresDaemonStartup(),\n },\n );\n }\n\n /** @internal */\n register(\n shell: IShell,\n context?: PluginRegistrationContext,\n ): Promise<PluginCapabilities> {\n return this.delegate.register(shell, context);\n }\n\n protected async onRegister(_context: InterfacePluginContext): Promise<void> {}\n protected async onReady(_context: InterfacePluginContext): Promise<void> {}\n protected async onShutdown(): Promise<void> {}\n protected async getTools(): Promise<Tool[]> {\n return [];\n }\n protected async getResources(): Promise<Resource[]> {\n return [];\n }\n protected async getInstructions(): Promise<string | undefined> {\n return undefined;\n }\n\n getWebRoutes(): WebRouteDefinition[] {\n return [];\n }\n\n requiresDaemonStartup(): boolean {\n return false;\n }\n\n ready(): Promise<void> {\n return this.delegate.ready();\n }\n\n shutdown(): Promise<void> {\n return this.delegate.shutdown?.() ?? Promise.resolve();\n }\n}\n",
8
8
  "import { MessageInterfacePlugin as RuntimeMessageInterfacePlugin } from \"../message-interface/message-interface-plugin\";\nimport type { InterfacePluginContext as RuntimeInterfacePluginContext } from \"../interface/context\";\nimport type {\n EditMessageRequest,\n SendMessageToChannelRequest,\n SendMessageWithIdRequest,\n} from \"../message-interface/message-interface-plugin\";\nimport type {\n IShell,\n PluginCapabilities,\n PluginRegistrationContext,\n} from \"../interfaces\";\nimport type { WebRouteDefinition } from \"../types/web-routes\";\nimport type { PermissionLookupContext } from \"@brains/templates\";\nimport type { PluginConfigSchema } from \"../config\";\nimport { InterfacePlugin } from \"./interface-plugin\";\nimport type {\n InterfacePluginContext,\n JobProgressEvent,\n MessageJobTrackingInfo,\n Resource,\n Tool,\n} from \"./types\";\n\ninterface MessageInterfacePluginHooks {\n onRegister(context: InterfacePluginContext): Promise<void>;\n onReady(context: InterfacePluginContext): Promise<void>;\n onShutdown(): Promise<void>;\n getTools(): Promise<Tool[]>;\n getResources(): Promise<Resource[]>;\n getInstructions(): Promise<string | undefined>;\n getWebRoutes(): WebRouteDefinition[];\n requiresDaemonStartup(): boolean;\n sendMessageToChannel(request: SendMessageToChannelRequest): void;\n sendMessageWithId(\n request: SendMessageWithIdRequest,\n ): Promise<string | undefined>;\n editMessage(request: EditMessageRequest): Promise<boolean>;\n supportsMessageEditing(): boolean;\n onProgressUpdate(event: JobProgressEvent): Promise<void>;\n}\n\nclass MessageInterfacePluginDelegate<\n TConfig,\n TConfigInput,\n TTrackingInfo extends MessageJobTrackingInfo,\n> extends RuntimeMessageInterfacePlugin<TConfig, TConfigInput, TTrackingInfo> {\n private readonly hooks: MessageInterfacePluginHooks;\n constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n hooks: MessageInterfacePluginHooks,\n ) {\n super(id, packageJson, config, configSchema);\n this.hooks = hooks;\n }\n\n protected override async onRegister(\n context: RuntimeInterfacePluginContext,\n ): Promise<void> {\n await super.onRegister(context);\n await this.hooks.onRegister(context);\n }\n\n protected override onReady(\n context: RuntimeInterfacePluginContext,\n ): Promise<void> {\n return this.hooks.onReady(context);\n }\n\n protected override onShutdown(): Promise<void> {\n return this.hooks.onShutdown();\n }\n\n protected override getTools(): Promise<never[]> {\n return this.hooks.getTools() as Promise<never[]>;\n }\n\n protected override getResources(): Promise<never[]> {\n return this.hooks.getResources() as Promise<never[]>;\n }\n\n protected override getInstructions(): Promise<string | undefined> {\n return this.hooks.getInstructions();\n }\n\n override getWebRoutes(): WebRouteDefinition[] {\n return this.hooks.getWebRoutes();\n }\n\n override requiresDaemonStartup(): boolean {\n return this.hooks.requiresDaemonStartup();\n }\n\n protected override sendMessageToChannel(\n request: SendMessageToChannelRequest,\n ): void {\n this.hooks.sendMessageToChannel(request);\n }\n\n protected override sendMessageWithId(\n request: SendMessageWithIdRequest,\n ): Promise<string | undefined> {\n return this.hooks.sendMessageWithId(request);\n }\n\n protected override editMessage(\n request: EditMessageRequest,\n ): Promise<boolean> {\n return this.hooks.editMessage(request);\n }\n\n protected override supportsMessageEditing(): boolean {\n return this.hooks.supportsMessageEditing();\n }\n\n protected override onProgressUpdate(event: JobProgressEvent): Promise<void> {\n return this.hooks.onProgressUpdate(event);\n }\n\n trackAgentResponseForJobPublic(\n jobId: string,\n messageId: string,\n channelId: string,\n ): void {\n this.trackAgentResponseForJob(jobId, messageId, channelId);\n }\n\n captureUrlViaAgentPublic(\n url: string,\n channelId: string,\n authorId: string,\n interfaceType: string,\n permissionContext?: PermissionLookupContext,\n ): Promise<void> {\n return this.captureUrlViaAgent(\n url,\n channelId,\n authorId,\n interfaceType,\n permissionContext,\n );\n }\n\n getCurrentChannelIdPublic(): string | null {\n return this.getCurrentChannelId();\n }\n}\n\nexport abstract class MessageInterfacePlugin<\n TConfig,\n TConfigInput,\n TTrackingInfo extends MessageJobTrackingInfo = MessageJobTrackingInfo,\n> extends InterfacePlugin<TConfig, TConfigInput, TTrackingInfo> {\n private readonly messageDelegate: MessageInterfacePluginDelegate<\n TConfig,\n TConfigInput,\n TTrackingInfo\n >;\n\n protected constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n ) {\n super(id, packageJson, config, configSchema);\n this.messageDelegate = new MessageInterfacePluginDelegate(\n id,\n packageJson,\n config,\n configSchema,\n {\n onRegister: (context): Promise<void> => this.onRegister(context),\n onReady: (context): Promise<void> => this.onReady(context),\n onShutdown: (): Promise<void> => this.onShutdown(),\n getTools: (): Promise<Tool[]> => this.getTools(),\n getResources: (): Promise<Resource[]> => this.getResources(),\n getInstructions: (): Promise<string | undefined> =>\n this.getInstructions(),\n getWebRoutes: (): WebRouteDefinition[] => this.getWebRoutes(),\n requiresDaemonStartup: (): boolean => this.requiresDaemonStartup(),\n sendMessageToChannel: (request): void =>\n this.sendMessageToChannel(request),\n sendMessageWithId: (request): Promise<string | undefined> =>\n this.sendMessageWithId(request),\n editMessage: (request): Promise<boolean> => this.editMessage(request),\n supportsMessageEditing: (): boolean => this.supportsMessageEditing(),\n onProgressUpdate: (event): Promise<void> =>\n this.onProgressUpdate(event),\n },\n );\n }\n\n /** @internal */\n override register(\n shell: IShell,\n context?: PluginRegistrationContext,\n ): Promise<PluginCapabilities> {\n return this.messageDelegate.register(shell, context);\n }\n\n protected abstract sendMessageToChannel(\n request: SendMessageToChannelRequest,\n ): void;\n\n protected override async onRegister(\n _context: InterfacePluginContext,\n ): Promise<void> {}\n protected override async onReady(\n _context: InterfacePluginContext,\n ): Promise<void> {}\n protected override async onShutdown(): Promise<void> {}\n protected override async getTools(): Promise<Tool[]> {\n return [];\n }\n protected override async getResources(): Promise<Resource[]> {\n return [];\n }\n protected override async getInstructions(): Promise<string | undefined> {\n return undefined;\n }\n protected sendMessageWithId(\n _request: SendMessageWithIdRequest,\n ): Promise<string | undefined> {\n return Promise.resolve(undefined);\n }\n protected editMessage(_request: EditMessageRequest): Promise<boolean> {\n return Promise.resolve(false);\n }\n protected supportsMessageEditing(): boolean {\n return false;\n }\n protected async onProgressUpdate(_event: JobProgressEvent): Promise<void> {}\n\n /** @internal */\n protected isUploadableTextFile(filename: string, mimetype?: string): boolean {\n const textFileExtensions = [\".md\", \".txt\", \".markdown\"];\n const textMimeTypes = [\"text/plain\", \"text/markdown\", \"text/x-markdown\"];\n if (mimetype && textMimeTypes.some((type) => mimetype.startsWith(type))) {\n return true;\n }\n return textFileExtensions.some((extension) =>\n filename.toLowerCase().endsWith(extension),\n );\n }\n\n /** @internal */\n protected isFileSizeAllowed(size: number): boolean {\n return size <= 100_000;\n }\n\n /** @internal */\n protected formatFileUploadMessage(filename: string, content: string): string {\n return `User uploaded a file \"${filename}\":\\n\\n${content}`;\n }\n\n /** @internal */\n protected extractCaptureableUrls(\n content: string,\n blockedDomains: string[],\n ): string[] {\n const matches =\n content.match(/https?:\\/\\/[^\\s<>\"{}|\\\\^`[\\]]+?(?=[,;:\\s]|$)/gi) ?? [];\n return [...new Set(matches)].filter((url) => {\n try {\n const { hostname } = new URL(url);\n return !blockedDomains.some(\n (domain) => hostname === domain || hostname.endsWith(`.${domain}`),\n );\n } catch {\n return false;\n }\n });\n }\n\n /** @internal */\n protected captureUrlViaAgent(\n url: string,\n channelId: string,\n authorId: string,\n interfaceType: string,\n permissionContext?: PermissionLookupContext,\n ): Promise<void> {\n return this.messageDelegate.captureUrlViaAgentPublic(\n url,\n channelId,\n authorId,\n interfaceType,\n permissionContext,\n );\n }\n\n protected trackAgentResponseForJob(\n jobId: string,\n messageId: string,\n channelId: string,\n ): void {\n this.messageDelegate.trackAgentResponseForJobPublic(\n jobId,\n messageId,\n channelId,\n );\n }\n\n public registerProgressCallback(\n callback: (events: JobProgressEvent[]) => void,\n ): void {\n this.messageDelegate.registerProgressCallback(\n callback as (events: JobProgressEvent[]) => void,\n );\n }\n\n public unregisterProgressCallback(): void {\n this.messageDelegate.unregisterProgressCallback();\n }\n\n public getProgressEvents(): JobProgressEvent[] {\n return this.messageDelegate.getProgressEvents() as JobProgressEvent[];\n }\n\n public getActiveProgressEvents(): JobProgressEvent[] {\n return this.messageDelegate.getActiveProgressEvents() as JobProgressEvent[];\n }\n\n public startProcessingInput(channelId: string | null = null): void {\n this.messageDelegate.startProcessingInput(channelId);\n }\n\n public endProcessingInput(): void {\n this.messageDelegate.endProcessingInput();\n }\n\n protected getCurrentChannelId(): string | null {\n return this.messageDelegate.getCurrentChannelIdPublic();\n }\n\n override ready(): Promise<void> {\n return this.messageDelegate.ready();\n }\n\n override shutdown(): Promise<void> {\n return this.messageDelegate.shutdown?.() ?? Promise.resolve();\n }\n}\n",
9
9
  "import { ServicePlugin as RuntimeServicePlugin } from \"../service/service-plugin\";\nimport type { ServicePluginContext as RuntimeServicePluginContext } from \"../service/context\";\nimport type { PluginConfigSchema } from \"../config\";\nimport type {\n IShell,\n PluginCapabilities,\n PluginRegistrationContext,\n} from \"../interfaces\";\nimport type { Plugin, Resource, ServicePluginContext, Tool } from \"./types\";\n\ninterface ServicePluginHooks {\n onRegister(context: ServicePluginContext): Promise<void>;\n onReady(context: ServicePluginContext): Promise<void>;\n onShutdown(): Promise<void>;\n getTools(): Promise<Tool[]>;\n getResources(): Promise<Resource[]>;\n getInstructions(): Promise<string | undefined>;\n}\n\nclass ServicePluginDelegate<TConfig, TConfigInput> extends RuntimeServicePlugin<\n TConfig,\n TConfigInput\n> {\n private readonly hooks: ServicePluginHooks;\n constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n hooks: ServicePluginHooks,\n ) {\n super(id, packageJson, config, configSchema);\n this.hooks = hooks;\n }\n\n protected override onRegister(\n context: RuntimeServicePluginContext,\n ): Promise<void> {\n return this.hooks.onRegister(context);\n }\n\n protected override onReady(\n context: RuntimeServicePluginContext,\n ): Promise<void> {\n return this.hooks.onReady(context);\n }\n\n protected override onShutdown(): Promise<void> {\n return this.hooks.onShutdown();\n }\n\n protected override getTools(): Promise<never[]> {\n return this.hooks.getTools() as Promise<never[]>;\n }\n\n protected override getResources(): Promise<never[]> {\n return this.hooks.getResources() as Promise<never[]>;\n }\n\n protected override getInstructions(): Promise<string | undefined> {\n return this.hooks.getInstructions();\n }\n}\n\nexport abstract class ServicePlugin<TConfig, TConfigInput> implements Plugin {\n public readonly type = \"service\" as const;\n public readonly id: string;\n public readonly version: string;\n public readonly packageName: string;\n public readonly description?: string;\n private readonly delegate: ServicePluginDelegate<TConfig, TConfigInput>;\n\n protected constructor(\n id: string,\n packageJson: { name: string; version: string; description?: string },\n config: TConfigInput,\n configSchema: PluginConfigSchema<TConfig>,\n ) {\n this.id = id;\n this.version = packageJson.version;\n this.packageName = packageJson.name;\n if (packageJson.description !== undefined) {\n this.description = packageJson.description;\n }\n this.delegate = new ServicePluginDelegate(\n id,\n packageJson,\n config,\n configSchema,\n {\n onRegister: (context): Promise<void> => this.onRegister(context),\n onReady: (context): Promise<void> => this.onReady(context),\n onShutdown: (): Promise<void> => this.onShutdown(),\n getTools: (): Promise<Tool[]> => this.getTools(),\n getResources: (): Promise<Resource[]> => this.getResources(),\n getInstructions: (): Promise<string | undefined> =>\n this.getInstructions(),\n },\n );\n }\n\n /** @internal */\n register(\n shell: IShell,\n context?: PluginRegistrationContext,\n ): Promise<PluginCapabilities> {\n return this.delegate.register(shell, context);\n }\n\n protected async onRegister(_context: ServicePluginContext): Promise<void> {}\n protected async onReady(_context: ServicePluginContext): Promise<void> {}\n protected async onShutdown(): Promise<void> {}\n protected async getTools(): Promise<Tool[]> {\n return [];\n }\n protected async getResources(): Promise<Resource[]> {\n return [];\n }\n protected async getInstructions(): Promise<string | undefined> {\n return undefined;\n }\n\n ready(): Promise<void> {\n return this.delegate.ready();\n }\n\n shutdown(): Promise<void> {\n return this.delegate.shutdown?.() ?? Promise.resolve();\n }\n}\n"
10
10
  ],
11
- "mappings": "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",
12
- "debugId": "DB5DF6AAFA5746AF64756E2164756E21",
11
+ "mappings": ";4XA0IO,UAAS,EAA8C,EAC5D,GACsB,EACtB,QAAO,EAGF,SAAS,CAAiC,CAC/C,EACmB,CACnB,OAAO,EAGF,SAAS,CAAwB,CAAC,EAA2B,CAClE,OAAO,IAAS,OAAY,CAAE,QAAS,EAAK,EAAI,CAAE,QAAS,GAAM,MAAK,EAGjE,SAAS,CAAS,CAAC,EAAoC,CAC5D,MAAO,CAAE,QAAS,GAAO,OAAM,EA8D1B,IAAM,EAGR,EAAE,OAAO,CACZ,YAAa,EAAE,QAAQ,EAAE,QAAQ,EAAK,EACtC,kBAAmB,EAChB,MAAM,EAAE,OAAO,CAAC,EAChB,QAAQ,CACP,kBACA,UACA,sBACA,cACA,cACA,eACA,UACA,cACA,aACA,qBACA,uBACA,YACA,YACA,iBACA,SACF,CAAC,CACL,CAAC,EAQM,SAAS,CAA4C,CAC1D,EACA,EAC8B,CAC9B,MAAO,CAAE,OAAM,QAAO,ECtNxB,MAAM,UAII,CAAoD,CAC3C,MACjB,WAAW,CACT,EACA,EACA,EACA,EACA,EACA,CACA,MAAM,EAAI,EAAa,EAAQ,CAAY,EAC3C,KAAK,MAAQ,KAGF,WAAU,EAAW,CAChC,OAAO,KAAK,MAAM,cAAc,KAGrB,OAAM,EAA0B,CAC3C,OAAO,KAAK,MAAM,UAAU,KAGjB,QAAO,EAA2B,CAC7C,OAAO,KAAK,MAAM,WAAW,EAGZ,UAAU,CAC3B,EACe,CACf,OAAO,KAAK,MAAM,WAAW,CAAO,EAGnB,OAAO,CACxB,EACe,CACf,OAAO,KAAK,MAAM,QAAQ,CAAO,EAGhB,UAAU,EAAkB,CAC7C,OAAO,KAAK,MAAM,WAAW,EAGZ,mBAAmB,EAAiC,CACrE,OAAO,KAAK,MAAM,oBAAoB,EAGrB,cAAc,EAAiB,CAChD,OAAO,KAAK,MAAM,eAAe,EAGhB,eAAe,EAAgC,CAChE,OAAO,KAAK,MAAM,gBAAgB,EAGjB,eAAe,CAChC,EACA,EACA,EACmC,CACnC,OAAO,KAAK,MAAM,gBAAgB,EAAO,EAAkB,CAAO,EAEtE,CAEO,MAAe,CAIF,CACF,KAAO,SACP,GACA,QACA,YACA,YAIC,SAMP,WAAW,CACnB,EACA,EACA,EACA,EACA,CAIA,GAHA,KAAK,GAAK,EACV,KAAK,QAAU,EAAY,QAC3B,KAAK,YAAc,EAAY,KAC3B,EAAY,cAAgB,OAC9B,KAAK,YAAc,EAAY,YAEjC,KAAK,SAAW,IAAI,EAClB,EACA,EACA,EACA,EACA,CACE,cAAe,IAAc,KAAK,WAClC,UAAW,IAA6B,KAAK,OAC7C,WAAY,IAA8B,KAAK,QAC/C,WAAY,CAAC,IAA2B,KAAK,WAAW,CAAO,EAC/D,QAAS,CAAC,IAA2B,KAAK,QAAQ,CAAO,EACzD,WAAY,IAAqB,KAAK,WAAW,EACjD,oBAAqB,IACnB,KAAK,oBAAoB,EAC3B,eAAgB,IAAoB,KAAK,eAAe,EACxD,gBAAiB,IACf,KAAK,gBAAgB,EACvB,gBAAiB,CACf,EACA,EACA,IAEA,KAAK,gBAAgB,EAAO,EAAkB,CAAO,CACzD,CACF,EAIF,QAAQ,CACN,EACA,EAC6B,CAC7B,OAAO,KAAK,SAAS,SAAS,EAAO,CAAO,OAG9B,WAAU,CAAC,EAA8C,OACzD,QAAO,CAAC,EAA8C,OACtD,WAAU,EAAkB,OAC5B,gBAAe,EAAgC,CAC7D,OAEQ,mBAAmB,EAAiC,CAC5D,OAEQ,cAAc,EAAiB,CACvC,MAAO,CAAC,OAEM,gBAAe,CAC7B,EACA,EACA,EACmC,CACnC,MAAO,CAAE,KAAM,WAAY,OAAM,EAGnC,KAAK,EAAkB,CACrB,OAAO,KAAK,SAAS,MAAM,EAG7B,QAAQ,EAAkB,CACxB,OAAO,KAAK,SAAS,WAAW,GAAK,QAAQ,QAAQ,EAEzD,CC1KA,MAAM,UAII,CAA6D,CACpD,MACjB,WAAW,CACT,EACA,EACA,EACA,EACA,EACA,CACA,MAAM,EAAI,EAAa,EAAQ,CAAY,EAC3C,KAAK,MAAQ,EAGI,UAAU,CAC3B,EACe,CACf,OAAO,KAAK,MAAM,WAAW,CAAO,EAGnB,OAAO,CACxB,EACe,CACf,OAAO,KAAK,MAAM,QAAQ,CAAO,EAGhB,UAAU,EAAkB,CAC7C,OAAO,KAAK,MAAM,WAAW,EAGZ,QAAQ,EAAqB,CAC9C,OAAO,KAAK,MAAM,SAAS,EAGV,YAAY,EAAqB,CAClD,OAAO,KAAK,MAAM,aAAa,EAGd,eAAe,EAAgC,CAChE,OAAO,KAAK,MAAM,gBAAgB,EAG3B,YAAY,EAAyB,CAC5C,OAAO,KAAK,MAAM,aAAa,EAGxB,qBAAqB,EAAY,CACxC,OAAO,KAAK,MAAM,sBAAsB,EAE5C,CAEO,MAAe,CAIF,CACF,KAAO,YACP,GACA,QACA,YACA,YACC,SAMP,WAAW,CACnB,EACA,EACA,EACA,EACA,CAIA,GAHA,KAAK,GAAK,EACV,KAAK,QAAU,EAAY,QAC3B,KAAK,YAAc,EAAY,KAC3B,EAAY,cAAgB,OAC9B,KAAK,YAAc,EAAY,YAEjC,KAAK,SAAW,IAAI,EAClB,EACA,EACA,EACA,EACA,CACE,WAAY,CAAC,IAA2B,KAAK,WAAW,CAAO,EAC/D,QAAS,CAAC,IAA2B,KAAK,QAAQ,CAAO,EACzD,WAAY,IAAqB,KAAK,WAAW,EACjD,SAAU,IAAuB,KAAK,SAAS,EAC/C,aAAc,IAA2B,KAAK,aAAa,EAC3D,gBAAiB,IACf,KAAK,gBAAgB,EACvB,aAAc,IAA4B,KAAK,aAAa,EAC5D,sBAAuB,IAAe,KAAK,sBAAsB,CACnE,CACF,EAIF,QAAQ,CACN,EACA,EAC6B,CAC7B,OAAO,KAAK,SAAS,SAAS,EAAO,CAAO,OAG9B,WAAU,CAAC,EAAiD,OAC5D,QAAO,CAAC,EAAiD,OACzD,WAAU,EAAkB,OAC5B,SAAQ,EAAoB,CAC1C,MAAO,CAAC,OAEM,aAAY,EAAwB,CAClD,MAAO,CAAC,OAEM,gBAAe,EAAgC,CAC7D,OAGF,YAAY,EAAyB,CACnC,MAAO,CAAC,EAGV,qBAAqB,EAAY,CAC/B,MAAO,GAGT,KAAK,EAAkB,CACrB,OAAO,KAAK,SAAS,MAAM,EAG7B,QAAQ,EAAkB,CACxB,OAAO,KAAK,SAAS,WAAW,GAAK,QAAQ,QAAQ,EAEzD,CC3HA,MAAM,UAII,CAAoE,CAC3D,MACjB,WAAW,CACT,EACA,EACA,EACA,EACA,EACA,CACA,MAAM,EAAI,EAAa,EAAQ,CAAY,EAC3C,KAAK,MAAQ,OAGU,WAAU,CACjC,EACe,CACf,MAAM,MAAM,WAAW,CAAO,EAC9B,MAAM,KAAK,MAAM,WAAW,CAAO,EAGlB,OAAO,CACxB,EACe,CACf,OAAO,KAAK,MAAM,QAAQ,CAAO,EAGhB,UAAU,EAAkB,CAC7C,OAAO,KAAK,MAAM,WAAW,EAGZ,QAAQ,EAAqB,CAC9C,OAAO,KAAK,MAAM,SAAS,EAGV,YAAY,EAAqB,CAClD,OAAO,KAAK,MAAM,aAAa,EAGd,eAAe,EAAgC,CAChE,OAAO,KAAK,MAAM,gBAAgB,EAG3B,YAAY,EAAyB,CAC5C,OAAO,KAAK,MAAM,aAAa,EAGxB,qBAAqB,EAAY,CACxC,OAAO,KAAK,MAAM,sBAAsB,EAGvB,oBAAoB,CACrC,EACM,CACN,KAAK,MAAM,qBAAqB,CAAO,EAGtB,iBAAiB,CAClC,EAC6B,CAC7B,OAAO,KAAK,MAAM,kBAAkB,CAAO,EAG1B,WAAW,CAC5B,EACkB,CAClB,OAAO,KAAK,MAAM,YAAY,CAAO,EAGpB,sBAAsB,EAAY,CACnD,OAAO,KAAK,MAAM,uBAAuB,EAGxB,gBAAgB,CAAC,EAAwC,CAC1E,OAAO,KAAK,MAAM,iBAAiB,CAAK,EAG1C,8BAA8B,CAC5B,EACA,EACA,EACM,CACN,KAAK,yBAAyB,EAAO,EAAW,CAAS,EAG3D,wBAAwB,CACtB,EACA,EACA,EACA,EACA,EACe,CACf,OAAO,KAAK,mBACV,EACA,EACA,EACA,EACA,CACF,EAGF,yBAAyB,EAAkB,CACzC,OAAO,KAAK,oBAAoB,EAEpC,CAEO,MAAe,UAIZ,CAAsD,CAC7C,gBAMP,WAAW,CACnB,EACA,EACA,EACA,EACA,CACA,MAAM,EAAI,EAAa,EAAQ,CAAY,EAC3C,KAAK,gBAAkB,IAAI,EACzB,EACA,EACA,EACA,EACA,CACE,WAAY,CAAC,IAA2B,KAAK,WAAW,CAAO,EAC/D,QAAS,CAAC,IAA2B,KAAK,QAAQ,CAAO,EACzD,WAAY,IAAqB,KAAK,WAAW,EACjD,SAAU,IAAuB,KAAK,SAAS,EAC/C,aAAc,IAA2B,KAAK,aAAa,EAC3D,gBAAiB,IACf,KAAK,gBAAgB,EACvB,aAAc,IAA4B,KAAK,aAAa,EAC5D,sBAAuB,IAAe,KAAK,sBAAsB,EACjE,qBAAsB,CAAC,IACrB,KAAK,qBAAqB,CAAO,EACnC,kBAAmB,CAAC,IAClB,KAAK,kBAAkB,CAAO,EAChC,YAAa,CAAC,IAA8B,KAAK,YAAY,CAAO,EACpE,uBAAwB,IAAe,KAAK,uBAAuB,EACnE,iBAAkB,CAAC,IACjB,KAAK,iBAAiB,CAAK,CAC/B,CACF,EAIO,QAAQ,CACf,EACA,EAC6B,CAC7B,OAAO,KAAK,gBAAgB,SAAS,EAAO,CAAO,OAO5B,WAAU,CACjC,EACe,OACQ,QAAO,CAC9B,EACe,OACQ,WAAU,EAAkB,OAC5B,SAAQ,EAAoB,CACnD,MAAO,CAAC,OAEe,aAAY,EAAwB,CAC3D,MAAO,CAAC,OAEe,gBAAe,EAAgC,CACtE,OAEQ,iBAAiB,CACzB,EAC6B,CAC7B,OAAO,QAAQ,QAAQ,MAAS,EAExB,WAAW,CAAC,EAAgD,CACpE,OAAO,QAAQ,QAAQ,EAAK,EAEpB,sBAAsB,EAAY,CAC1C,MAAO,QAEO,iBAAgB,CAAC,EAAyC,EAGhE,oBAAoB,CAAC,EAAkB,EAA4B,CAC3E,IAAM,EAAqB,CAAC,MAAO,OAAQ,WAAW,EAEtD,GAAI,GADkB,CAAC,aAAc,gBAAiB,iBAAiB,EACzC,KAAK,CAAC,IAAS,EAAS,WAAW,CAAI,CAAC,EACpE,MAAO,GAET,OAAO,EAAmB,KAAK,CAAC,IAC9B,EAAS,YAAY,EAAE,SAAS,CAAS,CAC3C,EAIQ,iBAAiB,CAAC,EAAuB,CACjD,OAAO,GAAQ,IAIP,uBAAuB,CAAC,EAAkB,EAAyB,CAC3E,MAAO,yBAAyB;AAAA;AAAA,EAAiB,IAIzC,sBAAsB,CAC9B,EACA,EACU,CACV,IAAM,EACJ,EAAQ,MAAM,gDAAgD,GAAK,CAAC,EACtE,MAAO,CAAC,GAAG,IAAI,IAAI,CAAO,CAAC,EAAE,OAAO,CAAC,IAAQ,CAC3C,GAAI,CACF,IAAQ,YAAa,IAAI,IAAI,CAAG,EAChC,MAAO,CAAC,EAAe,KACrB,CAAC,IAAW,IAAa,GAAU,EAAS,SAAS,IAAI,GAAQ,CACnE,EACA,KAAM,CACN,MAAO,IAEV,EAIO,kBAAkB,CAC1B,EACA,EACA,EACA,EACA,EACe,CACf,OAAO,KAAK,gBAAgB,yBAC1B,EACA,EACA,EACA,EACA,CACF,EAGQ,wBAAwB,CAChC,EACA,EACA,EACM,CACN,KAAK,gBAAgB,+BACnB,EACA,EACA,CACF,EAGK,wBAAwB,CAC7B,EACM,CACN,KAAK,gBAAgB,yBACnB,CACF,EAGK,0BAA0B,EAAS,CACxC,KAAK,gBAAgB,2BAA2B,EAG3C,iBAAiB,EAAuB,CAC7C,OAAO,KAAK,gBAAgB,kBAAkB,EAGzC,uBAAuB,EAAuB,CACnD,OAAO,KAAK,gBAAgB,wBAAwB,EAG/C,oBAAoB,CAAC,EAA2B,KAAY,CACjE,KAAK,gBAAgB,qBAAqB,CAAS,EAG9C,kBAAkB,EAAS,CAChC,KAAK,gBAAgB,mBAAmB,EAGhC,mBAAmB,EAAkB,CAC7C,OAAO,KAAK,gBAAgB,0BAA0B,EAG/C,KAAK,EAAkB,CAC9B,OAAO,KAAK,gBAAgB,MAAM,EAG3B,QAAQ,EAAkB,CACjC,OAAO,KAAK,gBAAgB,WAAW,GAAK,QAAQ,QAAQ,EAEhE,CCvUA,MAAM,UAAqD,CAGzD,CACiB,MACjB,WAAW,CACT,EACA,EACA,EACA,EACA,EACA,CACA,MAAM,EAAI,EAAa,EAAQ,CAAY,EAC3C,KAAK,MAAQ,EAGI,UAAU,CAC3B,EACe,CACf,OAAO,KAAK,MAAM,WAAW,CAAO,EAGnB,OAAO,CACxB,EACe,CACf,OAAO,KAAK,MAAM,QAAQ,CAAO,EAGhB,UAAU,EAAkB,CAC7C,OAAO,KAAK,MAAM,WAAW,EAGZ,QAAQ,EAAqB,CAC9C,OAAO,KAAK,MAAM,SAAS,EAGV,YAAY,EAAqB,CAClD,OAAO,KAAK,MAAM,aAAa,EAGd,eAAe,EAAgC,CAChE,OAAO,KAAK,MAAM,gBAAgB,EAEtC,CAEO,MAAe,CAAuD,CAC3D,KAAO,UACP,GACA,QACA,YACA,YACC,SAEP,WAAW,CACnB,EACA,EACA,EACA,EACA,CAIA,GAHA,KAAK,GAAK,EACV,KAAK,QAAU,EAAY,QAC3B,KAAK,YAAc,EAAY,KAC3B,EAAY,cAAgB,OAC9B,KAAK,YAAc,EAAY,YAEjC,KAAK,SAAW,IAAI,EAClB,EACA,EACA,EACA,EACA,CACE,WAAY,CAAC,IAA2B,KAAK,WAAW,CAAO,EAC/D,QAAS,CAAC,IAA2B,KAAK,QAAQ,CAAO,EACzD,WAAY,IAAqB,KAAK,WAAW,EACjD,SAAU,IAAuB,KAAK,SAAS,EAC/C,aAAc,IAA2B,KAAK,aAAa,EAC3D,gBAAiB,IACf,KAAK,gBAAgB,CACzB,CACF,EAIF,QAAQ,CACN,EACA,EAC6B,CAC7B,OAAO,KAAK,SAAS,SAAS,EAAO,CAAO,OAG9B,WAAU,CAAC,EAA+C,OAC1D,QAAO,CAAC,EAA+C,OACvD,WAAU,EAAkB,OAC5B,SAAQ,EAAoB,CAC1C,MAAO,CAAC,OAEM,aAAY,EAAwB,CAClD,MAAO,CAAC,OAEM,gBAAe,EAAgC,CAC7D,OAGF,KAAK,EAAkB,CACrB,OAAO,KAAK,SAAS,MAAM,EAG7B,QAAQ,EAAkB,CACxB,OAAO,KAAK,SAAS,WAAW,GAAK,QAAQ,QAAQ,EAEzD",
12
+ "debugId": "2CD50E0186B5245F64756E2164756E21",
13
13
  "names": []
14
14
  }
@@ -315,6 +315,12 @@ interface ICoreEntityService {
315
315
  getEntityRaw<T extends BaseEntity>(request: GetEntityRawRequest): Promise<T | null>;
316
316
  listEntities<T extends BaseEntity>(request: ListEntitiesRequest): Promise<T[]>;
317
317
  search<T extends BaseEntity = BaseEntity>(request: EntitySearchRequest): Promise<SearchResult<T>[]>;
318
+ /** Return embedded entities with raw cosine distance to a query. */
319
+ searchWithDistances(request: SearchWithDistancesRequest): Promise<Array<{
320
+ entityId: string;
321
+ entityType: string;
322
+ distance: number;
323
+ }>>;
318
324
  /** Project visible entities into a provider-independent semantic space. */
319
325
  projectSemanticSpace(request: ProjectSemanticSpaceRequest): Promise<SemanticSpaceProjection>;
320
326
  getEntityTypes(): string[];