@eldrforge/ai-service 0.1.22 → 1.0.1
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/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1680,9 +1680,11 @@ function createGetFileModificationTimesTool() {
|
|
|
1680
1680
|
async function runAgenticCommit(config) {
|
|
1681
1681
|
const {
|
|
1682
1682
|
changedFiles,
|
|
1683
|
-
diffContent,
|
|
1683
|
+
diffContent: _diffContent,
|
|
1684
|
+
// Optional - AI can use tools to read files
|
|
1684
1685
|
userDirection,
|
|
1685
|
-
logContext,
|
|
1686
|
+
logContext: _logContext,
|
|
1687
|
+
// Optional - AI can use get_recent_commits tool
|
|
1686
1688
|
model = "gpt-4o",
|
|
1687
1689
|
maxIterations = 10,
|
|
1688
1690
|
debug = false,
|
|
@@ -1700,14 +1702,8 @@ async function runAgenticCommit(config) {
|
|
|
1700
1702
|
});
|
|
1701
1703
|
const tools = createCommitTools();
|
|
1702
1704
|
toolRegistry.registerAll(tools);
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1705
|
-
includeExamples: true,
|
|
1706
|
-
explainWhenToUse: true,
|
|
1707
|
-
includeCategories: true
|
|
1708
|
-
});
|
|
1709
|
-
const systemPrompt = buildSystemPrompt$3(toolGuidance);
|
|
1710
|
-
const userMessage = buildUserMessage$2(changedFiles, diffContent, userDirection, logContext);
|
|
1705
|
+
const systemPrompt = buildSystemPrompt$3();
|
|
1706
|
+
const userMessage = buildUserMessage$2(changedFiles, userDirection);
|
|
1711
1707
|
const messages = [
|
|
1712
1708
|
{ role: "system", content: systemPrompt },
|
|
1713
1709
|
{ role: "user", content: userMessage }
|
|
@@ -1741,10 +1737,22 @@ async function runAgenticCommit(config) {
|
|
|
1741
1737
|
toolMetrics: result.toolMetrics
|
|
1742
1738
|
};
|
|
1743
1739
|
}
|
|
1744
|
-
function buildSystemPrompt$3(
|
|
1740
|
+
function buildSystemPrompt$3() {
|
|
1745
1741
|
return `You are a professional software engineer writing commit messages for your team.
|
|
1746
1742
|
|
|
1747
|
-
|
|
1743
|
+
## Available Tools
|
|
1744
|
+
|
|
1745
|
+
You have access to tools to investigate the changes:
|
|
1746
|
+
- \`get_file_content\` - Read file contents or diffs for specific files
|
|
1747
|
+
- \`get_file_modification_times\` - See when files were modified relative to each other
|
|
1748
|
+
- \`group_files_by_concern\` - Understand how files relate by type/purpose
|
|
1749
|
+
- \`get_recent_commits\` - Get recent commit history to avoid duplicates
|
|
1750
|
+
- \`get_file_history\` - Understand how code evolved
|
|
1751
|
+
- \`get_file_dependencies\` - Assess impact of changes
|
|
1752
|
+
- \`get_related_tests\` - Find related test files
|
|
1753
|
+
- \`search_codebase\` - Search for usage patterns
|
|
1754
|
+
|
|
1755
|
+
Use these tools to investigate the changes rather than asking for information upfront.
|
|
1748
1756
|
|
|
1749
1757
|
## Your Task
|
|
1750
1758
|
|
|
@@ -1850,37 +1858,30 @@ Split 3:
|
|
|
1850
1858
|
|
|
1851
1859
|
Output only the commit message and splits. No conversational remarks or follow-up offers.`;
|
|
1852
1860
|
}
|
|
1853
|
-
function buildUserMessage$2(changedFiles,
|
|
1861
|
+
function buildUserMessage$2(changedFiles, userDirection) {
|
|
1854
1862
|
const fileCount = changedFiles.length;
|
|
1855
1863
|
const manyFiles = fileCount >= 5;
|
|
1856
1864
|
let message = `I have staged changes that need a commit message.
|
|
1857
1865
|
|
|
1858
1866
|
Changed files (${fileCount}):
|
|
1859
|
-
${changedFiles.map((f) => ` - ${f}`).join("\n")}
|
|
1860
|
-
|
|
1861
|
-
Diff:
|
|
1862
|
-
${diffContent}`;
|
|
1867
|
+
${changedFiles.map((f) => ` - ${f}`).join("\n")}`;
|
|
1863
1868
|
if (userDirection) {
|
|
1864
1869
|
message += `
|
|
1865
1870
|
|
|
1866
1871
|
User direction: ${userDirection}`;
|
|
1867
|
-
}
|
|
1868
|
-
if (logContext) {
|
|
1869
|
-
message += `
|
|
1870
|
-
|
|
1871
|
-
Recent commit history for context:
|
|
1872
|
-
${logContext}`;
|
|
1873
1872
|
}
|
|
1874
1873
|
message += `
|
|
1875
1874
|
|
|
1876
1875
|
## Your Analysis Task
|
|
1877
1876
|
|
|
1878
|
-
${manyFiles ? `With ${fileCount} files changed,
|
|
1877
|
+
${manyFiles ? `With ${fileCount} files changed, investigate whether these represent multiple distinct changes that should be split into separate commits.
|
|
1879
1878
|
|
|
1880
|
-
` : ""}
|
|
1881
|
-
1. Use \`
|
|
1882
|
-
2. Use \`
|
|
1883
|
-
3.
|
|
1879
|
+
` : ""}Use your tools to investigate the changes:
|
|
1880
|
+
1. Use \`get_file_content\` to read the actual changes in the files
|
|
1881
|
+
2. Use \`get_file_modification_times\` to see when files were modified relative to each other
|
|
1882
|
+
3. Use \`group_files_by_concern\` to understand how files relate by type/purpose
|
|
1883
|
+
4. Use \`get_recent_commits\` to check recent commit history and avoid duplicates
|
|
1884
|
+
5. Cross-reference temporal proximity and logical relatedness to determine the best commit structure
|
|
1884
1885
|
|
|
1885
1886
|
Consider:
|
|
1886
1887
|
- What distinct features, fixes, or improvements are included?
|
|
@@ -1889,8 +1890,7 @@ Consider:
|
|
|
1889
1890
|
|
|
1890
1891
|
${manyFiles ? "With many files, consider whether multiple focused commits would be clearer than one large commit." : "If changes represent multiple logical concerns, suggest splits."}
|
|
1891
1892
|
|
|
1892
|
-
|
|
1893
|
-
Don't force connections that don't exist - focus on what actually changed.`;
|
|
1893
|
+
Start by reading the file contents to understand what actually changed.`;
|
|
1894
1894
|
return message;
|
|
1895
1895
|
}
|
|
1896
1896
|
function sanitizeFilePath(filePath) {
|
|
@@ -2596,11 +2596,14 @@ async function runAgenticRelease(config) {
|
|
|
2596
2596
|
const {
|
|
2597
2597
|
fromRef,
|
|
2598
2598
|
toRef,
|
|
2599
|
-
logContent,
|
|
2600
|
-
|
|
2599
|
+
logContent: _logContent,
|
|
2600
|
+
// Optional - AI can use tools to get commit log
|
|
2601
|
+
diffContent: _diffContent,
|
|
2602
|
+
// Optional - AI can use tools to get diffs
|
|
2601
2603
|
milestoneIssues,
|
|
2602
2604
|
releaseFocus,
|
|
2603
2605
|
userContext,
|
|
2606
|
+
targetVersion,
|
|
2604
2607
|
model = "gpt-4o",
|
|
2605
2608
|
maxIterations = 30,
|
|
2606
2609
|
debug = false,
|
|
@@ -2618,21 +2621,14 @@ async function runAgenticRelease(config) {
|
|
|
2618
2621
|
});
|
|
2619
2622
|
const tools = createReleaseTools();
|
|
2620
2623
|
toolRegistry.registerAll(tools);
|
|
2621
|
-
const
|
|
2622
|
-
strategy: "adaptive",
|
|
2623
|
-
includeExamples: true,
|
|
2624
|
-
explainWhenToUse: true,
|
|
2625
|
-
includeCategories: true
|
|
2626
|
-
});
|
|
2627
|
-
const systemPrompt = buildSystemPrompt$2(toolGuidance);
|
|
2624
|
+
const systemPrompt = buildSystemPrompt$2();
|
|
2628
2625
|
const userMessage = buildUserMessage$1({
|
|
2629
2626
|
fromRef,
|
|
2630
2627
|
toRef,
|
|
2631
|
-
logContent,
|
|
2632
|
-
diffContent,
|
|
2633
2628
|
milestoneIssues,
|
|
2634
2629
|
releaseFocus,
|
|
2635
|
-
userContext
|
|
2630
|
+
userContext,
|
|
2631
|
+
targetVersion
|
|
2636
2632
|
});
|
|
2637
2633
|
const messages = [
|
|
2638
2634
|
{ role: "system", content: systemPrompt },
|
|
@@ -2666,10 +2662,26 @@ async function runAgenticRelease(config) {
|
|
|
2666
2662
|
toolMetrics: result.toolMetrics
|
|
2667
2663
|
};
|
|
2668
2664
|
}
|
|
2669
|
-
function buildSystemPrompt$2(
|
|
2665
|
+
function buildSystemPrompt$2() {
|
|
2670
2666
|
return `You are a professional software engineer writing release notes for your team and users.
|
|
2671
2667
|
|
|
2672
|
-
|
|
2668
|
+
## Available Tools
|
|
2669
|
+
|
|
2670
|
+
You have access to tools to investigate the release:
|
|
2671
|
+
- \`get_tag_history\` - Understand release patterns
|
|
2672
|
+
- \`get_release_stats\` - Quantify scope of changes
|
|
2673
|
+
- \`compare_previous_release\` - See how this compares to previous releases
|
|
2674
|
+
- \`group_files_by_concern\` - Identify themes in changes
|
|
2675
|
+
- \`analyze_commit_patterns\` - Detect patterns in commits
|
|
2676
|
+
- \`get_file_content\` - Read file contents or diffs
|
|
2677
|
+
- \`analyze_diff_section\` - Expand unclear changes
|
|
2678
|
+
- \`get_file_history\` - Understand how code evolved
|
|
2679
|
+
- \`get_file_dependencies\` - Assess impact and reach
|
|
2680
|
+
- \`search_codebase\` - Find usage patterns
|
|
2681
|
+
- \`get_related_tests\` - Understand behavior changes
|
|
2682
|
+
- \`get_breaking_changes\` - Identify breaking changes (always use this)
|
|
2683
|
+
|
|
2684
|
+
Use these tools to investigate the changes rather than asking for information upfront.
|
|
2673
2685
|
|
|
2674
2686
|
## Your Task
|
|
2675
2687
|
|
|
@@ -2731,25 +2743,26 @@ Structure your notes logically:
|
|
|
2731
2743
|
|
|
2732
2744
|
## Output Format
|
|
2733
2745
|
|
|
2734
|
-
When ready,
|
|
2746
|
+
When ready, output your release notes in this exact format:
|
|
2735
2747
|
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
"title": "Clear, factual title describing the main changes",
|
|
2739
|
-
"body": "Detailed release notes in Markdown format"
|
|
2740
|
-
}
|
|
2748
|
+
RELEASE_TITLE:
|
|
2749
|
+
[A clear, factual title describing the main changes]
|
|
2741
2750
|
|
|
2742
|
-
|
|
2751
|
+
RELEASE_BODY:
|
|
2752
|
+
[Detailed release notes in Markdown format]
|
|
2753
|
+
|
|
2754
|
+
Do not include any JSON, code blocks, or wrapper syntax. Output plain text and markdown only.
|
|
2755
|
+
No conversational remarks or follow-up offers.`;
|
|
2743
2756
|
}
|
|
2744
2757
|
function buildUserMessage$1(params) {
|
|
2745
|
-
const { fromRef, toRef,
|
|
2746
|
-
let message = `I need comprehensive release notes for changes from ${fromRef} to ${toRef}
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2758
|
+
const { fromRef, toRef, milestoneIssues, releaseFocus, userContext, targetVersion } = params;
|
|
2759
|
+
let message = `I need comprehensive release notes for changes from ${fromRef} to ${toRef}.`;
|
|
2760
|
+
if (targetVersion) {
|
|
2761
|
+
const versionNumber = targetVersion.replace(/^v/, "");
|
|
2762
|
+
message += `
|
|
2750
2763
|
|
|
2751
|
-
|
|
2752
|
-
|
|
2764
|
+
**CRITICAL VERSION INSTRUCTION: This is a release for version ${versionNumber}. You MUST use EXACTLY "${versionNumber}" in your release title. DO NOT use any development/prerelease version numbers you may see in the diff (like ${versionNumber}-dev.0 or similar). The release version is ${versionNumber}.**`;
|
|
2765
|
+
}
|
|
2753
2766
|
if (milestoneIssues) {
|
|
2754
2767
|
message += `
|
|
2755
2768
|
|
|
@@ -2772,7 +2785,18 @@ ${userContext}`;
|
|
|
2772
2785
|
}
|
|
2773
2786
|
message += `
|
|
2774
2787
|
|
|
2775
|
-
|
|
2788
|
+
## Your Analysis Task
|
|
2789
|
+
|
|
2790
|
+
Use your tools to investigate the changes between ${fromRef} and ${toRef}:
|
|
2791
|
+
1. Use \`get_release_stats\` to understand the scope of changes
|
|
2792
|
+
2. Use \`get_tag_history\` or \`compare_previous_release\` to see release patterns
|
|
2793
|
+
3. Use \`analyze_commit_patterns\` to detect themes
|
|
2794
|
+
4. Use \`group_files_by_concern\` to identify logical groupings
|
|
2795
|
+
5. Use \`get_breaking_changes\` to identify breaking changes (always check this)
|
|
2796
|
+
6. Use \`get_file_content\` or \`analyze_diff_section\` to understand specific changes
|
|
2797
|
+
7. Use \`get_file_dependencies\` and \`search_codebase\` to assess impact
|
|
2798
|
+
|
|
2799
|
+
Write clear release notes that answer:
|
|
2776
2800
|
- What's the main story of this release?
|
|
2777
2801
|
- What problems does it solve?
|
|
2778
2802
|
- What's the impact on users and developers?
|
|
@@ -2782,37 +2806,29 @@ If context information is provided, use it only if relevant to this specific pac
|
|
|
2782
2806
|
Don't force connections that don't exist - if context describes changes in other packages
|
|
2783
2807
|
or unrelated features, simply ignore it and focus on what actually changed in this release.
|
|
2784
2808
|
|
|
2785
|
-
|
|
2809
|
+
Start by gathering statistics and understanding the scope, then investigate specific changes as needed.`;
|
|
2786
2810
|
return message;
|
|
2787
2811
|
}
|
|
2788
2812
|
function parseAgenticResult(finalMessage) {
|
|
2789
|
-
const
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
if (parsed && parsed.title && parsed.body) {
|
|
2800
|
-
return {
|
|
2801
|
-
releaseNotes: {
|
|
2802
|
-
title: parsed.title,
|
|
2803
|
-
body: parsed.body
|
|
2804
|
-
}
|
|
2805
|
-
};
|
|
2813
|
+
const titleMatch = finalMessage.match(/RELEASE_TITLE:\s*\n(.*?)(?=\n\nRELEASE_BODY:|\n\s*\nRELEASE_BODY:)/s);
|
|
2814
|
+
const bodyMatch = finalMessage.match(/RELEASE_BODY:\s*\n([\s\S]*)/);
|
|
2815
|
+
if (titleMatch && bodyMatch) {
|
|
2816
|
+
const title2 = titleMatch[1].trim();
|
|
2817
|
+
let body2 = bodyMatch[1].trim();
|
|
2818
|
+
body2 = cleanJsonArtifacts(body2);
|
|
2819
|
+
return {
|
|
2820
|
+
releaseNotes: {
|
|
2821
|
+
title: title2,
|
|
2822
|
+
body: body2
|
|
2806
2823
|
}
|
|
2807
|
-
}
|
|
2808
|
-
}
|
|
2824
|
+
};
|
|
2809
2825
|
}
|
|
2810
2826
|
const lines = finalMessage.split("\n");
|
|
2811
2827
|
let title = "";
|
|
2812
2828
|
let body = "";
|
|
2813
2829
|
let inBody = false;
|
|
2814
2830
|
for (const line of lines) {
|
|
2815
|
-
if (!title && line.trim() && !line.startsWith("#")) {
|
|
2831
|
+
if (!title && line.trim() && !line.startsWith("#") && !line.startsWith("RELEASE_")) {
|
|
2816
2832
|
title = line.trim();
|
|
2817
2833
|
} else if (title && line.trim()) {
|
|
2818
2834
|
inBody = true;
|
|
@@ -2825,6 +2841,7 @@ function parseAgenticResult(finalMessage) {
|
|
|
2825
2841
|
title = "Release Notes";
|
|
2826
2842
|
body = finalMessage;
|
|
2827
2843
|
}
|
|
2844
|
+
body = cleanJsonArtifacts(body);
|
|
2828
2845
|
return {
|
|
2829
2846
|
releaseNotes: {
|
|
2830
2847
|
title: title.trim(),
|
|
@@ -2832,6 +2849,15 @@ function parseAgenticResult(finalMessage) {
|
|
|
2832
2849
|
}
|
|
2833
2850
|
};
|
|
2834
2851
|
}
|
|
2852
|
+
function cleanJsonArtifacts(text) {
|
|
2853
|
+
text = text.replace(/^\s*\{\s*"title":\s*"[^"]*",?\s*"body":\s*"/m, "");
|
|
2854
|
+
text = text.replace(/"\s*\}\s*$/m, "");
|
|
2855
|
+
text = text.replace(/^```json\s*\n/gm, "");
|
|
2856
|
+
text = text.replace(/^```\s*$/gm, "");
|
|
2857
|
+
text = text.replace(/\\"/g, '"');
|
|
2858
|
+
text = text.replace(/\\n/g, "\n");
|
|
2859
|
+
return text.trim();
|
|
2860
|
+
}
|
|
2835
2861
|
function createPublishTools() {
|
|
2836
2862
|
return [
|
|
2837
2863
|
createCheckGitStatusTool(),
|