@compilr-dev/sdk 0.10.2 → 0.10.4

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.
package/dist/index.d.ts CHANGED
@@ -68,7 +68,9 @@ export { createPlatformTools, createProjectTools, createWorkItemTools, createDoc
68
68
  export type { ProjectAnchorStoreConfig, ImageToolsConfig, ImageResizer } from './platform/index.js';
69
69
  export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, isValidTransition, getStepCriteria, formatStepDisplay, getStepNumber, } from './platform/index.js';
70
70
  export type { CustomSkill, CompilrSkillExtension, ForkedFromMarker, SkillEligibilityContext, SkillCollision, SkillDiffLine, SkillValidationIssue, ScopeConfig, SkillResolution, } from './skills/index.js';
71
- export { RESERVED_SKILL_NAMES, isReservedSkillName, parseSkillMarkdown, loadSkillsFromDir, resolveLayeredSkills, resolveSkillsForAgent, detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill as validateSkillQuality, } from './skills/index.js';
71
+ export { RESERVED_SKILL_NAMES, isReservedSkillName, parseSkillMarkdown, loadSkillsFromDir, resolveLayeredSkills, resolveSkillsForAgent, detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill as validateSkillQuality, getSkillsDir, getSkillFolder, getSkillFile, ensureSkillsDir, isValidSkillName, getScopeConfigPath, readSkillScopeConfig, readSkillScopeConfigSync, writeSkillScopeConfig, getSkillBindings, resolveSkillBinding, } from './skills/index.js';
72
+ export type { SkillScope, SkillPromptResolution, AvailableSkillEntry, SkillSources, } from './skills/index.js';
73
+ export { resolveSkillPrompt, getAllAvailableSkills } from './skills/index.js';
72
74
  export { platformSkills, designSkill, sketchSkill, prdSkill, refineSkill, refineItemSkill, architectureSkill, sessionNotesSkill, buildSkill, scaffoldSkill, outlineSkill, literatureReviewSkill, draftSectionSkill, peerReviewSkill, researchScaffoldSkill, businessVisionSkill, marketAnalysisSkill, competitorAnalysisSkill, financialModelSkill, pitchOutlineSkill, businessReviewSkill, brandSetupSkill, contentStrategySkill, contentCalendarSkill, createContentSkill, contentReviewSkill, curriculumDesignSkill, lessonPlanSkill, assessmentDesignSkill, courseReviewSkill, bookOutlineSkill, characterDesignSkill, plotThreadsSkill, sceneBreakdownSkill, bookReviewSkill, } from './skills/index.js';
73
75
  export { ACTION_REGISTRY, getActionsForContext, getActionById, resolveActionPrompt, buildContextSummary, getSuggestedRole, } from './actions/index.js';
74
76
  export type { ActionContext, ActionDefinition } from './actions/index.js';
package/dist/index.js CHANGED
@@ -152,7 +152,8 @@ export { createPlatformTools, createProjectTools, createWorkItemTools, createDoc
152
152
  // Platform Workflow (pure step-criteria logic)
153
153
  // =============================================================================
154
154
  export { STEP_ORDER, GUIDED_STEP_CRITERIA, getNextStep, isValidTransition, getStepCriteria, formatStepDisplay, getStepNumber, } from './platform/index.js';
155
- export { RESERVED_SKILL_NAMES, isReservedSkillName, parseSkillMarkdown, loadSkillsFromDir, resolveLayeredSkills, resolveSkillsForAgent, detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill as validateSkillQuality, } from './skills/index.js';
155
+ export { RESERVED_SKILL_NAMES, isReservedSkillName, parseSkillMarkdown, loadSkillsFromDir, resolveLayeredSkills, resolveSkillsForAgent, detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill as validateSkillQuality, getSkillsDir, getSkillFolder, getSkillFile, ensureSkillsDir, isValidSkillName, getScopeConfigPath, readSkillScopeConfig, readSkillScopeConfigSync, writeSkillScopeConfig, getSkillBindings, resolveSkillBinding, } from './skills/index.js';
156
+ export { resolveSkillPrompt, getAllAvailableSkills } from './skills/index.js';
156
157
  export { platformSkills, designSkill, sketchSkill, prdSkill, refineSkill, refineItemSkill, architectureSkill, sessionNotesSkill, buildSkill, scaffoldSkill, outlineSkill, literatureReviewSkill, draftSectionSkill, peerReviewSkill, researchScaffoldSkill, businessVisionSkill, marketAnalysisSkill, competitorAnalysisSkill, financialModelSkill, pitchOutlineSkill, businessReviewSkill, brandSetupSkill, contentStrategySkill, contentCalendarSkill, createContentSkill, contentReviewSkill, curriculumDesignSkill, lessonPlanSkill, assessmentDesignSkill, courseReviewSkill, bookOutlineSkill, characterDesignSkill, plotThreadsSkill, sceneBreakdownSkill, bookReviewSkill, } from './skills/index.js';
157
158
  // =============================================================================
158
159
  // Contextual Actions (skill invocations with context)
@@ -8,4 +8,8 @@ export type { SkillEligibilityContext } from './resolver.js';
8
8
  export { resolveLayeredSkills, resolveSkillsForAgent } from './resolver.js';
9
9
  export type { SkillCollision, SkillDiffLine, SkillValidationIssue, ScopeConfig, SkillResolution, } from './operations.js';
10
10
  export { detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill, } from './operations.js';
11
+ export type { SkillScope } from './paths.js';
12
+ export { getSkillsDir, getSkillFolder, getSkillFile, ensureSkillsDir, isValidSkillName, getScopeConfigPath, readScopeConfig as readSkillScopeConfig, readScopeConfigSync as readSkillScopeConfigSync, writeScopeConfig as writeSkillScopeConfig, getAllBindings as getSkillBindings, resolveBinding as resolveSkillBinding, } from './paths.js';
13
+ export type { SkillPromptResolution, AvailableSkillEntry, SkillSources, } from './prompt-resolver.js';
14
+ export { resolveSkillPrompt, getAllAvailableSkills } from './prompt-resolver.js';
11
15
  export { platformSkills, designSkill, sketchSkill, prdSkill, refineSkill, refineItemSkill, architectureSkill, sessionNotesSkill, buildSkill, scaffoldSkill, outlineSkill, literatureReviewSkill, draftSectionSkill, peerReviewSkill, researchScaffoldSkill, businessVisionSkill, marketAnalysisSkill, competitorAnalysisSkill, financialModelSkill, pitchOutlineSkill, businessReviewSkill, brandSetupSkill, contentStrategySkill, contentCalendarSkill, createContentSkill, contentReviewSkill, curriculumDesignSkill, lessonPlanSkill, assessmentDesignSkill, courseReviewSkill, bookOutlineSkill, characterDesignSkill, plotThreadsSkill, sceneBreakdownSkill, bookReviewSkill, } from './platform-skills.js';
@@ -2,4 +2,6 @@ export { RESERVED_SKILL_NAMES, isReservedSkillName } from './types.js';
2
2
  export { parseSkillMarkdown, loadSkillsFromDir } from './loader.js';
3
3
  export { resolveLayeredSkills, resolveSkillsForAgent } from './resolver.js';
4
4
  export { detectCollisions, formatCollisionWarnings, diffForkVsUpstream, buildForkContent, buildNewSkillContent, validateSkill, } from './operations.js';
5
+ export { getSkillsDir, getSkillFolder, getSkillFile, ensureSkillsDir, isValidSkillName, getScopeConfigPath, readScopeConfig as readSkillScopeConfig, readScopeConfigSync as readSkillScopeConfigSync, writeScopeConfig as writeSkillScopeConfig, getAllBindings as getSkillBindings, resolveBinding as resolveSkillBinding, } from './paths.js';
6
+ export { resolveSkillPrompt, getAllAvailableSkills } from './prompt-resolver.js';
5
7
  export { platformSkills, designSkill, sketchSkill, prdSkill, refineSkill, refineItemSkill, architectureSkill, sessionNotesSkill, buildSkill, scaffoldSkill, outlineSkill, literatureReviewSkill, draftSectionSkill, peerReviewSkill, researchScaffoldSkill, businessVisionSkill, marketAnalysisSkill, competitorAnalysisSkill, financialModelSkill, pitchOutlineSkill, businessReviewSkill, brandSetupSkill, contentStrategySkill, contentCalendarSkill, createContentSkill, contentReviewSkill, curriculumDesignSkill, lessonPlanSkill, assessmentDesignSkill, courseReviewSkill, bookOutlineSkill, characterDesignSkill, plotThreadsSkill, sceneBreakdownSkill, bookReviewSkill, } from './platform-skills.js';
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Skill path resolution and config I/O.
3
+ *
4
+ * Portable across CLI and Desktop — takes explicit paths instead of
5
+ * relying on CLI-specific project detection.
6
+ */
7
+ export type SkillScope = 'user' | 'project';
8
+ /** Resolve the skills directory for a given scope. */
9
+ export declare function getSkillsDir(scope: SkillScope, projectDir?: string): string;
10
+ /** Ensure the skills directory exists. Returns the path. */
11
+ export declare function ensureSkillsDir(scope: SkillScope, projectDir?: string): Promise<string>;
12
+ /** Path to a single skill folder (no creation). */
13
+ export declare function getSkillFolder(name: string, scope: SkillScope, projectDir?: string): string;
14
+ /** Path to a skill's SKILL.md file. */
15
+ export declare function getSkillFile(name: string, scope: SkillScope, projectDir?: string): string;
16
+ /**
17
+ * Validate a skill name. Lowercase letters, digits, and hyphens only.
18
+ */
19
+ export declare function isValidSkillName(name: string): boolean;
20
+ /** Shape of <scope>/.compilr/config.json */
21
+ export interface ScopeConfig {
22
+ slashCommands?: Record<string, string>;
23
+ }
24
+ /** Path to the scope config file. */
25
+ export declare function getScopeConfigPath(scope: SkillScope, projectDir?: string): string;
26
+ /** Read the scope config asynchronously. Returns empty object if file doesn't exist. */
27
+ export declare function readScopeConfig(scope: SkillScope, projectDir?: string): Promise<ScopeConfig>;
28
+ /** Read the scope config synchronously. Returns empty object if file doesn't exist. */
29
+ export declare function readScopeConfigSync(scope: SkillScope, projectDir?: string): ScopeConfig;
30
+ /** Write the scope config. Creates parent directories if needed. */
31
+ export declare function writeScopeConfig(scope: SkillScope, config: ScopeConfig, projectDir?: string): Promise<void>;
32
+ /** Get all bindings across both scopes (project takes priority). */
33
+ export declare function getAllBindings(projectDir?: string): Promise<Record<string, {
34
+ skillName: string;
35
+ scope: SkillScope;
36
+ }>>;
37
+ /**
38
+ * Resolve a command name to a bound skill name via config.json.
39
+ * Synchronous — config files are tiny.
40
+ */
41
+ export declare function resolveBinding(commandName: string, projectDir?: string): string | null;
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Skill path resolution and config I/O.
3
+ *
4
+ * Portable across CLI and Desktop — takes explicit paths instead of
5
+ * relying on CLI-specific project detection.
6
+ */
7
+ import * as os from 'node:os';
8
+ import * as path from 'node:path';
9
+ import { promises as fs } from 'node:fs';
10
+ import { readFileSync } from 'node:fs';
11
+ // =============================================================================
12
+ // Path Resolution
13
+ // =============================================================================
14
+ /** Resolve the skills directory for a given scope. */
15
+ export function getSkillsDir(scope, projectDir) {
16
+ if (scope === 'user') {
17
+ return path.join(os.homedir(), '.compilr-dev', 'skills');
18
+ }
19
+ if (!projectDir)
20
+ throw new Error('projectDir required for project scope');
21
+ return path.join(projectDir, '.compilr', 'skills');
22
+ }
23
+ /** Ensure the skills directory exists. Returns the path. */
24
+ export async function ensureSkillsDir(scope, projectDir) {
25
+ const dir = getSkillsDir(scope, projectDir);
26
+ await fs.mkdir(dir, { recursive: true });
27
+ return dir;
28
+ }
29
+ /** Path to a single skill folder (no creation). */
30
+ export function getSkillFolder(name, scope, projectDir) {
31
+ return path.join(getSkillsDir(scope, projectDir), name);
32
+ }
33
+ /** Path to a skill's SKILL.md file. */
34
+ export function getSkillFile(name, scope, projectDir) {
35
+ return path.join(getSkillFolder(name, scope, projectDir), 'SKILL.md');
36
+ }
37
+ /**
38
+ * Validate a skill name. Lowercase letters, digits, and hyphens only.
39
+ */
40
+ export function isValidSkillName(name) {
41
+ if (!name || name.length === 0 || name.length > 64)
42
+ return false;
43
+ return /^[a-z][a-z0-9-]*$/.test(name);
44
+ }
45
+ /** Path to the scope config file. */
46
+ export function getScopeConfigPath(scope, projectDir) {
47
+ if (scope === 'user') {
48
+ return path.join(os.homedir(), '.compilr-dev', 'config.json');
49
+ }
50
+ if (!projectDir)
51
+ throw new Error('projectDir required for project scope');
52
+ return path.join(projectDir, '.compilr', 'config.json');
53
+ }
54
+ /** Read the scope config asynchronously. Returns empty object if file doesn't exist. */
55
+ export async function readScopeConfig(scope, projectDir) {
56
+ try {
57
+ const content = await fs.readFile(getScopeConfigPath(scope, projectDir), 'utf-8');
58
+ return JSON.parse(content);
59
+ }
60
+ catch {
61
+ return {};
62
+ }
63
+ }
64
+ /** Read the scope config synchronously. Returns empty object if file doesn't exist. */
65
+ export function readScopeConfigSync(scope, projectDir) {
66
+ try {
67
+ const content = readFileSync(getScopeConfigPath(scope, projectDir), 'utf-8');
68
+ return JSON.parse(content);
69
+ }
70
+ catch {
71
+ return {};
72
+ }
73
+ }
74
+ /** Write the scope config. Creates parent directories if needed. */
75
+ export async function writeScopeConfig(scope, config, projectDir) {
76
+ const configPath = getScopeConfigPath(scope, projectDir);
77
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
78
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2) + '\n');
79
+ }
80
+ /** Get all bindings across both scopes (project takes priority). */
81
+ export async function getAllBindings(projectDir) {
82
+ const result = {};
83
+ const userConfig = await readScopeConfig('user');
84
+ if (userConfig.slashCommands) {
85
+ for (const [cmd, skill] of Object.entries(userConfig.slashCommands)) {
86
+ result[cmd] = { skillName: skill, scope: 'user' };
87
+ }
88
+ }
89
+ if (projectDir) {
90
+ const projectConfig = await readScopeConfig('project', projectDir);
91
+ if (projectConfig.slashCommands) {
92
+ for (const [cmd, skill] of Object.entries(projectConfig.slashCommands)) {
93
+ result[cmd] = { skillName: skill, scope: 'project' };
94
+ }
95
+ }
96
+ }
97
+ return result;
98
+ }
99
+ // =============================================================================
100
+ // Binding Resolution
101
+ // =============================================================================
102
+ /**
103
+ * Resolve a command name to a bound skill name via config.json.
104
+ * Synchronous — config files are tiny.
105
+ */
106
+ export function resolveBinding(commandName, projectDir) {
107
+ if (projectDir) {
108
+ const projectConfig = readScopeConfigSync('project', projectDir);
109
+ if (projectConfig.slashCommands?.[commandName]) {
110
+ return projectConfig.slashCommands[commandName];
111
+ }
112
+ }
113
+ const userConfig = readScopeConfigSync('user');
114
+ if (userConfig.slashCommands?.[commandName]) {
115
+ return userConfig.slashCommands[commandName];
116
+ }
117
+ return null;
118
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Unified skill prompt resolver — used by both CLI and Desktop.
3
+ *
4
+ * Resolves a slash command name to a skill prompt using:
5
+ * 1. Binding resolution (config.json slashCommands)
6
+ * 2. 5-layer priority: project → user → SDK platform → agents builtin → agents-coding
7
+ *
8
+ * Also provides getAllAvailableSkills() for autocomplete/picker display.
9
+ */
10
+ import type { ForkedFromMarker } from './types.js';
11
+ /** Result of resolving a skill prompt */
12
+ export interface SkillPromptResolution {
13
+ /** The resolved skill prompt text */
14
+ prompt: string;
15
+ /** The skill name that provided the prompt (may differ from input if bound) */
16
+ skillName: string;
17
+ /** Whether this was resolved via a config.json binding */
18
+ isBound: boolean;
19
+ /** Fork info if the resolved skill is forked from an SDK skill */
20
+ forkedFrom?: ForkedFromMarker;
21
+ /** Source layer where the skill was found */
22
+ source?: 'project' | 'user' | 'sdk' | 'agents' | 'agents-coding' | 'factory';
23
+ }
24
+ /** Entry in the available skills list (for autocomplete/picker) */
25
+ export interface AvailableSkillEntry {
26
+ /** Skill name (used as slash command) */
27
+ name: string;
28
+ /** Human-readable description */
29
+ description: string;
30
+ /** Where this skill comes from */
31
+ source: 'project' | 'user' | 'sdk' | 'agents' | 'binding';
32
+ /** Scope for custom skills */
33
+ scope?: 'user' | 'project';
34
+ /** Whether the skill is enabled (custom skills only) */
35
+ enabled?: boolean;
36
+ /** Whether the skill has validation warnings */
37
+ hasWarnings?: boolean;
38
+ /** For binding entries: the command name */
39
+ boundCommand?: string;
40
+ /** Whether this is a forked skill */
41
+ isForked?: boolean;
42
+ }
43
+ /** Additional skill sources that consumers can provide */
44
+ export interface SkillSources {
45
+ /** Factory skills (from @compilr-dev/factory) */
46
+ factorySkills?: readonly {
47
+ name: string;
48
+ description: string;
49
+ prompt: string;
50
+ }[];
51
+ /** Coding skills (from @compilr-dev/agents-coding) */
52
+ codingSkills?: readonly {
53
+ name: string;
54
+ description: string;
55
+ prompt: string;
56
+ }[];
57
+ }
58
+ /**
59
+ * Resolve a slash command name to a skill prompt.
60
+ *
61
+ * Resolution order:
62
+ * 1. Check bindings (config.json slashCommands — project overrides user)
63
+ * 2. Project-scoped custom skills (<projectDir>/.compilr/skills/)
64
+ * 3. User-scoped custom skills (~/.compilr-dev/skills/)
65
+ * 4. SDK platform skills
66
+ * 5. Additional sources (factory, agents builtin, agents-coding)
67
+ *
68
+ * @param name - The slash command name (without leading /)
69
+ * @param projectDir - Project directory for project-scoped skills and bindings
70
+ * @param sources - Additional skill sources (factory, coding)
71
+ * @returns Resolution result with prompt and metadata, or null if not found
72
+ */
73
+ export declare function resolveSkillPrompt(name: string, projectDir?: string, sources?: SkillSources): SkillPromptResolution | null;
74
+ /**
75
+ * Get all available skills for display (autocomplete, picker, help menu).
76
+ *
77
+ * Returns a deduplicated list from all sources with metadata.
78
+ * Project skills override user skills override SDK skills (by name).
79
+ *
80
+ * @param projectDir - Project directory for project-scoped skills and bindings
81
+ * @param sources - Additional skill sources (factory, coding)
82
+ * @returns List of all available skills with source and metadata
83
+ */
84
+ export declare function getAllAvailableSkills(projectDir?: string, sources?: SkillSources): AvailableSkillEntry[];
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Unified skill prompt resolver — used by both CLI and Desktop.
3
+ *
4
+ * Resolves a slash command name to a skill prompt using:
5
+ * 1. Binding resolution (config.json slashCommands)
6
+ * 2. 5-layer priority: project → user → SDK platform → agents builtin → agents-coding
7
+ *
8
+ * Also provides getAllAvailableSkills() for autocomplete/picker display.
9
+ */
10
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { parseSkillMarkdown } from './loader.js';
13
+ import { resolveBinding, getSkillsDir, readScopeConfigSync } from './paths.js';
14
+ import { platformSkills } from './platform-skills.js';
15
+ // Re-export builtinSkills from agents (available via SDK re-export)
16
+ // The SDK re-exports builtinSkills from @compilr-dev/agents
17
+ import { builtinSkills } from '@compilr-dev/agents';
18
+ // =============================================================================
19
+ // Prompt Resolution
20
+ // =============================================================================
21
+ /**
22
+ * Read a skill prompt from a scoped directory (project or user).
23
+ * Returns null if the skill doesn't exist, is disabled, or has malformed frontmatter.
24
+ */
25
+ function readScopedSkillPrompt(scope, name, projectDir) {
26
+ try {
27
+ const file = join(getSkillsDir(scope, projectDir), name, 'SKILL.md');
28
+ if (!existsSync(file))
29
+ return null;
30
+ const content = readFileSync(file, 'utf-8');
31
+ const parsed = parseSkillMarkdown(content);
32
+ if (!parsed || parsed.enabled === false)
33
+ return null;
34
+ return parsed.prompt;
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ /**
41
+ * Read the forkedFrom marker from a scoped skill.
42
+ */
43
+ function readScopedSkillForkedFrom(scope, name, projectDir) {
44
+ try {
45
+ const file = join(getSkillsDir(scope, projectDir), name, 'SKILL.md');
46
+ const content = readFileSync(file, 'utf-8');
47
+ const parsed = parseSkillMarkdown(content);
48
+ return parsed?.forkedFrom ?? null;
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ /**
55
+ * Resolve a slash command name to a skill prompt.
56
+ *
57
+ * Resolution order:
58
+ * 1. Check bindings (config.json slashCommands — project overrides user)
59
+ * 2. Project-scoped custom skills (<projectDir>/.compilr/skills/)
60
+ * 3. User-scoped custom skills (~/.compilr-dev/skills/)
61
+ * 4. SDK platform skills
62
+ * 5. Additional sources (factory, agents builtin, agents-coding)
63
+ *
64
+ * @param name - The slash command name (without leading /)
65
+ * @param projectDir - Project directory for project-scoped skills and bindings
66
+ * @param sources - Additional skill sources (factory, coding)
67
+ * @returns Resolution result with prompt and metadata, or null if not found
68
+ */
69
+ export function resolveSkillPrompt(name, projectDir, sources) {
70
+ // 1. Check bindings
71
+ const boundName = resolveBinding(name, projectDir);
72
+ if (boundName && boundName !== name) {
73
+ for (const scope of ['project', 'user']) {
74
+ const prompt = readScopedSkillPrompt(scope, boundName, projectDir);
75
+ if (prompt) {
76
+ const forkedFrom = readScopedSkillForkedFrom(scope, boundName, projectDir);
77
+ return {
78
+ prompt,
79
+ skillName: boundName,
80
+ isBound: true,
81
+ forkedFrom: forkedFrom ?? undefined,
82
+ source: scope,
83
+ };
84
+ }
85
+ }
86
+ // Bound skill not found — fall through to normal resolution
87
+ }
88
+ // 2. Project-scoped custom skills
89
+ if (projectDir) {
90
+ const prompt = readScopedSkillPrompt('project', name, projectDir);
91
+ if (prompt) {
92
+ return { prompt, skillName: name, isBound: false, source: 'project' };
93
+ }
94
+ }
95
+ // 3. User-scoped custom skills
96
+ {
97
+ const prompt = readScopedSkillPrompt('user', name);
98
+ if (prompt) {
99
+ return { prompt, skillName: name, isBound: false, source: 'user' };
100
+ }
101
+ }
102
+ // 4. SDK platform skills
103
+ const sdkSkill = platformSkills.find((s) => s.name === name);
104
+ if (sdkSkill) {
105
+ return { prompt: sdkSkill.prompt, skillName: name, isBound: false, source: 'sdk' };
106
+ }
107
+ // 5. Additional sources
108
+ if (sources?.factorySkills) {
109
+ const factorySkill = sources.factorySkills.find((s) => s.name === name);
110
+ if (factorySkill) {
111
+ return { prompt: factorySkill.prompt, skillName: name, isBound: false, source: 'factory' };
112
+ }
113
+ }
114
+ const agentsSkill = builtinSkills.find((s) => s.name === name);
115
+ if (agentsSkill) {
116
+ return { prompt: agentsSkill.prompt, skillName: name, isBound: false, source: 'agents' };
117
+ }
118
+ if (sources?.codingSkills) {
119
+ const codingSkill = sources.codingSkills.find((s) => s.name === name);
120
+ if (codingSkill) {
121
+ return {
122
+ prompt: codingSkill.prompt,
123
+ skillName: name,
124
+ isBound: false,
125
+ source: 'agents-coding',
126
+ };
127
+ }
128
+ }
129
+ return null;
130
+ }
131
+ // =============================================================================
132
+ // Available Skills List
133
+ // =============================================================================
134
+ /**
135
+ * Get all available skills for display (autocomplete, picker, help menu).
136
+ *
137
+ * Returns a deduplicated list from all sources with metadata.
138
+ * Project skills override user skills override SDK skills (by name).
139
+ *
140
+ * @param projectDir - Project directory for project-scoped skills and bindings
141
+ * @param sources - Additional skill sources (factory, coding)
142
+ * @returns List of all available skills with source and metadata
143
+ */
144
+ export function getAllAvailableSkills(projectDir, sources) {
145
+ const entries = [];
146
+ const seen = new Set();
147
+ // 1. Custom skills (project + user)
148
+ for (const scope of ['project', 'user']) {
149
+ try {
150
+ const dir = getSkillsDir(scope, scope === 'project' ? projectDir : undefined);
151
+ const dirEntries = readdirSync(dir, { withFileTypes: true });
152
+ for (const entry of dirEntries) {
153
+ if (!entry.isDirectory() || seen.has(entry.name))
154
+ continue;
155
+ seen.add(entry.name);
156
+ try {
157
+ const content = readFileSync(join(dir, entry.name, 'SKILL.md'), 'utf-8');
158
+ const parsed = parseSkillMarkdown(content);
159
+ if (parsed) {
160
+ entries.push({
161
+ name: parsed.name,
162
+ description: parsed.description,
163
+ source: scope,
164
+ scope,
165
+ enabled: parsed.enabled !== false,
166
+ hasWarnings: parsed.description.length < 60 || !parsed.prompt.trim(),
167
+ isForked: !!parsed.forkedFrom,
168
+ });
169
+ }
170
+ }
171
+ catch {
172
+ /* skip malformed */
173
+ }
174
+ }
175
+ }
176
+ catch {
177
+ /* dir doesn't exist */
178
+ }
179
+ }
180
+ // 2. SDK platform skills
181
+ for (const skill of platformSkills) {
182
+ if (!seen.has(skill.name)) {
183
+ seen.add(skill.name);
184
+ entries.push({ name: skill.name, description: skill.description, source: 'sdk' });
185
+ }
186
+ }
187
+ // 3. Agents builtin skills
188
+ for (const skill of builtinSkills) {
189
+ if (!seen.has(skill.name)) {
190
+ seen.add(skill.name);
191
+ entries.push({ name: skill.name, description: skill.description, source: 'agents' });
192
+ }
193
+ }
194
+ // 4. Additional sources
195
+ if (sources?.factorySkills) {
196
+ for (const skill of sources.factorySkills) {
197
+ if (!seen.has(skill.name)) {
198
+ seen.add(skill.name);
199
+ entries.push({ name: skill.name, description: skill.description, source: 'sdk' });
200
+ }
201
+ }
202
+ }
203
+ if (sources?.codingSkills) {
204
+ for (const skill of sources.codingSkills) {
205
+ if (!seen.has(skill.name)) {
206
+ seen.add(skill.name);
207
+ entries.push({ name: skill.name, description: skill.description, source: 'agents' });
208
+ }
209
+ }
210
+ }
211
+ // 5. Bound commands (as separate entries)
212
+ for (const scope of ['project', 'user']) {
213
+ try {
214
+ const config = readScopeConfigSync(scope, scope === 'project' ? projectDir : undefined);
215
+ if (config.slashCommands) {
216
+ for (const [cmd, skillName] of Object.entries(config.slashCommands)) {
217
+ if (!seen.has(cmd)) {
218
+ seen.add(cmd);
219
+ entries.push({
220
+ name: cmd,
221
+ description: `→ ${skillName} [${scope} binding]`,
222
+ source: 'binding',
223
+ scope,
224
+ boundCommand: cmd,
225
+ });
226
+ }
227
+ }
228
+ }
229
+ }
230
+ catch {
231
+ /* skip */
232
+ }
233
+ }
234
+ return entries;
235
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/sdk",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "description": "Universal agent runtime for building AI-powered applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -58,6 +58,7 @@
58
58
  "dependencies": {
59
59
  "@compilr-dev/agents": "^0.5.7",
60
60
  "@compilr-dev/logger": "^0.1.0",
61
+ "@compilr-dev/sdk": "^0.10.2",
61
62
  "ajv": "^6.14.0",
62
63
  "yaml": "^2.8.4"
63
64
  },