diff --git a/apps/server/src/core/skills/SkillManager.ts b/apps/server/src/core/skills/SkillManager.ts index 238f6f88..fd8594ef 100644 --- a/apps/server/src/core/skills/SkillManager.ts +++ b/apps/server/src/core/skills/SkillManager.ts @@ -10,6 +10,7 @@ import { SkillRegistry, SkillSelector, loadSkillMarkdownFile, + resolveBuiltinSkillsDirectory, parseSkillMarkdown, type LoadedSkillContext, type SignedSkillRegistryEntry, @@ -22,7 +23,7 @@ import { listSkillFiles, type ParsedSkillFile } from './parser'; import { logger } from '../../utils/logger'; import { getConfig } from '../../config'; -const DEFAULT_BUILTIN_DIR = path.resolve(process.cwd(), 'apps/server/src/core/skills/builtins'); +const DEFAULT_BUILTIN_DIR = resolveBuiltinSkillsDirectory(); function skillDataRoot(): string { return path.resolve( diff --git a/docs/guides/releases.md b/docs/guides/releases.md index 70b09ee0..1b713027 100644 --- a/docs/guides/releases.md +++ b/docs/guides/releases.md @@ -11,6 +11,9 @@ or operate a Server. The complete v1.0.0 package atlas is available in the - All public `@codesoul-co/hypha-*` packages in one release use the same Semantic Version. - Internal `@codesoul-co/hypha-*` dependencies use the exact release version. - Each package publishes only `dist/` plus npm-generated metadata. +- `@codesoul-co/hypha-skills` additionally ships the framework built-in skills + (`builtins/`) and exposes `resolveBuiltinSkillsDirectory()` so npm consumers can load + `context-enrichment` and `intent-classification` without a Server source checkout. - Node.js 22 or newer is required. - `npm run release:check:npm` builds package output, verifies declared source dependencies, checks package metadata, and validates the files that `npm pack` would include. diff --git a/apps/server/src/core/skills/builtins/context-enrichment.md b/packages/skills/builtins/context-enrichment.md similarity index 100% rename from apps/server/src/core/skills/builtins/context-enrichment.md rename to packages/skills/builtins/context-enrichment.md diff --git a/apps/server/src/core/skills/builtins/intent-classification.md b/packages/skills/builtins/intent-classification.md similarity index 100% rename from apps/server/src/core/skills/builtins/intent-classification.md rename to packages/skills/builtins/intent-classification.md diff --git a/packages/skills/package.json b/packages/skills/package.json index bc529ded..b4f91d4f 100644 --- a/packages/skills/package.json +++ b/packages/skills/package.json @@ -12,7 +12,8 @@ } }, "files": [ - "dist" + "dist", + "builtins" ], "publishConfig": { "access": "public" diff --git a/packages/skills/src/builtin-skills.test.ts b/packages/skills/src/builtin-skills.test.ts new file mode 100644 index 00000000..4a8ca96f --- /dev/null +++ b/packages/skills/src/builtin-skills.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from 'vitest'; +import { + LocalSkillLoader, + SkillRegistry, + resolveBuiltinSkillsDirectory, +} from './index'; + +describe('packaged built-in skills', () => { + it('resolves the builtins directory shipped inside the package', () => { + const directory = resolveBuiltinSkillsDirectory(); + expect(directory.endsWith('builtins')).toBe(true); + expect(directory).toContain('packages'); + expect(directory).toContain('skills'); + }); + + it('loads both framework built-in skills from the packaged directory', async () => { + const registry = new SkillRegistry(); + const loader = new LocalSkillLoader({ + directories: [resolveBuiltinSkillsDirectory()], + recursive: true, + }); + const skills = await loader.loadInto(registry); + const ids = skills.map((skill) => skill.id).sort(); + expect(ids).toEqual(['context-enrichment', 'intent-classification']); + expect(registry.get('context-enrichment')).toMatchObject({ version: '1.0.0' }); + expect(registry.get('intent-classification')).toMatchObject({ version: '1.0.0' }); + }); +}); diff --git a/packages/skills/src/index.ts b/packages/skills/src/index.ts index 0f374b5a..857f1cd1 100644 --- a/packages/skills/src/index.ts +++ b/packages/skills/src/index.ts @@ -21,6 +21,18 @@ import { export * from './remote-registry'; +/** + * Resolves the directory that ships Hypha's built-in skills + * (context-enrichment, intent-classification) inside this npm package. + * + * The published tarball includes `builtins/` next to `dist/`, so consumers + * can load the framework built-ins without a source checkout of the Server. + */ +export function resolveBuiltinSkillsDirectory(): string { + // Compiled CJS output lives in /dist; the shipped data lives in /builtins. + return path.resolve(__dirname, '..', 'builtins'); +} + export interface SkillRef { id: string; version?: string; diff --git a/packages/skills/src/skills.test.ts b/packages/skills/src/skills.test.ts index ce358a60..22a6bee1 100644 --- a/packages/skills/src/skills.test.ts +++ b/packages/skills/src/skills.test.ts @@ -6,6 +6,7 @@ import { DefaultSkillPolicy, createEffectiveAgentCapabilitySnapshot, LocalSkillLoader, + resolveBuiltinSkillsDirectory, SkillContextLoader, SkillRegistry, SkillResolver, @@ -209,7 +210,7 @@ describe('@codesoul-co/hypha-skills resolver', () => { it('loads a real local markdown skill and activates it progressively', async () => { const registry = new SkillRegistry(); const loader = new LocalSkillLoader({ - directories: ['apps/server/src/core/skills/builtins'], + directories: [resolveBuiltinSkillsDirectory()], recursive: false, }); await loader.loadInto(registry);