@deimoscloud/coreai 0.1.16 → 0.1.18

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/cli/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/index.ts
4
- import { join as join14, dirname as dirname7 } from "path";
4
+ import { join as join14, dirname as dirname8 } from "path";
5
5
  import { fileURLToPath as fileURLToPath2 } from "url";
6
6
  import { Command } from "commander";
7
7
 
8
8
  // src/index.ts
9
9
  import { readFileSync as readFileSync7 } from "fs";
10
- import { dirname as dirname5, join as join8 } from "path";
10
+ import { dirname as dirname6, join as join8 } from "path";
11
11
  import { fileURLToPath } from "url";
12
12
 
13
13
  // src/config/loader.ts
@@ -442,7 +442,7 @@ function resolveAgentDefinition(agent, config, options = {}) {
442
442
 
443
443
  // src/agents/compiler.ts
444
444
  import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
445
- import { join as join3, dirname as dirname2, extname as extname2 } from "path";
445
+ import { join as join3, dirname as dirname2, extname as extname2, isAbsolute } from "path";
446
446
  import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
447
447
  function buildAgentTools(agent, mcpServers) {
448
448
  const tools = agent.tools ? [...agent.tools] : [...DEFAULT_AGENT_TOOLS];
@@ -456,16 +456,44 @@ function buildAgentTools(agent, mcpServers) {
456
456
  }
457
457
  return tools.join(", ");
458
458
  }
459
+ function processIncludes(template, templateDir, depth = 0, maxDepth = 3) {
460
+ if (depth > maxDepth) {
461
+ throw new Error(`Include depth exceeded maximum of ${maxDepth}`);
462
+ }
463
+ const includePattern = /<!--\s*include:\s*(\S+)\s*-->/g;
464
+ return template.replace(includePattern, (_match, includePath) => {
465
+ const resolvedPath = isAbsolute(includePath) ? includePath : join3(templateDir, includePath);
466
+ if (!existsSync3(resolvedPath)) {
467
+ throw new Error(`Include file not found: ${includePath} (resolved to ${resolvedPath})`);
468
+ }
469
+ const includedContent = readFileSync3(resolvedPath, "utf-8");
470
+ return processIncludes(includedContent, dirname2(resolvedPath), depth + 1, maxDepth);
471
+ });
472
+ }
459
473
  function processAgentTemplate(templatePath, agent, config, mcpServers) {
460
474
  const template = readFileSync3(templatePath, "utf-8");
461
- const context = { agent };
475
+ const templateDir = dirname2(templatePath);
476
+ const expandedTemplate = processIncludes(template, templateDir);
477
+ const earlyMatch = expandedTemplate.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
478
+ if (!earlyMatch) {
479
+ throw new Error(`Invalid markdown format in ${templatePath}: no frontmatter found`);
480
+ }
481
+ const earlyFrontmatter = parseYaml3(earlyMatch[1]);
482
+ const reservedKeys = /* @__PURE__ */ new Set(["name", "description", "tools"]);
483
+ const extendedAgent = { ...agent };
484
+ for (const [key, value] of Object.entries(earlyFrontmatter)) {
485
+ if (!reservedKeys.has(key) && !(key in extendedAgent)) {
486
+ extendedAgent[key] = value;
487
+ }
488
+ }
489
+ const context = { agent: extendedAgent };
462
490
  if (config) {
463
491
  context.config = config;
464
492
  }
465
- const resolved = resolveString(template, context);
493
+ const resolved = resolveString(expandedTemplate, context);
466
494
  const frontmatterMatch = resolved.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
467
495
  if (!frontmatterMatch) {
468
- throw new Error(`Invalid markdown format in ${templatePath}: no frontmatter found`);
496
+ throw new Error(`Invalid markdown format after resolution in ${templatePath}`);
469
497
  }
470
498
  const frontmatterYaml = frontmatterMatch[1];
471
499
  const body = frontmatterMatch[2] ?? "";
@@ -1876,469 +1904,123 @@ var CacheManager = class {
1876
1904
 
1877
1905
  // src/skills/generator.ts
1878
1906
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync } from "fs";
1879
- import { join as join6, basename as basename2 } from "path";
1880
-
1881
- // src/skills/templates.ts
1882
- var checkInboxSkill = {
1883
- name: "check-inbox",
1884
- description: "Check your inbox for pending tasks and messages",
1885
- category: "core",
1886
- content: `---
1887
- description: Check your inbox for pending tasks and messages
1888
- ---
1889
-
1890
- # Check Inbox
1891
-
1892
- Check the inbox at \`KnowledgeLibrary/{{AGENT_NAME}}/inbox/\` for new messages.
1893
-
1894
- ## Instructions
1895
-
1896
- 1. Read all unprocessed messages in the inbox directory
1897
- 2. For each message:
1898
- - Parse the frontmatter (type, from, date, priority)
1899
- - Understand the request or task
1900
- - Take appropriate action based on message type
1901
- 3. After processing, move message to \`inbox/processed/\`
1902
- 4. Update your context file at \`KnowledgeLibrary/{{AGENT_NAME}}/context/current.txt\`
1903
-
1904
- ## Message Types
1905
-
1906
- - **task-assignment**: New work assigned to you
1907
- - **completion-report**: Another agent completed work
1908
- - **review-request**: Code review needed
1909
- - **feedback**: Response to your previous work
1910
-
1911
- ## Output Format
1912
-
1913
- Report what messages were processed and actions taken.
1914
- `
1915
- };
1916
- var delegateSkill = {
1917
- name: "delegate",
1918
- description: "Delegate a task to another agent via inbox messaging",
1919
- argumentHint: "<task-description> to <agent-name>",
1920
- category: "core",
1921
- content: `---
1922
- description: Delegate a task to another agent via inbox messaging
1923
- argument-hint: <task-description> to <agent-name>
1924
- ---
1925
-
1926
- # Delegate Task
1927
-
1928
- Delegate work to another agent using the inbox-based messaging system.
1929
-
1930
- ## CRITICAL: Do NOT use the Task tool
1931
-
1932
- Agent-to-agent delegation MUST use file-based messaging, not the Task tool.
1933
- The Task tool spawns subagents that lose MCP access.
1934
-
1935
- ## Instructions
1936
-
1937
- 1. Parse the delegation request to identify:
1938
- - The task to delegate
1939
- - The target agent
1940
-
1941
- 2. Create a message file in the target agent's inbox:
1942
- - Path: \`KnowledgeLibrary/<target-agent>/inbox/\`
1943
- - Filename: \`YYYYMMDD_HHMM-{{AGENT_NAME}}-<subject>.md\`
1944
-
1945
- 3. Use this message format:
1946
- \`\`\`markdown
1947
- ---
1948
- type: task-assignment
1949
- from: {{AGENT_NAME}}
1950
- to: <target-agent>
1951
- date: YYYY-MM-DD HH:MM
1952
- priority: P2
1953
- ---
1954
-
1955
- ## Task Assignment
1956
-
1957
- ### Description
1958
- <Clear description of what needs to be done>
1959
-
1960
- ### Context
1961
- <Any relevant context or background>
1962
-
1963
- ### Expected Deliverables
1964
- 1. <Deliverable 1>
1965
- 2. <Deliverable 2>
1966
-
1967
- ### Success Criteria
1968
- - <Criterion 1>
1969
- - <Criterion 2>
1970
- \`\`\`
1971
-
1972
- 4. Tell the user to invoke the target agent:
1973
- "Please invoke @<target-agent> to process this task."
1974
-
1975
- ## Output
1976
-
1977
- Confirm the delegation message was created and instruct user to invoke the agent.
1978
- `
1979
- };
1980
- var gitCommitSkill = {
1981
- name: "git-commit",
1982
- description: "Create a quality-gated git commit",
1983
- argumentHint: "<commit-message>",
1984
- category: "core",
1985
- dependencies: [{ type: "git", required: false, description: "For commit operations" }],
1986
- content: `---
1987
- description: Create a quality-gated git commit
1988
- argument-hint: <commit-message>
1989
- optional: [git]
1990
- ---
1991
-
1992
- # Git Commit
1993
-
1994
- Create a git commit after passing all quality gates.
1995
-
1996
- ## Quality Gates
1997
-
1998
- Run these checks before committing:
1999
-
2000
- 1. **Lint**: \`{{LINT_CMD}}\`
2001
- 2. **Tests**: \`{{TEST_CMD}}\`
2002
- 3. **Build**: \`{{BUILD_CMD}}\`
2003
-
2004
- ## Instructions
2005
-
2006
- 1. Stage the relevant files with \`git add\`
2007
- 2. Run all quality gate commands
2008
- 3. If any gate fails:
2009
- - Fix the issues
2010
- - Re-run the failed gate
2011
- - Continue only when all pass
2012
- 4. Create the commit with the provided message
2013
- 5. Format: Include ticket reference if applicable
2014
-
2015
- ## Commit Message Format
2016
-
2017
- \`\`\`
2018
- <type>(<scope>): <description>
2019
-
2020
- [optional body]
2021
-
2022
- [optional footer]
2023
- \`\`\`
2024
-
2025
- Types: feat, fix, docs, style, refactor, test, chore
2026
-
2027
- ## Fallbacks
2028
-
2029
- If quality gate commands are not configured:
2030
- - Ask the user what commands to run
2031
- - Or skip gates with user confirmation
2032
- `
2033
- };
2034
- var prCreateSkill = {
2035
- name: "pr-create",
2036
- description: "Create a pull request with proper format",
2037
- argumentHint: "[branch-name]",
2038
- category: "core",
2039
- dependencies: [{ type: "git", required: true, description: "For PR creation" }],
2040
- content: `---
2041
- description: Create a pull request with proper format
2042
- argument-hint: [branch-name]
2043
- requires: [git]
2044
- ---
2045
-
2046
- # Create Pull Request
2047
-
2048
- Create a well-formatted pull request for the current branch.
2049
-
2050
- ## Instructions
2051
-
2052
- 1. Ensure all changes are committed
2053
- 2. Push the branch to remote
2054
- 3. Create PR with proper format:
2055
-
2056
- \`\`\`markdown
2057
- ## Summary
2058
- <Brief description of changes>
2059
-
2060
- ## Changes
2061
- - <Change 1>
2062
- - <Change 2>
2063
-
2064
- ## Test Plan
2065
- - [ ] <Test case 1>
2066
- - [ ] <Test case 2>
2067
-
2068
- ## Related Issues
2069
- Closes {{JIRA_PROJECT}}-XXX
2070
- \`\`\`
2071
-
2072
- 4. Request reviewers if specified
2073
-
2074
- ## Using GitHub CLI
2075
-
2076
- \`\`\`bash
2077
- gh pr create --title "<title>" --body "<body>"
2078
- \`\`\`
2079
-
2080
- ## Output
2081
-
2082
- Provide the PR URL and summary of what was created.
2083
- `
2084
- };
2085
- var reviewSkill = {
2086
- name: "review",
2087
- description: "Request or perform a code review",
2088
- argumentHint: "<pr-number-or-url>",
2089
- category: "core",
2090
- dependencies: [{ type: "git", required: true, description: "For PR review" }],
2091
- content: `---
2092
- description: Request or perform a code review
2093
- argument-hint: <pr-number-or-url>
2094
- requires: [git]
2095
- ---
2096
-
2097
- # Code Review
2098
-
2099
- Review a pull request or delegate review to a specialist.
2100
-
2101
- ## Instructions
2102
-
2103
- ### If you are reviewing:
2104
-
2105
- 1. Fetch the PR details and diff
2106
- 2. Review for:
2107
- - Code quality and style
2108
- - Logic errors or bugs
2109
- - Security concerns
2110
- - Test coverage
2111
- - Documentation
2112
- 3. Provide feedback with specific line references
2113
- 4. Approve, request changes, or comment
2114
-
2115
- ### If delegating to a reviewer:
2116
-
2117
- 1. Identify the appropriate reviewer based on the changes
2118
- 2. Create a review request message in their inbox
2119
- 3. Include PR link and context
2120
-
2121
- ## Review Checklist
2122
-
2123
- - [ ] Code follows project conventions
2124
- - [ ] No obvious bugs or edge cases
2125
- - [ ] Tests cover the changes
2126
- - [ ] Documentation updated if needed
2127
- - [ ] No security vulnerabilities
2128
-
2129
- ## Output
2130
-
2131
- Provide review summary with actionable feedback.
2132
- `
2133
- };
2134
- var sprintStatusSkill = {
2135
- name: "sprint-status",
2136
- description: "Get current sprint status and progress",
2137
- category: "optional",
2138
- dependencies: [{ type: "issue_tracker", required: true, description: "For sprint data" }],
2139
- content: `---
2140
- description: Get current sprint status and progress
2141
- requires: [issue_tracker]
2142
- ---
2143
-
2144
- # Sprint Status
2145
-
2146
- Get the current sprint status and team progress.
2147
-
2148
- ## Instructions
2149
-
2150
- 1. Query the active sprint for project {{JIRA_PROJECT}}
2151
- 2. Gather metrics:
2152
- - Total story points committed
2153
- - Points completed
2154
- - Points in progress
2155
- - Points remaining
2156
- 3. List tickets by status
2157
- 4. Identify blockers or at-risk items
2158
-
2159
- ## Output Format
2160
-
2161
- \`\`\`
2162
- Sprint: <sprint-name>
2163
- Progress: XX/YY points (ZZ%)
2164
-
2165
- ## Completed
2166
- - [{{JIRA_PROJECT}}-123] Task name (3 pts)
2167
-
2168
- ## In Progress
2169
- - [{{JIRA_PROJECT}}-124] Task name (5 pts) - @assignee
2170
-
2171
- ## To Do
2172
- - [{{JIRA_PROJECT}}-125] Task name (2 pts)
2173
-
2174
- ## Blocked
2175
- - [{{JIRA_PROJECT}}-126] Task name - Reason
2176
- \`\`\`
2177
-
2178
- ## Fallbacks
2179
-
2180
- If issue tracker is unavailable:
2181
- - Report that sprint data cannot be fetched
2182
- - Suggest checking the issue tracker directly at {{JIRA_URL}}
2183
- `
2184
- };
2185
- var jiraCreateSkill = {
2186
- name: "jira-create",
2187
- description: "Create a new Jira ticket",
2188
- argumentHint: "<ticket-type> <summary>",
2189
- category: "optional",
2190
- dependencies: [{ type: "issue_tracker", required: true, description: "For ticket creation" }],
2191
- content: `---
2192
- description: Create a new Jira ticket
2193
- argument-hint: <ticket-type> <summary>
2194
- requires: [issue_tracker]
2195
- ---
2196
-
2197
- # Create Jira Ticket
2198
-
2199
- Create a new ticket in project {{JIRA_PROJECT}}.
2200
-
2201
- ## Instructions
2202
-
2203
- 1. Parse the ticket type and summary from arguments
2204
- 2. Gather additional details:
2205
- - Description
2206
- - Priority
2207
- - Labels
2208
- - Components (if applicable)
2209
- 3. Create the ticket via the issue tracker integration
2210
- 4. Return the ticket key and URL
2211
-
2212
- ## Ticket Types
2213
-
2214
- - **Story**: User-facing feature
2215
- - **Bug**: Defect to fix
2216
- - **Task**: Technical work
2217
- - **Spike**: Research/investigation
2218
-
2219
- ## Output
2220
-
2221
- \`\`\`
2222
- Created: {{JIRA_PROJECT}}-XXX
2223
- URL: {{JIRA_URL}}/browse/{{JIRA_PROJECT}}-XXX
2224
- Summary: <summary>
2225
- Type: <type>
2226
- \`\`\`
2227
-
2228
- ## Fallbacks
2229
-
2230
- If issue tracker is unavailable:
2231
- - Provide the user with manual creation instructions
2232
- - Include all details they should enter
2233
- `
2234
- };
2235
- var jiraTransitionSkill = {
2236
- name: "jira-transition",
2237
- description: "Transition a Jira ticket to a new status",
2238
- argumentHint: "<ticket-key> to <status>",
2239
- category: "optional",
2240
- dependencies: [{ type: "issue_tracker", required: true, description: "For ticket transitions" }],
2241
- content: `---
2242
- description: Transition a Jira ticket to a new status
2243
- argument-hint: <ticket-key> to <status>
2244
- requires: [issue_tracker]
2245
- ---
2246
-
2247
- # Transition Jira Ticket
2248
-
2249
- Update the status of a ticket in {{JIRA_PROJECT}}.
2250
-
2251
- ## Status Mapping
2252
-
2253
- | Workflow Status | Jira Status |
2254
- |-----------------|-------------|
2255
- | BACKLOG | Backlog |
2256
- | IN_PROGRESS | In Progress |
2257
- | PR_CREATED | In Review |
2258
- | IN_REVIEW | In Review |
2259
- | APPROVED | Ready to Merge |
2260
- | MERGED | Done |
2261
- | DONE | Done |
2262
-
2263
- ## Instructions
2264
-
2265
- 1. Parse ticket key and target status
2266
- 2. Validate the transition is allowed
2267
- 3. Add a comment explaining the transition
2268
- 4. Execute the transition
2269
-
2270
- ## Transition Comment Format
2271
-
2272
- \`\`\`
2273
- Status updated to <status>.
2274
- <optional context about why>
2275
- \`\`\`
2276
-
2277
- ## Fallbacks
2278
-
2279
- If issue tracker is unavailable:
2280
- - Instruct user to manually transition at {{JIRA_URL}}
2281
- - Provide the target status name
2282
- `
2283
- };
2284
- var docsUpdateSkill = {
2285
- name: "docs-update",
2286
- description: "Update project documentation",
2287
- argumentHint: "<doc-path-or-topic>",
2288
- category: "optional",
2289
- dependencies: [{ type: "documentation", required: false, description: "For remote docs" }],
2290
- content: `---
2291
- description: Update project documentation
2292
- argument-hint: <doc-path-or-topic>
2293
- optional: [documentation]
2294
- ---
2295
-
2296
- # Update Documentation
2297
-
2298
- Update project documentation for a specific topic or file.
2299
-
2300
- ## Instructions
2301
-
2302
- 1. Identify the documentation to update:
2303
- - Local: \`{{DOCS_PATH}}/\`
2304
- - Remote: {{CONFLUENCE_SPACE}} (if configured)
2305
-
2306
- 2. Make the necessary updates:
2307
- - Keep formatting consistent
2308
- - Update examples if code changed
2309
- - Add/update version information
2310
-
2311
- 3. For remote documentation:
2312
- - Use the documentation integration
2313
- - Or provide content for manual update
2314
-
2315
- ## Documentation Types
2316
-
2317
- - **README**: Project overview and setup
2318
- - **API Docs**: Endpoint documentation
2319
- - **Architecture**: Design decisions
2320
- - **Runbooks**: Operational procedures
2321
-
2322
- ## Fallbacks
2323
-
2324
- If documentation integration is unavailable:
2325
- - Create/update local markdown files
2326
- - Provide instructions for manual remote update
2327
- `
2328
- };
2329
- var builtInSkills = [
2330
- checkInboxSkill,
2331
- delegateSkill,
2332
- gitCommitSkill,
2333
- prCreateSkill,
2334
- reviewSkill,
2335
- sprintStatusSkill,
2336
- jiraCreateSkill,
2337
- jiraTransitionSkill,
2338
- docsUpdateSkill
2339
- ];
2340
-
2341
- // src/skills/generator.ts
1907
+ import { join as join6, dirname as dirname5 } from "path";
1908
+ function getCoreSkillsDir() {
1909
+ let currentDir = dirname5(import.meta.url.replace("file://", ""));
1910
+ for (let i = 0; i < 5; i++) {
1911
+ if (existsSync5(join6(currentDir, "package.json"))) {
1912
+ return join6(currentDir, "skills");
1913
+ }
1914
+ currentDir = dirname5(currentDir);
1915
+ }
1916
+ return join6(dirname5(dirname5(dirname5(import.meta.url.replace("file://", "")))), "skills");
1917
+ }
1918
+ function discoverSkills(skillsDir) {
1919
+ const templates = [];
1920
+ if (!existsSync5(skillsDir)) {
1921
+ return templates;
1922
+ }
1923
+ const categories = readdirSync2(skillsDir);
1924
+ for (const category of categories) {
1925
+ const categoryPath = join6(skillsDir, category);
1926
+ const stat = statSync(categoryPath);
1927
+ if (!stat.isDirectory()) continue;
1928
+ if (category.startsWith(".") || category.startsWith("_")) continue;
1929
+ const skillDirs = readdirSync2(categoryPath);
1930
+ for (const skillName of skillDirs) {
1931
+ const skillDir = join6(categoryPath, skillName);
1932
+ const skillStat = statSync(skillDir);
1933
+ if (!skillStat.isDirectory()) continue;
1934
+ const skillFile = join6(skillDir, "SKILL.md");
1935
+ if (!existsSync5(skillFile)) continue;
1936
+ try {
1937
+ const content = readFileSync5(skillFile, "utf-8");
1938
+ const template = parseSkillFile(skillName, category, content);
1939
+ templates.push(template);
1940
+ } catch {
1941
+ }
1942
+ }
1943
+ }
1944
+ return templates;
1945
+ }
1946
+ function parseSkillFile(name, category, content) {
1947
+ const template = {
1948
+ name,
1949
+ description: name,
1950
+ category,
1951
+ content
1952
+ };
1953
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
1954
+ if (!frontmatterMatch) {
1955
+ return template;
1956
+ }
1957
+ const frontmatter = frontmatterMatch[1];
1958
+ const lines = frontmatter.split(/\r?\n/);
1959
+ const dependencies = [];
1960
+ for (const line of lines) {
1961
+ const colonIndex = line.indexOf(":");
1962
+ if (colonIndex === -1) continue;
1963
+ const key = line.slice(0, colonIndex).trim();
1964
+ let value = line.slice(colonIndex + 1).trim();
1965
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
1966
+ value = value.slice(1, -1);
1967
+ }
1968
+ switch (key) {
1969
+ case "name":
1970
+ template.name = value;
1971
+ break;
1972
+ case "description":
1973
+ template.description = value;
1974
+ break;
1975
+ case "argument-hint":
1976
+ template.argumentHint = value;
1977
+ break;
1978
+ case "requires":
1979
+ if (value.startsWith("[") && value.endsWith("]")) {
1980
+ const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
1981
+ for (const item of items) {
1982
+ if (item) {
1983
+ dependencies.push({
1984
+ type: mapIntegrationName(item),
1985
+ required: true
1986
+ });
1987
+ }
1988
+ }
1989
+ }
1990
+ break;
1991
+ case "optional":
1992
+ if (value.startsWith("[") && value.endsWith("]")) {
1993
+ const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
1994
+ for (const item of items) {
1995
+ if (item) {
1996
+ dependencies.push({
1997
+ type: mapIntegrationName(item),
1998
+ required: false
1999
+ });
2000
+ }
2001
+ }
2002
+ }
2003
+ break;
2004
+ }
2005
+ }
2006
+ if (dependencies.length > 0) {
2007
+ template.dependencies = dependencies;
2008
+ }
2009
+ return template;
2010
+ }
2011
+ function mapIntegrationName(name) {
2012
+ const lower = name.toLowerCase();
2013
+ if (["jira", "linear", "issue_tracker", "issues", "github-issues"].includes(lower)) {
2014
+ return "issue_tracker";
2015
+ }
2016
+ if (["git", "github", "gitlab", "bitbucket"].includes(lower)) {
2017
+ return "git";
2018
+ }
2019
+ if (["docs", "documentation", "confluence", "notion", "wiki"].includes(lower)) {
2020
+ return "documentation";
2021
+ }
2022
+ return "state";
2023
+ }
2342
2024
  function extractVariables2(config) {
2343
2025
  const vars = {};
2344
2026
  if (!config) {
@@ -2448,112 +2130,12 @@ function checkDependencies(skill, config) {
2448
2130
  missing
2449
2131
  };
2450
2132
  }
2451
- function loadCustomTemplates(templatesDir) {
2452
- const templates = [];
2453
- if (!existsSync5(templatesDir)) {
2454
- return templates;
2455
- }
2456
- const files = readdirSync2(templatesDir);
2457
- for (const file of files) {
2458
- if (!file.endsWith(".md")) continue;
2459
- const filePath = join6(templatesDir, file);
2460
- const stat = statSync(filePath);
2461
- if (!stat.isFile()) continue;
2462
- try {
2463
- const content = readFileSync5(filePath, "utf-8");
2464
- const template = parseSkillTemplate(file, content);
2465
- templates.push(template);
2466
- } catch {
2467
- }
2468
- }
2469
- return templates;
2470
- }
2471
- function parseSkillTemplate(filename, content) {
2472
- const name = basename2(filename, ".md");
2473
- const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
2474
- let description = name;
2475
- let argumentHint;
2476
- const dependencies = [];
2477
- if (frontmatterMatch) {
2478
- const frontmatter = frontmatterMatch[1] ?? "";
2479
- const lines = frontmatter.split(/\r?\n/);
2480
- for (const line of lines) {
2481
- const colonIndex = line.indexOf(":");
2482
- if (colonIndex === -1) continue;
2483
- const key = line.slice(0, colonIndex).trim();
2484
- let value = line.slice(colonIndex + 1).trim();
2485
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2486
- value = value.slice(1, -1);
2487
- }
2488
- switch (key) {
2489
- case "description":
2490
- description = value;
2491
- break;
2492
- case "argument-hint":
2493
- argumentHint = value;
2494
- break;
2495
- case "requires":
2496
- if (value.startsWith("[") && value.endsWith("]")) {
2497
- const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
2498
- for (const item of items) {
2499
- if (item) {
2500
- dependencies.push({
2501
- type: mapIntegrationName(item),
2502
- required: true
2503
- });
2504
- }
2505
- }
2506
- }
2507
- break;
2508
- case "optional":
2509
- if (value.startsWith("[") && value.endsWith("]")) {
2510
- const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
2511
- for (const item of items) {
2512
- if (item) {
2513
- dependencies.push({
2514
- type: mapIntegrationName(item),
2515
- required: false
2516
- });
2517
- }
2518
- }
2519
- }
2520
- break;
2521
- }
2522
- }
2523
- }
2524
- const template = {
2525
- name,
2526
- description,
2527
- category: "custom",
2528
- content
2529
- };
2530
- if (argumentHint) {
2531
- template.argumentHint = argumentHint;
2532
- }
2533
- if (dependencies.length > 0) {
2534
- template.dependencies = dependencies;
2535
- }
2536
- return template;
2537
- }
2538
- function mapIntegrationName(name) {
2539
- const lower = name.toLowerCase();
2540
- if (["jira", "linear", "issue_tracker", "issues", "github-issues"].includes(lower)) {
2541
- return "issue_tracker";
2542
- }
2543
- if (["git", "github", "gitlab", "bitbucket"].includes(lower)) {
2544
- return "git";
2545
- }
2546
- if (["docs", "documentation", "confluence", "notion", "wiki"].includes(lower)) {
2547
- return "documentation";
2548
- }
2549
- return "state";
2550
- }
2551
2133
  function generateSkills(config, options = {}) {
2552
2134
  const projectRoot = options.projectRoot ?? process.cwd();
2553
- const outputDir = options.outputDir ?? join6(projectRoot, ".claude", "commands");
2135
+ const coreSkillsDir = options.coreSkillsDir ?? getCoreSkillsDir();
2136
+ const outputDir = options.outputDir ?? join6(projectRoot, ".claude", "skills");
2554
2137
  const includeCoreSkills = options.includeCoreSkills ?? true;
2555
- const includeOptionalSkills = options.includeOptionalSkills ?? true;
2556
- const overwrite = options.overwrite ?? false;
2138
+ const overwrite = options.overwrite ?? true;
2557
2139
  const result = {
2558
2140
  generated: [],
2559
2141
  errors: [],
@@ -2566,21 +2148,17 @@ function generateSkills(config, options = {}) {
2566
2148
  result.variables = variables;
2567
2149
  let templates = [];
2568
2150
  if (includeCoreSkills) {
2569
- templates.push(...builtInSkills.filter((s) => s.category === "core"));
2570
- }
2571
- if (includeOptionalSkills) {
2572
- templates.push(...builtInSkills.filter((s) => s.category === "optional"));
2151
+ const discovered = discoverSkills(coreSkillsDir);
2152
+ templates.push(...discovered);
2573
2153
  }
2574
2154
  if (options.customTemplatesDir && existsSync5(options.customTemplatesDir)) {
2575
- templates.push(...loadCustomTemplates(options.customTemplatesDir));
2155
+ const custom = discoverSkills(options.customTemplatesDir);
2156
+ templates.push(...custom);
2576
2157
  }
2577
2158
  if (options.skills && options.skills.length > 0) {
2578
2159
  const skillsToInclude = options.skills;
2579
2160
  templates = templates.filter((t) => skillsToInclude.includes(t.name));
2580
2161
  }
2581
- if (!existsSync5(outputDir)) {
2582
- mkdirSync2(outputDir, { recursive: true });
2583
- }
2584
2162
  for (const template of templates) {
2585
2163
  try {
2586
2164
  const generated = generateSkill(template, variables, config, outputDir, overwrite);
@@ -2595,7 +2173,8 @@ function generateSkills(config, options = {}) {
2595
2173
  return result;
2596
2174
  }
2597
2175
  function generateSkill(template, variables, config, outputDir, overwrite) {
2598
- const outputPath = join6(outputDir, `${template.name}.md`);
2176
+ const skillDir = join6(outputDir, template.name);
2177
+ const outputPath = join6(skillDir, "SKILL.md");
2599
2178
  if (existsSync5(outputPath) && !overwrite) {
2600
2179
  return {
2601
2180
  name: template.name,
@@ -2618,6 +2197,9 @@ function generateSkill(template, variables, config, outputDir, overwrite) {
2618
2197
  }
2619
2198
  const content = substituteVariables(template.content, variables);
2620
2199
  const isUpdate = existsSync5(outputPath);
2200
+ if (!existsSync5(skillDir)) {
2201
+ mkdirSync2(skillDir, { recursive: true });
2202
+ }
2621
2203
  writeFileSync2(outputPath, content, "utf-8");
2622
2204
  return {
2623
2205
  name: template.name,
@@ -2661,7 +2243,7 @@ function formatGenerateResult(result) {
2661
2243
  }
2662
2244
  const total = created.length + updated.length;
2663
2245
  if (total > 0) {
2664
- lines.push(`Generated ${total} skill(s) to .claude/commands/`);
2246
+ lines.push(`Generated ${total} skill(s) to .claude/skills/`);
2665
2247
  } else if (result.generated.length === 0 && result.errors.length === 0) {
2666
2248
  lines.push("No skills to generate.");
2667
2249
  }
@@ -2678,7 +2260,7 @@ import {
2678
2260
  renameSync,
2679
2261
  statSync as statSync2
2680
2262
  } from "fs";
2681
- import { join as join7, basename as basename3 } from "path";
2263
+ import { join as join7, basename as basename2 } from "path";
2682
2264
  var DEFAULT_KNOWLEDGE_LIBRARY_PATH = "KnowledgeLibrary";
2683
2265
  var STANDARD_FILES = {
2684
2266
  context: "context.txt",
@@ -3091,8 +2673,8 @@ function getKnowledgeLibraryState(options = {}) {
3091
2673
 
3092
2674
  // src/index.ts
3093
2675
  function findPackageJson() {
3094
- let dir = dirname5(fileURLToPath(import.meta.url));
3095
- while (dir !== dirname5(dir)) {
2676
+ let dir = dirname6(fileURLToPath(import.meta.url));
2677
+ while (dir !== dirname6(dir)) {
3096
2678
  const pkgPath = join8(dir, "package.json");
3097
2679
  try {
3098
2680
  const content = readFileSync7(pkgPath, "utf-8");
@@ -3102,7 +2684,7 @@ function findPackageJson() {
3102
2684
  }
3103
2685
  } catch {
3104
2686
  }
3105
- dir = dirname5(dir);
2687
+ dir = dirname6(dir);
3106
2688
  }
3107
2689
  return '{"version": "unknown"}';
3108
2690
  }
@@ -3380,7 +2962,7 @@ function formatSyncResult(result) {
3380
2962
 
3381
2963
  // src/cli/commands/init.ts
3382
2964
  import { existsSync as existsSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync8 } from "fs";
3383
- import { join as join11, basename as basename4 } from "path";
2965
+ import { join as join11, basename as basename3 } from "path";
3384
2966
  import { execSync } from "child_process";
3385
2967
  function detectGitInfo() {
3386
2968
  try {
@@ -3417,7 +2999,7 @@ function detectProjectName(projectRoot) {
3417
2999
  } catch {
3418
3000
  }
3419
3001
  }
3420
- return basename4(projectRoot);
3002
+ return basename3(projectRoot);
3421
3003
  }
3422
3004
  function generateConfigYaml(options) {
3423
3005
  let yaml = `# CoreAI Configuration
@@ -3614,6 +3196,14 @@ function build(options = {}) {
3614
3196
  warnings
3615
3197
  };
3616
3198
  }
3199
+ let skillsResult;
3200
+ if (!options.skipSkills) {
3201
+ skillsResult = generateSkills(config, {
3202
+ projectRoot,
3203
+ skills: options.skills,
3204
+ overwrite: true
3205
+ });
3206
+ }
3617
3207
  let knowledgeLibraryInitialized;
3618
3208
  if (options.initKnowledgeLibrary) {
3619
3209
  knowledgeLibraryInitialized = [];
@@ -3630,6 +3220,7 @@ function build(options = {}) {
3630
3220
  return {
3631
3221
  success: true,
3632
3222
  result,
3223
+ skillsResult,
3633
3224
  config,
3634
3225
  warnings: warnings.length > 0 ? warnings : void 0,
3635
3226
  knowledgeLibraryInitialized,
@@ -3699,6 +3290,24 @@ function formatBuildResult(result) {
3699
3290
  }
3700
3291
  lines.push("");
3701
3292
  }
3293
+ if (result.skillsResult) {
3294
+ const created = result.skillsResult.generated.filter((g) => g.action === "created");
3295
+ const updated = result.skillsResult.generated.filter((g) => g.action === "updated");
3296
+ const total = created.length + updated.length;
3297
+ if (total > 0) {
3298
+ lines.push(`Generated ${total} skill(s):`);
3299
+ for (const skill of [...created, ...updated]) {
3300
+ lines.push(` \u2713 ${skill.name} \u2192 ${skill.outputPath}`);
3301
+ }
3302
+ lines.push("");
3303
+ }
3304
+ if (result.skillsResult.errors.length > 0) {
3305
+ for (const error of result.skillsResult.errors) {
3306
+ lines.push(` \u2717 skill ${error.name}: ${error.error}`);
3307
+ }
3308
+ lines.push("");
3309
+ }
3310
+ }
3702
3311
  if (result.mcpServers && result.mcpServers.length > 0) {
3703
3312
  lines.push(`MCP tools included: ${result.mcpServers.map((s) => `mcp__${s}`).join(", ")}`);
3704
3313
  lines.push("");
@@ -3943,8 +3552,7 @@ function skillsGenerate(options = {}) {
3943
3552
  const generateOptions = {
3944
3553
  projectRoot,
3945
3554
  includeCoreSkills: options.includeCoreSkills ?? true,
3946
- includeOptionalSkills: options.includeOptionalSkills ?? true,
3947
- overwrite: options.overwrite ?? false
3555
+ overwrite: options.overwrite ?? true
3948
3556
  };
3949
3557
  if (options.outputDir) {
3950
3558
  generateOptions.outputDir = options.outputDir;
@@ -4010,11 +3618,11 @@ function formatSkillsGenerateResult(result) {
4010
3618
  function skillsList(options = {}) {
4011
3619
  try {
4012
3620
  const skills = [];
3621
+ const coreSkillsDir = getCoreSkillsDir();
3622
+ const discovered = discoverSkills(coreSkillsDir);
4013
3623
  const includeCoreSkills = options.includeCoreSkills ?? true;
4014
- const includeOptionalSkills = options.includeOptionalSkills ?? true;
4015
- for (const skill of builtInSkills) {
3624
+ for (const skill of discovered) {
4016
3625
  if (skill.category === "core" && !includeCoreSkills) continue;
4017
- if (skill.category === "optional" && !includeOptionalSkills) continue;
4018
3626
  skills.push({
4019
3627
  name: skill.name,
4020
3628
  description: skill.description,
@@ -4024,7 +3632,7 @@ function skillsList(options = {}) {
4024
3632
  });
4025
3633
  }
4026
3634
  if (options.customTemplatesDir) {
4027
- const customSkills = loadCustomTemplates(options.customTemplatesDir);
3635
+ const customSkills = discoverSkills(options.customTemplatesDir);
4028
3636
  for (const skill of customSkills) {
4029
3637
  skills.push({
4030
3638
  name: skill.name,
@@ -4056,7 +3664,6 @@ function formatSkillsListResult(result) {
4056
3664
  const lines = [];
4057
3665
  lines.push("Available skills:\n");
4058
3666
  const coreSkills = result.skills.filter((s) => s.category === "core");
4059
- const optionalSkills = result.skills.filter((s) => s.category === "optional");
4060
3667
  const customSkills = result.skills.filter((s) => s.category === "custom");
4061
3668
  if (coreSkills.length > 0) {
4062
3669
  lines.push("Core skills:");
@@ -4069,18 +3676,6 @@ function formatSkillsListResult(result) {
4069
3676
  }
4070
3677
  lines.push("");
4071
3678
  }
4072
- if (optionalSkills.length > 0) {
4073
- lines.push("Optional skills:");
4074
- for (const skill of optionalSkills) {
4075
- const deps = skill.dependencies?.length ? ` (requires: ${skill.dependencies.join(", ")})` : "";
4076
- lines.push(` ${skill.name}${deps}`);
4077
- lines.push(` ${skill.description}`);
4078
- if (skill.argumentHint) {
4079
- lines.push(` Argument: ${skill.argumentHint}`);
4080
- }
4081
- }
4082
- lines.push("");
4083
- }
4084
3679
  if (customSkills.length > 0) {
4085
3680
  lines.push("Custom skills:");
4086
3681
  for (const skill of customSkills) {
@@ -4257,7 +3852,7 @@ function formatStatusResult(result) {
4257
3852
 
4258
3853
  // src/cli/commands/agents.ts
4259
3854
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
4260
- import { join as join13, dirname as dirname6 } from "path";
3855
+ import { join as join13, dirname as dirname7 } from "path";
4261
3856
  import { parse as parseYaml4, stringify as stringifyYaml2 } from "yaml";
4262
3857
  function readConfigFile(configPath) {
4263
3858
  const content = readFileSync9(configPath, "utf-8");
@@ -4291,7 +3886,7 @@ function getAvailableAgents(coreAgentsDir, customAgentsDir) {
4291
3886
  }
4292
3887
  function agentsAdd(agents2, options = {}) {
4293
3888
  const projectRoot = options.projectRoot ?? process.cwd();
4294
- const coreAgentsDir = options.coreAgentsDir ?? join13(dirname6(dirname6(dirname6(__dirname))), "agents");
3889
+ const coreAgentsDir = options.coreAgentsDir ?? join13(dirname7(dirname7(dirname7(__dirname))), "agents");
4295
3890
  const customAgentsDir = join13(projectRoot, "coreai", "agents");
4296
3891
  const configPath = findConfigFile(projectRoot);
4297
3892
  if (!configPath) {
@@ -4473,7 +4068,7 @@ function formatAgentsRemoveResult(result) {
4473
4068
 
4474
4069
  // src/cli/index.ts
4475
4070
  var __filename = fileURLToPath2(import.meta.url);
4476
- var __dirname2 = dirname7(__filename);
4071
+ var __dirname2 = dirname8(__filename);
4477
4072
  function getCoreAgentsPath() {
4478
4073
  return join14(__dirname2, "..", "..", "agents");
4479
4074
  }
@@ -4783,7 +4378,7 @@ program.command("status").description("Show agent states and pending messages").
4783
4378
  }
4784
4379
  });
4785
4380
  var skillsCmd = program.command("skills").description("Manage Claude skills");
4786
- skillsCmd.command("generate").description("Generate Claude skills from templates").option("-o, --output <dir>", "output directory (default: .claude/commands)").option("--skills <skills>", "comma-separated list of skills to generate").option("--no-core", "exclude core skills").option("--no-optional", "exclude optional skills").option("--overwrite", "overwrite existing skill files").option("--json", "output as JSON").action(
4381
+ skillsCmd.command("generate").description("Generate Claude skills from source files").option("-o, --output <dir>", "output directory (default: .claude/skills)").option("--skills <skills>", "comma-separated list of skills to generate").option("--no-core", "exclude core skills").option("--no-overwrite", "do not overwrite existing skill files").option("--json", "output as JSON").action(
4787
4382
  (options) => {
4788
4383
  console.log("Generating skills...\n");
4789
4384
  const result = skillsGenerate({
@@ -4791,8 +4386,7 @@ skillsCmd.command("generate").description("Generate Claude skills from templates
4791
4386
  outputDir: options.output,
4792
4387
  skills: options.skills?.split(",").map((s) => s.trim()),
4793
4388
  includeCoreSkills: options.core !== false,
4794
- includeOptionalSkills: options.optional !== false,
4795
- overwrite: options.overwrite
4389
+ overwrite: options.overwrite !== false
4796
4390
  });
4797
4391
  if (options.json) {
4798
4392
  console.log(JSON.stringify(result, null, 2));
@@ -4804,11 +4398,10 @@ skillsCmd.command("generate").description("Generate Claude skills from templates
4804
4398
  }
4805
4399
  }
4806
4400
  );
4807
- skillsCmd.command("list").description("List available skills").option("--no-core", "exclude core skills").option("--no-optional", "exclude optional skills").option("--json", "output as JSON").action((options) => {
4401
+ skillsCmd.command("list").description("List available skills").option("--no-core", "exclude core skills").option("--json", "output as JSON").action((options) => {
4808
4402
  const result = skillsList({
4809
4403
  projectRoot: process.cwd(),
4810
- includeCoreSkills: options.core !== false,
4811
- includeOptionalSkills: options.optional !== false
4404
+ includeCoreSkills: options.core !== false
4812
4405
  });
4813
4406
  if (options.json) {
4814
4407
  console.log(JSON.stringify(result, null, 2));