BREAKING CHANGE(aidoc): migrate agent orchestration to new runAgent API and filesystem tools; refactor model handling and update README and tests

This commit is contained in:
2026-03-11 18:58:48 +00:00
parent 883985dbc0
commit 6b2957b272
11 changed files with 834 additions and 3270 deletions

View File

@@ -103,7 +103,7 @@ export class Commit {
const totalChars = diffStringArray.join('\n\n').length;
const estimatedTokens = Math.ceil(totalChars / 4);
console.log(`📊 Raw git diff statistics:`);
console.log(`Raw git diff statistics:`);
console.log(` Files changed: ${diffStringArray.length}`);
console.log(` Total characters: ${totalChars.toLocaleString()}`);
console.log(` Estimated tokens: ${estimatedTokens.toLocaleString()}`);
@@ -111,7 +111,7 @@ export class Commit {
// Calculate available tokens for diff based on total budget
const maxDiffTokens = calculateMaxDiffTokens();
console.log(`📊 Token budget: ${maxDiffTokens.toLocaleString()} tokens for diff (limit: ${TOKEN_BUDGET.OPENAI_CONTEXT_LIMIT.toLocaleString()}, overhead: ${(TOKEN_BUDGET.SMARTAGENT_OVERHEAD + TOKEN_BUDGET.TASK_PROMPT_OVERHEAD).toLocaleString()})`);
console.log(`Token budget: ${maxDiffTokens.toLocaleString()} tokens for diff (limit: ${TOKEN_BUDGET.OPENAI_CONTEXT_LIMIT.toLocaleString()}, overhead: ${(TOKEN_BUDGET.SMARTAGENT_OVERHEAD + TOKEN_BUDGET.TASK_PROMPT_OVERHEAD).toLocaleString()})`);
// Use DiffProcessor to intelligently handle large diffs
const diffProcessor = new DiffProcessor({
@@ -125,14 +125,14 @@ export class Commit {
const processedDiff = diffProcessor.processDiffs(diffStringArray);
processedDiffString = diffProcessor.formatForContext(processedDiff);
console.log(`📝 Processed diff statistics:`);
console.log(`Processed diff statistics:`);
console.log(` Full diffs: ${processedDiff.fullDiffs.length} files`);
console.log(` Summarized: ${processedDiff.summarizedDiffs.length} files`);
console.log(` Metadata only: ${processedDiff.metadataOnly.length} files`);
console.log(` Final tokens: ${processedDiff.totalTokens.toLocaleString()}`);
if (estimatedTokens > 50000) {
console.log(`DiffProcessor reduced token usage: ${estimatedTokens.toLocaleString()} ${processedDiff.totalTokens.toLocaleString()}`);
console.log(`DiffProcessor reduced token usage: ${estimatedTokens.toLocaleString()} -> ${processedDiff.totalTokens.toLocaleString()}`);
}
// Validate total tokens won't exceed limit
@@ -141,71 +141,44 @@ export class Commit {
+ TOKEN_BUDGET.TASK_PROMPT_OVERHEAD;
if (totalEstimatedTokens > TOKEN_BUDGET.OPENAI_CONTEXT_LIMIT - TOKEN_BUDGET.SAFETY_MARGIN) {
console.log(`⚠️ Warning: Estimated tokens (${totalEstimatedTokens.toLocaleString()}) approaching limit`);
console.log(`Warning: Estimated tokens (${totalEstimatedTokens.toLocaleString()}) approaching limit`);
console.log(` Consider splitting into smaller commits`);
}
} else {
processedDiffString = 'No changes.';
}
// Use DualAgentOrchestrator for commit message generation
const commitOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
logPrefix: '[Commit]',
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate commit messages for semantic versioning compliance.
// Use runAgent for commit message generation with filesystem tool
const fsTools = plugins.smartagentTools.filesystemTool({ rootDir: this.projectDir });
APPROVE tool calls for:
- Reading package.json or source files to understand project context
- Using tree to see project structure
- Listing directory contents
const commitSystemPrompt = `
You create commit messages for git commits following semantic versioning conventions.
REJECT tool calls for:
- Reading files outside the project directory
- Writing, deleting, or modifying any files
- Any destructive operations
You have access to filesystem tools to explore the project if needed.
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 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();
IMPORTANT RULES:
- Only READ files (package.json, source files) for context
- Do NOT write, delete, or modify any files
- Version level (fix/feat/BREAKING CHANGE) must match the scope of changes
- Commit message must be clear, professional, and follow conventional commit conventions
- Do NOT include personal information, licensing details, or AI mentions (Claude/Codex)
- JSON structure must be valid with all required fields
- Scope must accurately reflect the changed modules/files
`;
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
You have access to filesystem tools to explore the project if needed:
- Use list_directory to see project structure
- Use read_file 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.
Your final output (inside the task_complete tags) must be ONLY valid JSON - the raw JSON object, nothing else.
Your final response 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().
Here is the structure of the JSON you must return:
@@ -227,15 +200,19 @@ ${processedDiffString}
Analyze these changes and output the JSON commit message object.
`;
const commitResult = await commitOrchestrator.run(commitTaskPrompt);
await commitOrchestrator.stop();
logger.log('info', 'Starting commit message generation with agent...');
if (!commitResult.success) {
throw new Error(`Commit message generation failed: ${commitResult.status}`);
}
const commitResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: commitTaskPrompt,
system: commitSystemPrompt,
tools: fsTools,
maxSteps: 10,
onToolCall: (toolName) => logger.log('info', `[Commit] Tool call: ${toolName}`),
});
// Extract JSON from result - handle cases where AI adds text around it
let jsonString = commitResult.result
let jsonString = commitResult.text
.replace(/```json\n?/gi, '')
.replace(/```\n?/gi, '');
@@ -259,30 +236,16 @@ Analyze these changes and output the JSON commit message object.
const commitMessages = await gitRepo.getAllCommitMessages();
console.log(JSON.stringify(commitMessages, null, 2));
// Use DualAgentOrchestrator for changelog generation with Guardian validation
const changelogOrchestrator = new plugins.smartagent.DualAgentOrchestrator({
smartAiInstance: this.aiDocsRef.smartAiInstance,
defaultProvider: 'openai',
logPrefix: '[Changelog]',
onProgress: (event) => logger.log(event.logLevel, event.logMessage),
guardianPolicyPrompt: `
You validate changelog generation.
const changelogSystemPrompt = `
You generate changelog.md files for software projects.
APPROVE if:
- Changelog follows proper markdown format with ## headers for each version
- Entries are chronologically ordered (newest first)
- Version ranges for trivial commits are properly summarized
RULES:
- Changelog must follow proper markdown format with ## headers for each version
- Entries must be chronologically ordered (newest first)
- Version ranges for trivial commits should be properly summarized
- No duplicate or empty entries
- Format matches: ## yyyy-mm-dd - x.x.x - scope
REJECT with feedback if:
- Markdown formatting is incorrect
- Entries are not meaningful or helpful
- Dates or versions are malformed
`,
});
await changelogOrchestrator.start();
- Format: ## yyyy-mm-dd - x.x.x - scope
`;
const changelogTaskPrompt = `
You are building a changelog.md file for the project.
@@ -291,7 +254,7 @@ Omit commits and versions that lack relevant changes, but make sure to mention t
A changelog entry should look like this:
## yyyy-mm-dd - x.x.x - scope here
main descriptiom here
main description here
- detailed bullet points follow
@@ -305,16 +268,17 @@ Here are the commit messages:
${JSON.stringify(commitMessages, null, 2)}
`;
const changelogResult = await changelogOrchestrator.run(changelogTaskPrompt);
await changelogOrchestrator.stop();
if (!changelogResult.success) {
throw new Error(`Changelog generation failed: ${changelogResult.status}`);
}
const changelogResult = await plugins.smartagent.runAgent({
model: this.aiDocsRef.model,
prompt: changelogTaskPrompt,
system: changelogSystemPrompt,
maxSteps: 1,
onToolCall: (toolName) => logger.log('info', `[Changelog] Tool call: ${toolName}`),
});
previousChangelog = plugins.smartfileFactory.fromString(
previousChangelogPath,
changelogResult.result.replaceAll('```markdown', '').replaceAll('```', ''),
changelogResult.text.replaceAll('```markdown', '').replaceAll('```', ''),
'utf8'
);
}