This commit is contained in:
2025-12-15 15:54:25 +00:00
parent 3485392979
commit 90af6eb1b1
3 changed files with 55 additions and 23 deletions

View File

@@ -29,7 +29,7 @@
"@push.rocks/early": "^4.0.4",
"@push.rocks/npmextra": "^5.3.3",
"@push.rocks/qenv": "^6.1.3",
"@push.rocks/smartagent": "file:../../push.rocks/smartagent",
"@push.rocks/smartagent": "1.2.5",
"@push.rocks/smartai": "^0.8.0",
"@push.rocks/smartcli": "^4.0.19",
"@push.rocks/smartdelay": "^3.0.5",

11
pnpm-lock.yaml generated
View File

@@ -21,8 +21,8 @@ importers:
specifier: ^6.1.3
version: 6.1.3
'@push.rocks/smartagent':
specifier: file:../../push.rocks/smartagent
version: file:../../push.rocks/smartagent(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
specifier: 1.2.5
version: 1.2.5(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
'@push.rocks/smartai':
specifier: ^0.8.0
version: 0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
@@ -1155,8 +1155,8 @@ packages:
'@push.rocks/qenv@6.1.3':
resolution: {integrity: sha512-+z2hsAU/7CIgpYLFqvda8cn9rUBMHqLdQLjsFfRn5jPoD7dJ5rFlpkbhfM4Ws8mHMniwWaxGKo+q/YBhtzRBLg==}
'@push.rocks/smartagent@file:../../push.rocks/smartagent':
resolution: {directory: ../../push.rocks/smartagent, type: directory}
'@push.rocks/smartagent@1.2.5':
resolution: {integrity: sha512-qV7zyHbp5p5ySg16uipjIdYzKM85fn5/l97pKlZz9awRZhOcvYblmypQRKHlMc+O2mVevxLY4Q/6pzYwI8UXvw==}
'@push.rocks/smartai@0.8.0':
resolution: {integrity: sha512-guzi28meUDc3mydC8kpoA+4pzExRQqygXYFDD4qQSWPpIRHQ7qhpeNqJzrrGezT1yOH5Gb9taPEGwT56hI+nwQ==}
@@ -6920,7 +6920,7 @@ snapshots:
'@push.rocks/smartlog': 3.1.10
'@push.rocks/smartpath': 6.0.0
'@push.rocks/smartagent@file:../../push.rocks/smartagent(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)':
'@push.rocks/smartagent@1.2.5(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)':
dependencies:
'@push.rocks/smartai': 0.8.0(typescript@5.9.3)(ws@8.18.3)(zod@3.25.76)
'@push.rocks/smartbrowser': 2.0.8(typescript@5.9.3)
@@ -6928,6 +6928,7 @@ snapshots:
'@push.rocks/smartfs': 1.2.0
'@push.rocks/smartrequest': 5.0.1
'@push.rocks/smartshell': 3.3.0
minimatch: 10.1.1
transitivePeerDependencies:
- aws-crt
- bare-abort-controller

View File

@@ -116,7 +116,6 @@ export class Commit {
}
// Use DualAgentOrchestrator for commit message generation
// Note: No filesystem tool needed - the diff already contains all change information
const commitOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
@@ -125,43 +124,65 @@ export class Commit {
guardianPolicyPrompt: `
You validate commit messages for semantic versioning compliance.
APPROVE if:
APPROVE tool calls for:
- Reading package.json or source files to understand project context
- Using tree to see project structure
- Listing directory contents
REJECT tool calls for:
- Reading files outside the project directory
- Writing, deleting, or modifying any files
- Any destructive operations
APPROVE final output if:
- Version level (fix/feat/BREAKING CHANGE) matches the scope of changes in the diff
- Commit message is clear, professional, and follows conventional commit conventions
- No personal information, licensing details, or AI mentions (Claude/Codex) included
- JSON structure is valid with all required fields
- Scope accurately reflects the changed modules/files
REJECT with specific feedback if:
REJECT final output if:
- Version level doesn't match the scope of changes (e.g., "feat" for a typo fix should be "fix")
- Message is vague, unprofessional, or contains sensitive information
- JSON is malformed or missing required fields
`,
});
// Register scoped filesystem tool for agent exploration
commitOrchestrator.registerScopedFilesystemTool(this.projectDir, [
'.nogit/**',
'node_modules/**',
'.git/**',
'dist/**',
'dist_*/**',
]);
await commitOrchestrator.start();
const commitTaskPrompt = `
You create a commit message for a git commit.
Project directory: ${this.projectDir}
You have access to a filesystem tool to explore the project if needed:
- Use tree to see project structure
- Use read to read package.json or source files for context
Analyze the git diff below to understand what changed and generate a commit message.
You should not include any licensing information or personal information.
Never mention CLAUDE code, or codex.
Important: Answer only in valid JSON.
Your final output (inside the task_complete tags) must be ONLY valid JSON - the raw JSON object, nothing else.
No explanations, no summaries, no markdown - just the JSON object that can be parsed with JSON.parse().
Your answer should be parseable with JSON.parse() without modifying anything.
Here is the structure of the JSON you must return:
Here is the structure of the JSON you should return:
interface {
recommendedNextVersionLevel: 'fix' | 'feat' | 'BREAKING CHANGE'; // the recommended next version level
recommendedNextVersionScope: string; // scope name like "core", "cli", or specific class names
recommendedNextVersionMessage: string; // the commit message (don't include fix/feat prefix)
recommendedNextVersionDetails: string[]; // detailed bullet points for the changelog
recommendedNextVersion: string; // the recommended next version x.x.x
{
"recommendedNextVersionLevel": "fix" | "feat" | "BREAKING CHANGE",
"recommendedNextVersionScope": "string",
"recommendedNextVersionMessage": "string",
"recommendedNextVersionDetails": ["string"],
"recommendedNextVersion": "x.x.x"
}
For recommendedNextVersionDetails, only add entries that have obvious value to the reader.
@@ -170,7 +191,7 @@ Here is the git diff showing what changed:
${processedDiffString}
Generate the commit message based on these changes.
Analyze these changes and output the JSON commit message object.
`;
const commitResult = await commitOrchestrator.run(commitTaskPrompt);
@@ -180,9 +201,19 @@ Generate the commit message based on these changes.
throw new Error(`Commit message generation failed: ${commitResult.status}`);
}
const resultObject: INextCommitObject = JSON.parse(
commitResult.result.replace('```json', '').replace('```', '')
);
// Extract JSON from result - handle cases where AI adds text around it
let jsonString = commitResult.result
.replace(/```json\n?/gi, '')
.replace(/```\n?/gi, '');
// Try to find JSON object in the result
const jsonMatch = jsonString.match(/\{[\s\S]*\}/);
if (!jsonMatch) {
throw new Error(`Could not find JSON object in result: ${jsonString.substring(0, 100)}...`);
}
jsonString = jsonMatch[0];
const resultObject: INextCommitObject = JSON.parse(jsonString);
const previousChangelogPath = plugins.path.join(this.projectDir, 'changelog.md');
let previousChangelog: plugins.smartfile.SmartFile;