import type { Skill, SkillManifest, SkillSource, SkillResources } from './types.js'; /** 懒加载配置 */ interface LazyLoadConfig { /** content LRU 缓存容量(默认 30) */ cacheSize?: number; /** 是否在启动时就加载 content(false=懒加载,默认 true 保持向后兼容) */ lazy?: boolean; /** * 懒物化钩子(按需物化):技能包资源首次访问时(ensureMaterialized)由宿主将 * DB 权威文件写出到 packageDir。未注入时维持「调用方自行物化」的旧语义。 */ lazyMaterializer?: (skillId: string, packageDir: string) => void | Promise; } export declare class SkillManager { /** 轻量清单索引(仅 front matter,不含 content) */ private manifests; /** * 名称索引:name/alias(小写)→ manifest 存储 key(id)。 * 用于支持按 name 查找 Skill(DB 源以 name 为唯一标识,更扁平)。 */ private nameIndex; /** content LRU 缓存(懒加载时按需填充) */ private contentCache; /** 嵌套子包扫描结果缓存:packageDir -> Skill[] */ private nestedSkillsCache; /** 是否启用懒加载 */ private lazy; /** 懒物化钩子(按需物化):技能包资源首次访问时由宿主将 DB 权威文件写出到 packageDir */ private lazyMaterializer?; /** 物化进行中的 Promise 去重表(key 为物化动作粒度:父包 storageId) */ private materializeInFlight; /** 记录加载的目录,用于 reload */ private loadedDirs; constructor(config?: LazyLoadConfig); /** * 将连接器 ID 和 Skill ID 拼接为内部存储 key * 格式:`{connectorId}__{skillId}` */ static connectorSkillKey(connectorId: string, skillId: string): string; /** * 拆分连接器 Skill key,返回 [connectorId, skillId],无连接器则返回 null */ static splitConnectorSkillKey(key: string): [string, string] | null; /** * 从目录加载 Skill 文件 * * - lazy=true:仅解析 front matter(manifest),不读 content,毫秒级完成 * - lazy=false(默认):全量读取,保持向后兼容 */ loadFromDir(dir: string, source: SkillSource, connectorId?: string): void; /** 扫描目录包的资源清单(scripts/ references/ assets/ skills/),返回相对路径(POSIX 风格) */ static scanPackageResources(packageDir: string): SkillResources; /** 扫描嵌套子包(skills/ 目录下的子目录含 SKILL.md) */ private static scanNestedPackages; /** * 扫描嵌套子包并返回完整的 Skill 对象列表 * @param parentPkgDir 父包的物化目录 * @param parentRuntimeId 父包的运行时 ID * @param parentPath 父包的 path * @returns 嵌套子包列表 */ static scanNestedSkills(parentPkgDir: string, parentRuntimeId: string, parentPath: string): Skill[]; /** * 加载单个标准目录包(含 SKILL.md 的目录)。 * 自动扫描资源目录并注册资源清单。 * @param relId 相对于加载根目录的嵌套 id(如 `master-investment/modules/zk-strategy`); * 无连接器时直接作为 storageId,确保不同层级的同名目录互不覆盖。 */ loadPackageDir(packageDir: string, relId: string, source: SkillSource, connectorId?: string): void; /** 手动注册 Skill(全量,含 content) */ register(skill: Skill): void; /** * 将 manifest 的 name / aliases 建立到 nameIndex,支持按 name 查找。 * 同名下后注册的覆盖前者(DB 唯一约束保证 name 不冲突,这里仅防御重复)。 */ private indexManifest; /** 注销 Skill */ unregister(id: string): void; /** * 获取指定 Skill(含 content) * * - 缓存命中:直接返回 * - 缓存未命中 + 有 filePath:从磁盘懒加载 content * - 缓存未命中 + 无 filePath:返回空 content(仅 manifest) */ get(id: string): Skill | undefined; /** * 获取 Skill 清单(不含 content,用于路由目录构建和 UI 展示) */ getManifest(id: string): SkillManifest | undefined; /** * 解析 Skill:支持按存储 id 或 name/alias 查找。 * name 查找不区分大小写。 */ private resolveManifest; private resolveManifestEntry; /** * 获取所有 Skill 清单(不含 content) * 适用于 SkillRouter 构建路由目录、Engine 构建 skill catalog、UI 列表展示 */ getAllManifests(): SkillManifest[]; /** * 将位于 fromRoot 下的技能包目录整体重定向到 toRoot(跨会话复用 server 时刷新沙箱根)。 * 仅重映射 packageDir/filePath 的根前缀,保持相对层级不变; * 不在 fromRoot 下的技能(连接器技能、文件模式共享目录)不受影响。 * @returns 重定向的技能数量 */ rebasePackageDirs(fromRoot: string, toRoot: string): number; /** 获取所有已注册 Skill(含 content,触发懒加载) */ getAll(): Skill[]; /** 按标签过滤 */ getByTag(tag: string): Skill[]; /** 检查某个目录是否已在加载列表中 */ hasLoadedDir(dir: string): boolean; /** 获取缓存统计信息 */ getCacheStats(): { manifestCount: number; cachedContentCount: number; lazyMode: boolean; }; /** * 确保技能包已物化到磁盘(按需物化入口)。 * * 「DB 权威 + 按需物化」模型下,注册阶段仅注入 manifest(packageDir 指向线程沙箱 * 目标位置,磁盘文件可尚不存在)。首次访问技能资源(run_skill_script / * read_skill_reference / list_skill_resources / load_skill 懒加载正文)前调用本方法: * - packageDir 下 SKILL.md 已存在:已物化,直接返回 true; * - 不存在且注入了 lazyMaterializer:回调宿主物化(如 work-space 从 DB 写出文件), * 成功后刷新该包 resources 清单,并增量注册磁盘嵌套子包(`parentId/subDir` 形态 ID); * - 未注入钩子或物化失败:返回 false,维持「资源未找到」的既有失败语义。 * * 幂等:重复调用仅首次触发写盘。 * 并发去重:同一次物化动作(含嵌套子包与其父包)并发首访时共享同一进行中的 * Promise,仅首次触发宿主写盘(物化底层 rmSync + 逐文件写盘非原子,并发交错 * 执行可致对方读到半成品或 ENOENT)。 * * @param skillIdOrName 技能 id / name / alias / 嵌套子包 id * @returns 物化后 packageDir 下 SKILL.md 是否存在(无 packageDir 的技能恒为 false) */ ensureMaterialized(skillIdOrName: string): Promise; /** * 执行一次物化动作(仅由 ensureMaterialized 的发起者调用,并发等待者共享其结果): * 调用宿主钩子写盘 -> 二次校验发起者 SKILL.md -> 刷新其资源清单并增量注册嵌套子包。 */ private runMaterialize; /** * 已物化但资源清单为空(注册期磁盘目录未就绪)时补扫刷新,幂等。 * 清单非空(管理端显式注入或此前已扫描)时不覆盖。 */ private refreshEmptyResources; /** * 注册 Skill 包的资源清单与根目录(标准目录包形态)。 * 供管理端注入运行时 Skill 时调用,或 loadFromDir 扫描目录包时自动调用。 */ registerPackageResources(skillId: string, resources: SkillResources, packageDir: string): void; /** 列出 Skill 的资源清单(无则返回 null) */ listResources(skillIdOrName: string): SkillResources | null; /** * 按需加载 Skill 资源文件文本内容(references/ assets/ 等)。 * 仅允许读取 packageDir 内的文件,含路径穿越防护。 */ loadResource(skillIdOrName: string, resourcePath: string): string | null; /** 获取资源文件绝对路径(供执行/二进制读取),含路径穿越防护 */ resolveResourcePathByName(skillIdOrName: string, resourcePath: string): string | null; /** 解析脚本绝对路径(scripts/ 下),供脚本执行工具调用 */ resolveScriptPath(skillIdOrName: string, scriptRel: string): string | null; /** 内部:解析并校验资源路径,确保位于 packageDir 内(防路径穿越) */ private resolveResourcePath; /** 重新加载(文件变更后刷新) */ reload(): void; /** * 清除嵌套子包缓存 * @param packageDir 包目录路径,不传则清除所有缓存 */ clearNestedSkillsCache(packageDir?: string): void; /** * 获取嵌套子包缓存统计信息 */ getNestedSkillsCacheStats(): { size: number; keys: string[]; }; /** * 从磁盘懒加载 content * 支持 Markdown 文件(含 front matter)和纯文本 */ private loadContent; /** * 预加载引用的 Skills(referencedSkills) * 当某个 Skill 被加载时,自动加载它引用的其他 Skills */ private preloadReferencedSkills; /** 从 Skill 对象提取清单,保留 content(供未物化时回退,见 get 方法) */ private toManifest; /** * 仅解析 front matter(不读 content),用于懒加载模式 * 通过读取文件前 32KB 提取 YAML front matter,避免加载整个文件。 * 使用标准解析器,兼容嵌套 map / 多行折叠语法。 */ private parseManifest; /** * 由解析后的 frontmatter data 构建 SkillManifest(公共逻辑,parse/parseManifest 复用)。 * content 字段由调用方按需补充(parse 全量 / parseManifest 仅清单)。 */ private buildManifest; /** 解析完整的 Markdown 文件(含 content),用于兼容模式 */ private parse; } export {}; //# sourceMappingURL=manager.d.ts.map