@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/agents/_templates/master-context.md +76 -0
- package/agents/_templates/master-protocols.md +39 -0
- package/agents/android-engineer.md +3 -115
- package/agents/backend-engineer.md +3 -115
- package/agents/database-administrator.md +3 -115
- package/agents/devops-engineer.md +3 -115
- package/agents/frontend-engineer.md +3 -115
- package/agents/react-engineer.md +3 -115
- package/agents/react-native-engineer.md +3 -115
- package/agents/software-security-engineer.md +3 -115
- package/agents/sre-huawei-cloud-architect.md +3 -115
- package/agents/sre-iac-specialist.md +3 -115
- package/agents/sre-kubernetes-specialist.md +3 -115
- package/agents/sre-network-specialist.md +3 -115
- package/agents/wearos-engineer.md +3 -115
- package/dist/cli/index.js +209 -616
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +35 -30
- package/dist/index.js +173 -590
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/skills/core/check-inbox/SKILL.md +37 -0
- package/skills/core/delegate/SKILL.md +61 -0
- package/skills/core/review/SKILL.md +57 -0
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { readFileSync as readFileSync6 } from "fs";
|
|
3
|
-
import { dirname as
|
|
3
|
+
import { dirname as dirname6, join as join8 } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
|
|
6
6
|
// src/config/loader.ts
|
|
@@ -446,7 +446,7 @@ function resolveAgentDefinition(agent, config, options = {}) {
|
|
|
446
446
|
|
|
447
447
|
// src/agents/compiler.ts
|
|
448
448
|
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
449
|
-
import { join as join3, dirname as dirname2, extname as extname2 } from "path";
|
|
449
|
+
import { join as join3, dirname as dirname2, extname as extname2, isAbsolute } from "path";
|
|
450
450
|
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
451
451
|
function buildAgentTools(agent, mcpServers) {
|
|
452
452
|
const tools = agent.tools ? [...agent.tools] : [...DEFAULT_AGENT_TOOLS];
|
|
@@ -460,16 +460,44 @@ function buildAgentTools(agent, mcpServers) {
|
|
|
460
460
|
}
|
|
461
461
|
return tools.join(", ");
|
|
462
462
|
}
|
|
463
|
+
function processIncludes(template, templateDir, depth = 0, maxDepth = 3) {
|
|
464
|
+
if (depth > maxDepth) {
|
|
465
|
+
throw new Error(`Include depth exceeded maximum of ${maxDepth}`);
|
|
466
|
+
}
|
|
467
|
+
const includePattern = /<!--\s*include:\s*(\S+)\s*-->/g;
|
|
468
|
+
return template.replace(includePattern, (_match, includePath) => {
|
|
469
|
+
const resolvedPath = isAbsolute(includePath) ? includePath : join3(templateDir, includePath);
|
|
470
|
+
if (!existsSync3(resolvedPath)) {
|
|
471
|
+
throw new Error(`Include file not found: ${includePath} (resolved to ${resolvedPath})`);
|
|
472
|
+
}
|
|
473
|
+
const includedContent = readFileSync3(resolvedPath, "utf-8");
|
|
474
|
+
return processIncludes(includedContent, dirname2(resolvedPath), depth + 1, maxDepth);
|
|
475
|
+
});
|
|
476
|
+
}
|
|
463
477
|
function processAgentTemplate(templatePath, agent, config, mcpServers) {
|
|
464
478
|
const template = readFileSync3(templatePath, "utf-8");
|
|
465
|
-
const
|
|
479
|
+
const templateDir = dirname2(templatePath);
|
|
480
|
+
const expandedTemplate = processIncludes(template, templateDir);
|
|
481
|
+
const earlyMatch = expandedTemplate.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
482
|
+
if (!earlyMatch) {
|
|
483
|
+
throw new Error(`Invalid markdown format in ${templatePath}: no frontmatter found`);
|
|
484
|
+
}
|
|
485
|
+
const earlyFrontmatter = parseYaml3(earlyMatch[1]);
|
|
486
|
+
const reservedKeys = /* @__PURE__ */ new Set(["name", "description", "tools"]);
|
|
487
|
+
const extendedAgent = { ...agent };
|
|
488
|
+
for (const [key, value] of Object.entries(earlyFrontmatter)) {
|
|
489
|
+
if (!reservedKeys.has(key) && !(key in extendedAgent)) {
|
|
490
|
+
extendedAgent[key] = value;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
const context = { agent: extendedAgent };
|
|
466
494
|
if (config) {
|
|
467
495
|
context.config = config;
|
|
468
496
|
}
|
|
469
|
-
const resolved = resolveString(
|
|
497
|
+
const resolved = resolveString(expandedTemplate, context);
|
|
470
498
|
const frontmatterMatch = resolved.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
471
499
|
if (!frontmatterMatch) {
|
|
472
|
-
throw new Error(`Invalid markdown format in ${templatePath}
|
|
500
|
+
throw new Error(`Invalid markdown format after resolution in ${templatePath}`);
|
|
473
501
|
}
|
|
474
502
|
const frontmatterYaml = frontmatterMatch[1];
|
|
475
503
|
const body = frontmatterMatch[2] ?? "";
|
|
@@ -2667,469 +2695,123 @@ var StepTracker = class {
|
|
|
2667
2695
|
|
|
2668
2696
|
// src/skills/generator.ts
|
|
2669
2697
|
import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync } from "fs";
|
|
2670
|
-
import { join as join6,
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
## Quality Gates
|
|
2788
|
-
|
|
2789
|
-
Run these checks before committing:
|
|
2790
|
-
|
|
2791
|
-
1. **Lint**: \`{{LINT_CMD}}\`
|
|
2792
|
-
2. **Tests**: \`{{TEST_CMD}}\`
|
|
2793
|
-
3. **Build**: \`{{BUILD_CMD}}\`
|
|
2794
|
-
|
|
2795
|
-
## Instructions
|
|
2796
|
-
|
|
2797
|
-
1. Stage the relevant files with \`git add\`
|
|
2798
|
-
2. Run all quality gate commands
|
|
2799
|
-
3. If any gate fails:
|
|
2800
|
-
- Fix the issues
|
|
2801
|
-
- Re-run the failed gate
|
|
2802
|
-
- Continue only when all pass
|
|
2803
|
-
4. Create the commit with the provided message
|
|
2804
|
-
5. Format: Include ticket reference if applicable
|
|
2805
|
-
|
|
2806
|
-
## Commit Message Format
|
|
2807
|
-
|
|
2808
|
-
\`\`\`
|
|
2809
|
-
<type>(<scope>): <description>
|
|
2810
|
-
|
|
2811
|
-
[optional body]
|
|
2812
|
-
|
|
2813
|
-
[optional footer]
|
|
2814
|
-
\`\`\`
|
|
2815
|
-
|
|
2816
|
-
Types: feat, fix, docs, style, refactor, test, chore
|
|
2817
|
-
|
|
2818
|
-
## Fallbacks
|
|
2819
|
-
|
|
2820
|
-
If quality gate commands are not configured:
|
|
2821
|
-
- Ask the user what commands to run
|
|
2822
|
-
- Or skip gates with user confirmation
|
|
2823
|
-
`
|
|
2824
|
-
};
|
|
2825
|
-
var prCreateSkill = {
|
|
2826
|
-
name: "pr-create",
|
|
2827
|
-
description: "Create a pull request with proper format",
|
|
2828
|
-
argumentHint: "[branch-name]",
|
|
2829
|
-
category: "core",
|
|
2830
|
-
dependencies: [{ type: "git", required: true, description: "For PR creation" }],
|
|
2831
|
-
content: `---
|
|
2832
|
-
description: Create a pull request with proper format
|
|
2833
|
-
argument-hint: [branch-name]
|
|
2834
|
-
requires: [git]
|
|
2835
|
-
---
|
|
2836
|
-
|
|
2837
|
-
# Create Pull Request
|
|
2838
|
-
|
|
2839
|
-
Create a well-formatted pull request for the current branch.
|
|
2840
|
-
|
|
2841
|
-
## Instructions
|
|
2842
|
-
|
|
2843
|
-
1. Ensure all changes are committed
|
|
2844
|
-
2. Push the branch to remote
|
|
2845
|
-
3. Create PR with proper format:
|
|
2846
|
-
|
|
2847
|
-
\`\`\`markdown
|
|
2848
|
-
## Summary
|
|
2849
|
-
<Brief description of changes>
|
|
2850
|
-
|
|
2851
|
-
## Changes
|
|
2852
|
-
- <Change 1>
|
|
2853
|
-
- <Change 2>
|
|
2854
|
-
|
|
2855
|
-
## Test Plan
|
|
2856
|
-
- [ ] <Test case 1>
|
|
2857
|
-
- [ ] <Test case 2>
|
|
2858
|
-
|
|
2859
|
-
## Related Issues
|
|
2860
|
-
Closes {{JIRA_PROJECT}}-XXX
|
|
2861
|
-
\`\`\`
|
|
2862
|
-
|
|
2863
|
-
4. Request reviewers if specified
|
|
2864
|
-
|
|
2865
|
-
## Using GitHub CLI
|
|
2866
|
-
|
|
2867
|
-
\`\`\`bash
|
|
2868
|
-
gh pr create --title "<title>" --body "<body>"
|
|
2869
|
-
\`\`\`
|
|
2870
|
-
|
|
2871
|
-
## Output
|
|
2872
|
-
|
|
2873
|
-
Provide the PR URL and summary of what was created.
|
|
2874
|
-
`
|
|
2875
|
-
};
|
|
2876
|
-
var reviewSkill = {
|
|
2877
|
-
name: "review",
|
|
2878
|
-
description: "Request or perform a code review",
|
|
2879
|
-
argumentHint: "<pr-number-or-url>",
|
|
2880
|
-
category: "core",
|
|
2881
|
-
dependencies: [{ type: "git", required: true, description: "For PR review" }],
|
|
2882
|
-
content: `---
|
|
2883
|
-
description: Request or perform a code review
|
|
2884
|
-
argument-hint: <pr-number-or-url>
|
|
2885
|
-
requires: [git]
|
|
2886
|
-
---
|
|
2887
|
-
|
|
2888
|
-
# Code Review
|
|
2889
|
-
|
|
2890
|
-
Review a pull request or delegate review to a specialist.
|
|
2891
|
-
|
|
2892
|
-
## Instructions
|
|
2893
|
-
|
|
2894
|
-
### If you are reviewing:
|
|
2895
|
-
|
|
2896
|
-
1. Fetch the PR details and diff
|
|
2897
|
-
2. Review for:
|
|
2898
|
-
- Code quality and style
|
|
2899
|
-
- Logic errors or bugs
|
|
2900
|
-
- Security concerns
|
|
2901
|
-
- Test coverage
|
|
2902
|
-
- Documentation
|
|
2903
|
-
3. Provide feedback with specific line references
|
|
2904
|
-
4. Approve, request changes, or comment
|
|
2905
|
-
|
|
2906
|
-
### If delegating to a reviewer:
|
|
2907
|
-
|
|
2908
|
-
1. Identify the appropriate reviewer based on the changes
|
|
2909
|
-
2. Create a review request message in their inbox
|
|
2910
|
-
3. Include PR link and context
|
|
2911
|
-
|
|
2912
|
-
## Review Checklist
|
|
2913
|
-
|
|
2914
|
-
- [ ] Code follows project conventions
|
|
2915
|
-
- [ ] No obvious bugs or edge cases
|
|
2916
|
-
- [ ] Tests cover the changes
|
|
2917
|
-
- [ ] Documentation updated if needed
|
|
2918
|
-
- [ ] No security vulnerabilities
|
|
2919
|
-
|
|
2920
|
-
## Output
|
|
2921
|
-
|
|
2922
|
-
Provide review summary with actionable feedback.
|
|
2923
|
-
`
|
|
2924
|
-
};
|
|
2925
|
-
var sprintStatusSkill = {
|
|
2926
|
-
name: "sprint-status",
|
|
2927
|
-
description: "Get current sprint status and progress",
|
|
2928
|
-
category: "optional",
|
|
2929
|
-
dependencies: [{ type: "issue_tracker", required: true, description: "For sprint data" }],
|
|
2930
|
-
content: `---
|
|
2931
|
-
description: Get current sprint status and progress
|
|
2932
|
-
requires: [issue_tracker]
|
|
2933
|
-
---
|
|
2934
|
-
|
|
2935
|
-
# Sprint Status
|
|
2936
|
-
|
|
2937
|
-
Get the current sprint status and team progress.
|
|
2938
|
-
|
|
2939
|
-
## Instructions
|
|
2940
|
-
|
|
2941
|
-
1. Query the active sprint for project {{JIRA_PROJECT}}
|
|
2942
|
-
2. Gather metrics:
|
|
2943
|
-
- Total story points committed
|
|
2944
|
-
- Points completed
|
|
2945
|
-
- Points in progress
|
|
2946
|
-
- Points remaining
|
|
2947
|
-
3. List tickets by status
|
|
2948
|
-
4. Identify blockers or at-risk items
|
|
2949
|
-
|
|
2950
|
-
## Output Format
|
|
2951
|
-
|
|
2952
|
-
\`\`\`
|
|
2953
|
-
Sprint: <sprint-name>
|
|
2954
|
-
Progress: XX/YY points (ZZ%)
|
|
2955
|
-
|
|
2956
|
-
## Completed
|
|
2957
|
-
- [{{JIRA_PROJECT}}-123] Task name (3 pts)
|
|
2958
|
-
|
|
2959
|
-
## In Progress
|
|
2960
|
-
- [{{JIRA_PROJECT}}-124] Task name (5 pts) - @assignee
|
|
2961
|
-
|
|
2962
|
-
## To Do
|
|
2963
|
-
- [{{JIRA_PROJECT}}-125] Task name (2 pts)
|
|
2964
|
-
|
|
2965
|
-
## Blocked
|
|
2966
|
-
- [{{JIRA_PROJECT}}-126] Task name - Reason
|
|
2967
|
-
\`\`\`
|
|
2968
|
-
|
|
2969
|
-
## Fallbacks
|
|
2970
|
-
|
|
2971
|
-
If issue tracker is unavailable:
|
|
2972
|
-
- Report that sprint data cannot be fetched
|
|
2973
|
-
- Suggest checking the issue tracker directly at {{JIRA_URL}}
|
|
2974
|
-
`
|
|
2975
|
-
};
|
|
2976
|
-
var jiraCreateSkill = {
|
|
2977
|
-
name: "jira-create",
|
|
2978
|
-
description: "Create a new Jira ticket",
|
|
2979
|
-
argumentHint: "<ticket-type> <summary>",
|
|
2980
|
-
category: "optional",
|
|
2981
|
-
dependencies: [{ type: "issue_tracker", required: true, description: "For ticket creation" }],
|
|
2982
|
-
content: `---
|
|
2983
|
-
description: Create a new Jira ticket
|
|
2984
|
-
argument-hint: <ticket-type> <summary>
|
|
2985
|
-
requires: [issue_tracker]
|
|
2986
|
-
---
|
|
2987
|
-
|
|
2988
|
-
# Create Jira Ticket
|
|
2989
|
-
|
|
2990
|
-
Create a new ticket in project {{JIRA_PROJECT}}.
|
|
2991
|
-
|
|
2992
|
-
## Instructions
|
|
2993
|
-
|
|
2994
|
-
1. Parse the ticket type and summary from arguments
|
|
2995
|
-
2. Gather additional details:
|
|
2996
|
-
- Description
|
|
2997
|
-
- Priority
|
|
2998
|
-
- Labels
|
|
2999
|
-
- Components (if applicable)
|
|
3000
|
-
3. Create the ticket via the issue tracker integration
|
|
3001
|
-
4. Return the ticket key and URL
|
|
3002
|
-
|
|
3003
|
-
## Ticket Types
|
|
3004
|
-
|
|
3005
|
-
- **Story**: User-facing feature
|
|
3006
|
-
- **Bug**: Defect to fix
|
|
3007
|
-
- **Task**: Technical work
|
|
3008
|
-
- **Spike**: Research/investigation
|
|
3009
|
-
|
|
3010
|
-
## Output
|
|
3011
|
-
|
|
3012
|
-
\`\`\`
|
|
3013
|
-
Created: {{JIRA_PROJECT}}-XXX
|
|
3014
|
-
URL: {{JIRA_URL}}/browse/{{JIRA_PROJECT}}-XXX
|
|
3015
|
-
Summary: <summary>
|
|
3016
|
-
Type: <type>
|
|
3017
|
-
\`\`\`
|
|
3018
|
-
|
|
3019
|
-
## Fallbacks
|
|
3020
|
-
|
|
3021
|
-
If issue tracker is unavailable:
|
|
3022
|
-
- Provide the user with manual creation instructions
|
|
3023
|
-
- Include all details they should enter
|
|
3024
|
-
`
|
|
3025
|
-
};
|
|
3026
|
-
var jiraTransitionSkill = {
|
|
3027
|
-
name: "jira-transition",
|
|
3028
|
-
description: "Transition a Jira ticket to a new status",
|
|
3029
|
-
argumentHint: "<ticket-key> to <status>",
|
|
3030
|
-
category: "optional",
|
|
3031
|
-
dependencies: [{ type: "issue_tracker", required: true, description: "For ticket transitions" }],
|
|
3032
|
-
content: `---
|
|
3033
|
-
description: Transition a Jira ticket to a new status
|
|
3034
|
-
argument-hint: <ticket-key> to <status>
|
|
3035
|
-
requires: [issue_tracker]
|
|
3036
|
-
---
|
|
3037
|
-
|
|
3038
|
-
# Transition Jira Ticket
|
|
3039
|
-
|
|
3040
|
-
Update the status of a ticket in {{JIRA_PROJECT}}.
|
|
3041
|
-
|
|
3042
|
-
## Status Mapping
|
|
3043
|
-
|
|
3044
|
-
| Workflow Status | Jira Status |
|
|
3045
|
-
|-----------------|-------------|
|
|
3046
|
-
| BACKLOG | Backlog |
|
|
3047
|
-
| IN_PROGRESS | In Progress |
|
|
3048
|
-
| PR_CREATED | In Review |
|
|
3049
|
-
| IN_REVIEW | In Review |
|
|
3050
|
-
| APPROVED | Ready to Merge |
|
|
3051
|
-
| MERGED | Done |
|
|
3052
|
-
| DONE | Done |
|
|
3053
|
-
|
|
3054
|
-
## Instructions
|
|
3055
|
-
|
|
3056
|
-
1. Parse ticket key and target status
|
|
3057
|
-
2. Validate the transition is allowed
|
|
3058
|
-
3. Add a comment explaining the transition
|
|
3059
|
-
4. Execute the transition
|
|
3060
|
-
|
|
3061
|
-
## Transition Comment Format
|
|
3062
|
-
|
|
3063
|
-
\`\`\`
|
|
3064
|
-
Status updated to <status>.
|
|
3065
|
-
<optional context about why>
|
|
3066
|
-
\`\`\`
|
|
3067
|
-
|
|
3068
|
-
## Fallbacks
|
|
3069
|
-
|
|
3070
|
-
If issue tracker is unavailable:
|
|
3071
|
-
- Instruct user to manually transition at {{JIRA_URL}}
|
|
3072
|
-
- Provide the target status name
|
|
3073
|
-
`
|
|
3074
|
-
};
|
|
3075
|
-
var docsUpdateSkill = {
|
|
3076
|
-
name: "docs-update",
|
|
3077
|
-
description: "Update project documentation",
|
|
3078
|
-
argumentHint: "<doc-path-or-topic>",
|
|
3079
|
-
category: "optional",
|
|
3080
|
-
dependencies: [{ type: "documentation", required: false, description: "For remote docs" }],
|
|
3081
|
-
content: `---
|
|
3082
|
-
description: Update project documentation
|
|
3083
|
-
argument-hint: <doc-path-or-topic>
|
|
3084
|
-
optional: [documentation]
|
|
3085
|
-
---
|
|
3086
|
-
|
|
3087
|
-
# Update Documentation
|
|
3088
|
-
|
|
3089
|
-
Update project documentation for a specific topic or file.
|
|
3090
|
-
|
|
3091
|
-
## Instructions
|
|
3092
|
-
|
|
3093
|
-
1. Identify the documentation to update:
|
|
3094
|
-
- Local: \`{{DOCS_PATH}}/\`
|
|
3095
|
-
- Remote: {{CONFLUENCE_SPACE}} (if configured)
|
|
3096
|
-
|
|
3097
|
-
2. Make the necessary updates:
|
|
3098
|
-
- Keep formatting consistent
|
|
3099
|
-
- Update examples if code changed
|
|
3100
|
-
- Add/update version information
|
|
3101
|
-
|
|
3102
|
-
3. For remote documentation:
|
|
3103
|
-
- Use the documentation integration
|
|
3104
|
-
- Or provide content for manual update
|
|
3105
|
-
|
|
3106
|
-
## Documentation Types
|
|
3107
|
-
|
|
3108
|
-
- **README**: Project overview and setup
|
|
3109
|
-
- **API Docs**: Endpoint documentation
|
|
3110
|
-
- **Architecture**: Design decisions
|
|
3111
|
-
- **Runbooks**: Operational procedures
|
|
3112
|
-
|
|
3113
|
-
## Fallbacks
|
|
3114
|
-
|
|
3115
|
-
If documentation integration is unavailable:
|
|
3116
|
-
- Create/update local markdown files
|
|
3117
|
-
- Provide instructions for manual remote update
|
|
3118
|
-
`
|
|
3119
|
-
};
|
|
3120
|
-
var builtInSkills = [
|
|
3121
|
-
checkInboxSkill,
|
|
3122
|
-
delegateSkill,
|
|
3123
|
-
gitCommitSkill,
|
|
3124
|
-
prCreateSkill,
|
|
3125
|
-
reviewSkill,
|
|
3126
|
-
sprintStatusSkill,
|
|
3127
|
-
jiraCreateSkill,
|
|
3128
|
-
jiraTransitionSkill,
|
|
3129
|
-
docsUpdateSkill
|
|
3130
|
-
];
|
|
3131
|
-
|
|
3132
|
-
// src/skills/generator.ts
|
|
2698
|
+
import { join as join6, dirname as dirname5 } from "path";
|
|
2699
|
+
function getCoreSkillsDir() {
|
|
2700
|
+
let currentDir = dirname5(import.meta.url.replace("file://", ""));
|
|
2701
|
+
for (let i = 0; i < 5; i++) {
|
|
2702
|
+
if (existsSync4(join6(currentDir, "package.json"))) {
|
|
2703
|
+
return join6(currentDir, "skills");
|
|
2704
|
+
}
|
|
2705
|
+
currentDir = dirname5(currentDir);
|
|
2706
|
+
}
|
|
2707
|
+
return join6(dirname5(dirname5(dirname5(import.meta.url.replace("file://", "")))), "skills");
|
|
2708
|
+
}
|
|
2709
|
+
function discoverSkills(skillsDir) {
|
|
2710
|
+
const templates = [];
|
|
2711
|
+
if (!existsSync4(skillsDir)) {
|
|
2712
|
+
return templates;
|
|
2713
|
+
}
|
|
2714
|
+
const categories = readdirSync2(skillsDir);
|
|
2715
|
+
for (const category of categories) {
|
|
2716
|
+
const categoryPath = join6(skillsDir, category);
|
|
2717
|
+
const stat = statSync(categoryPath);
|
|
2718
|
+
if (!stat.isDirectory()) continue;
|
|
2719
|
+
if (category.startsWith(".") || category.startsWith("_")) continue;
|
|
2720
|
+
const skillDirs = readdirSync2(categoryPath);
|
|
2721
|
+
for (const skillName of skillDirs) {
|
|
2722
|
+
const skillDir = join6(categoryPath, skillName);
|
|
2723
|
+
const skillStat = statSync(skillDir);
|
|
2724
|
+
if (!skillStat.isDirectory()) continue;
|
|
2725
|
+
const skillFile = join6(skillDir, "SKILL.md");
|
|
2726
|
+
if (!existsSync4(skillFile)) continue;
|
|
2727
|
+
try {
|
|
2728
|
+
const content = readFileSync4(skillFile, "utf-8");
|
|
2729
|
+
const template = parseSkillFile(skillName, category, content);
|
|
2730
|
+
templates.push(template);
|
|
2731
|
+
} catch {
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
return templates;
|
|
2736
|
+
}
|
|
2737
|
+
function parseSkillFile(name, category, content) {
|
|
2738
|
+
const template = {
|
|
2739
|
+
name,
|
|
2740
|
+
description: name,
|
|
2741
|
+
category,
|
|
2742
|
+
content
|
|
2743
|
+
};
|
|
2744
|
+
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
|
2745
|
+
if (!frontmatterMatch) {
|
|
2746
|
+
return template;
|
|
2747
|
+
}
|
|
2748
|
+
const frontmatter = frontmatterMatch[1];
|
|
2749
|
+
const lines = frontmatter.split(/\r?\n/);
|
|
2750
|
+
const dependencies = [];
|
|
2751
|
+
for (const line of lines) {
|
|
2752
|
+
const colonIndex = line.indexOf(":");
|
|
2753
|
+
if (colonIndex === -1) continue;
|
|
2754
|
+
const key = line.slice(0, colonIndex).trim();
|
|
2755
|
+
let value = line.slice(colonIndex + 1).trim();
|
|
2756
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
2757
|
+
value = value.slice(1, -1);
|
|
2758
|
+
}
|
|
2759
|
+
switch (key) {
|
|
2760
|
+
case "name":
|
|
2761
|
+
template.name = value;
|
|
2762
|
+
break;
|
|
2763
|
+
case "description":
|
|
2764
|
+
template.description = value;
|
|
2765
|
+
break;
|
|
2766
|
+
case "argument-hint":
|
|
2767
|
+
template.argumentHint = value;
|
|
2768
|
+
break;
|
|
2769
|
+
case "requires":
|
|
2770
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
2771
|
+
const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
|
|
2772
|
+
for (const item of items) {
|
|
2773
|
+
if (item) {
|
|
2774
|
+
dependencies.push({
|
|
2775
|
+
type: mapIntegrationName(item),
|
|
2776
|
+
required: true
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
break;
|
|
2782
|
+
case "optional":
|
|
2783
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
2784
|
+
const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
|
|
2785
|
+
for (const item of items) {
|
|
2786
|
+
if (item) {
|
|
2787
|
+
dependencies.push({
|
|
2788
|
+
type: mapIntegrationName(item),
|
|
2789
|
+
required: false
|
|
2790
|
+
});
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
break;
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
if (dependencies.length > 0) {
|
|
2798
|
+
template.dependencies = dependencies;
|
|
2799
|
+
}
|
|
2800
|
+
return template;
|
|
2801
|
+
}
|
|
2802
|
+
function mapIntegrationName(name) {
|
|
2803
|
+
const lower = name.toLowerCase();
|
|
2804
|
+
if (["jira", "linear", "issue_tracker", "issues", "github-issues"].includes(lower)) {
|
|
2805
|
+
return "issue_tracker";
|
|
2806
|
+
}
|
|
2807
|
+
if (["git", "github", "gitlab", "bitbucket"].includes(lower)) {
|
|
2808
|
+
return "git";
|
|
2809
|
+
}
|
|
2810
|
+
if (["docs", "documentation", "confluence", "notion", "wiki"].includes(lower)) {
|
|
2811
|
+
return "documentation";
|
|
2812
|
+
}
|
|
2813
|
+
return "state";
|
|
2814
|
+
}
|
|
3133
2815
|
function extractVariables2(config) {
|
|
3134
2816
|
const vars = {};
|
|
3135
2817
|
if (!config) {
|
|
@@ -3239,112 +2921,12 @@ function checkDependencies(skill, config) {
|
|
|
3239
2921
|
missing
|
|
3240
2922
|
};
|
|
3241
2923
|
}
|
|
3242
|
-
function loadCustomTemplates(templatesDir) {
|
|
3243
|
-
const templates = [];
|
|
3244
|
-
if (!existsSync4(templatesDir)) {
|
|
3245
|
-
return templates;
|
|
3246
|
-
}
|
|
3247
|
-
const files = readdirSync2(templatesDir);
|
|
3248
|
-
for (const file of files) {
|
|
3249
|
-
if (!file.endsWith(".md")) continue;
|
|
3250
|
-
const filePath = join6(templatesDir, file);
|
|
3251
|
-
const stat = statSync(filePath);
|
|
3252
|
-
if (!stat.isFile()) continue;
|
|
3253
|
-
try {
|
|
3254
|
-
const content = readFileSync4(filePath, "utf-8");
|
|
3255
|
-
const template = parseSkillTemplate(file, content);
|
|
3256
|
-
templates.push(template);
|
|
3257
|
-
} catch {
|
|
3258
|
-
}
|
|
3259
|
-
}
|
|
3260
|
-
return templates;
|
|
3261
|
-
}
|
|
3262
|
-
function parseSkillTemplate(filename, content) {
|
|
3263
|
-
const name = basename3(filename, ".md");
|
|
3264
|
-
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
|
3265
|
-
let description = name;
|
|
3266
|
-
let argumentHint;
|
|
3267
|
-
const dependencies = [];
|
|
3268
|
-
if (frontmatterMatch) {
|
|
3269
|
-
const frontmatter = frontmatterMatch[1] ?? "";
|
|
3270
|
-
const lines = frontmatter.split(/\r?\n/);
|
|
3271
|
-
for (const line of lines) {
|
|
3272
|
-
const colonIndex = line.indexOf(":");
|
|
3273
|
-
if (colonIndex === -1) continue;
|
|
3274
|
-
const key = line.slice(0, colonIndex).trim();
|
|
3275
|
-
let value = line.slice(colonIndex + 1).trim();
|
|
3276
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
3277
|
-
value = value.slice(1, -1);
|
|
3278
|
-
}
|
|
3279
|
-
switch (key) {
|
|
3280
|
-
case "description":
|
|
3281
|
-
description = value;
|
|
3282
|
-
break;
|
|
3283
|
-
case "argument-hint":
|
|
3284
|
-
argumentHint = value;
|
|
3285
|
-
break;
|
|
3286
|
-
case "requires":
|
|
3287
|
-
if (value.startsWith("[") && value.endsWith("]")) {
|
|
3288
|
-
const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
|
|
3289
|
-
for (const item of items) {
|
|
3290
|
-
if (item) {
|
|
3291
|
-
dependencies.push({
|
|
3292
|
-
type: mapIntegrationName(item),
|
|
3293
|
-
required: true
|
|
3294
|
-
});
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
break;
|
|
3299
|
-
case "optional":
|
|
3300
|
-
if (value.startsWith("[") && value.endsWith("]")) {
|
|
3301
|
-
const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
|
|
3302
|
-
for (const item of items) {
|
|
3303
|
-
if (item) {
|
|
3304
|
-
dependencies.push({
|
|
3305
|
-
type: mapIntegrationName(item),
|
|
3306
|
-
required: false
|
|
3307
|
-
});
|
|
3308
|
-
}
|
|
3309
|
-
}
|
|
3310
|
-
}
|
|
3311
|
-
break;
|
|
3312
|
-
}
|
|
3313
|
-
}
|
|
3314
|
-
}
|
|
3315
|
-
const template = {
|
|
3316
|
-
name,
|
|
3317
|
-
description,
|
|
3318
|
-
category: "custom",
|
|
3319
|
-
content
|
|
3320
|
-
};
|
|
3321
|
-
if (argumentHint) {
|
|
3322
|
-
template.argumentHint = argumentHint;
|
|
3323
|
-
}
|
|
3324
|
-
if (dependencies.length > 0) {
|
|
3325
|
-
template.dependencies = dependencies;
|
|
3326
|
-
}
|
|
3327
|
-
return template;
|
|
3328
|
-
}
|
|
3329
|
-
function mapIntegrationName(name) {
|
|
3330
|
-
const lower = name.toLowerCase();
|
|
3331
|
-
if (["jira", "linear", "issue_tracker", "issues", "github-issues"].includes(lower)) {
|
|
3332
|
-
return "issue_tracker";
|
|
3333
|
-
}
|
|
3334
|
-
if (["git", "github", "gitlab", "bitbucket"].includes(lower)) {
|
|
3335
|
-
return "git";
|
|
3336
|
-
}
|
|
3337
|
-
if (["docs", "documentation", "confluence", "notion", "wiki"].includes(lower)) {
|
|
3338
|
-
return "documentation";
|
|
3339
|
-
}
|
|
3340
|
-
return "state";
|
|
3341
|
-
}
|
|
3342
2924
|
function generateSkills(config, options = {}) {
|
|
3343
2925
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
3344
|
-
const
|
|
2926
|
+
const coreSkillsDir = options.coreSkillsDir ?? getCoreSkillsDir();
|
|
2927
|
+
const outputDir = options.outputDir ?? join6(projectRoot, ".claude", "skills");
|
|
3345
2928
|
const includeCoreSkills = options.includeCoreSkills ?? true;
|
|
3346
|
-
const
|
|
3347
|
-
const overwrite = options.overwrite ?? false;
|
|
2929
|
+
const overwrite = options.overwrite ?? true;
|
|
3348
2930
|
const result = {
|
|
3349
2931
|
generated: [],
|
|
3350
2932
|
errors: [],
|
|
@@ -3357,21 +2939,17 @@ function generateSkills(config, options = {}) {
|
|
|
3357
2939
|
result.variables = variables;
|
|
3358
2940
|
let templates = [];
|
|
3359
2941
|
if (includeCoreSkills) {
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
if (includeOptionalSkills) {
|
|
3363
|
-
templates.push(...builtInSkills.filter((s) => s.category === "optional"));
|
|
2942
|
+
const discovered = discoverSkills(coreSkillsDir);
|
|
2943
|
+
templates.push(...discovered);
|
|
3364
2944
|
}
|
|
3365
2945
|
if (options.customTemplatesDir && existsSync4(options.customTemplatesDir)) {
|
|
3366
|
-
|
|
2946
|
+
const custom = discoverSkills(options.customTemplatesDir);
|
|
2947
|
+
templates.push(...custom);
|
|
3367
2948
|
}
|
|
3368
2949
|
if (options.skills && options.skills.length > 0) {
|
|
3369
2950
|
const skillsToInclude = options.skills;
|
|
3370
2951
|
templates = templates.filter((t) => skillsToInclude.includes(t.name));
|
|
3371
2952
|
}
|
|
3372
|
-
if (!existsSync4(outputDir)) {
|
|
3373
|
-
mkdirSync2(outputDir, { recursive: true });
|
|
3374
|
-
}
|
|
3375
2953
|
for (const template of templates) {
|
|
3376
2954
|
try {
|
|
3377
2955
|
const generated = generateSkill(template, variables, config, outputDir, overwrite);
|
|
@@ -3386,7 +2964,8 @@ function generateSkills(config, options = {}) {
|
|
|
3386
2964
|
return result;
|
|
3387
2965
|
}
|
|
3388
2966
|
function generateSkill(template, variables, config, outputDir, overwrite) {
|
|
3389
|
-
const
|
|
2967
|
+
const skillDir = join6(outputDir, template.name);
|
|
2968
|
+
const outputPath = join6(skillDir, "SKILL.md");
|
|
3390
2969
|
if (existsSync4(outputPath) && !overwrite) {
|
|
3391
2970
|
return {
|
|
3392
2971
|
name: template.name,
|
|
@@ -3409,6 +2988,9 @@ function generateSkill(template, variables, config, outputDir, overwrite) {
|
|
|
3409
2988
|
}
|
|
3410
2989
|
const content = substituteVariables(template.content, variables);
|
|
3411
2990
|
const isUpdate = existsSync4(outputPath);
|
|
2991
|
+
if (!existsSync4(skillDir)) {
|
|
2992
|
+
mkdirSync2(skillDir, { recursive: true });
|
|
2993
|
+
}
|
|
3412
2994
|
writeFileSync2(outputPath, content, "utf-8");
|
|
3413
2995
|
return {
|
|
3414
2996
|
name: template.name,
|
|
@@ -3452,7 +3034,7 @@ function formatGenerateResult(result) {
|
|
|
3452
3034
|
}
|
|
3453
3035
|
const total = created.length + updated.length;
|
|
3454
3036
|
if (total > 0) {
|
|
3455
|
-
lines.push(`Generated ${total} skill(s) to .claude/
|
|
3037
|
+
lines.push(`Generated ${total} skill(s) to .claude/skills/`);
|
|
3456
3038
|
} else if (result.generated.length === 0 && result.errors.length === 0) {
|
|
3457
3039
|
lines.push("No skills to generate.");
|
|
3458
3040
|
}
|
|
@@ -3469,7 +3051,7 @@ import {
|
|
|
3469
3051
|
renameSync,
|
|
3470
3052
|
statSync as statSync2
|
|
3471
3053
|
} from "fs";
|
|
3472
|
-
import { join as join7, basename as
|
|
3054
|
+
import { join as join7, basename as basename3 } from "path";
|
|
3473
3055
|
var DEFAULT_KNOWLEDGE_LIBRARY_PATH = "KnowledgeLibrary";
|
|
3474
3056
|
var STANDARD_FILES = {
|
|
3475
3057
|
context: "context.txt",
|
|
@@ -3993,9 +3575,9 @@ function formatKnowledgeLibraryState(state) {
|
|
|
3993
3575
|
lines.push(`KnowledgeLibrary: ${state.basePath}
|
|
3994
3576
|
`);
|
|
3995
3577
|
lines.push("Global files:");
|
|
3996
|
-
lines.push(` - ${
|
|
3997
|
-
lines.push(` - ${
|
|
3998
|
-
lines.push(` - ${
|
|
3578
|
+
lines.push(` - ${basename3(state.contextPath)}`);
|
|
3579
|
+
lines.push(` - ${basename3(state.architecturePath)}`);
|
|
3580
|
+
lines.push(` - ${basename3(state.prdPath)}`);
|
|
3999
3581
|
lines.push("");
|
|
4000
3582
|
if (state.agents.length > 0) {
|
|
4001
3583
|
lines.push(`Agents (${state.agents.length}):`);
|
|
@@ -4040,8 +3622,8 @@ function formatAgentKnowledgeState(state) {
|
|
|
4040
3622
|
|
|
4041
3623
|
// src/index.ts
|
|
4042
3624
|
function findPackageJson() {
|
|
4043
|
-
let dir =
|
|
4044
|
-
while (dir !==
|
|
3625
|
+
let dir = dirname6(fileURLToPath(import.meta.url));
|
|
3626
|
+
while (dir !== dirname6(dir)) {
|
|
4045
3627
|
const pkgPath = join8(dir, "package.json");
|
|
4046
3628
|
try {
|
|
4047
3629
|
const content = readFileSync6(pkgPath, "utf-8");
|
|
@@ -4051,7 +3633,7 @@ function findPackageJson() {
|
|
|
4051
3633
|
}
|
|
4052
3634
|
} catch {
|
|
4053
3635
|
}
|
|
4054
|
-
dir =
|
|
3636
|
+
dir = dirname6(dir);
|
|
4055
3637
|
}
|
|
4056
3638
|
return '{"version": "unknown"}';
|
|
4057
3639
|
}
|
|
@@ -4077,7 +3659,6 @@ export {
|
|
|
4077
3659
|
StepTracker,
|
|
4078
3660
|
VERSION,
|
|
4079
3661
|
agentKnowledgeLibraryExists,
|
|
4080
|
-
builtInSkills,
|
|
4081
3662
|
checkDependencies,
|
|
4082
3663
|
cleanupContext,
|
|
4083
3664
|
compileAgent,
|
|
@@ -4091,6 +3672,7 @@ export {
|
|
|
4091
3672
|
createContextLoader,
|
|
4092
3673
|
createDegradingHandler,
|
|
4093
3674
|
createFileCacheProvider,
|
|
3675
|
+
discoverSkills,
|
|
4094
3676
|
executeWithDegradation,
|
|
4095
3677
|
extractVariables2 as extractSkillVariables,
|
|
4096
3678
|
extractVariables,
|
|
@@ -4106,6 +3688,7 @@ export {
|
|
|
4106
3688
|
getAgentKnowledgeState,
|
|
4107
3689
|
getConfigPath,
|
|
4108
3690
|
getCoreAgentsDir,
|
|
3691
|
+
getCoreSkillsDir,
|
|
4109
3692
|
getGlobalRegistry,
|
|
4110
3693
|
getKnowledgeLibraryState,
|
|
4111
3694
|
getRoleFromFilename,
|
|
@@ -4121,9 +3704,9 @@ export {
|
|
|
4121
3704
|
loadConfig,
|
|
4122
3705
|
loadConfigFromFile,
|
|
4123
3706
|
loadCoreAICommands,
|
|
4124
|
-
loadCustomTemplates,
|
|
4125
3707
|
markMessageProcessed,
|
|
4126
3708
|
parseAgentYaml,
|
|
3709
|
+
parseSkillFile,
|
|
4127
3710
|
readInboxMessages,
|
|
4128
3711
|
resetGlobalRegistry,
|
|
4129
3712
|
resolveAgentDefinition,
|