fix: address CodeRabbit review comments for Kimi CLI support

This commit is contained in:
Yang 2026-03-04 15:41:51 +08:00
parent c797c4e584
commit 304b68130d
2 changed files with 15 additions and 13 deletions

View File

@ -1,4 +1,5 @@
const path = require('node:path'); const path = require('node:path');
const os = require('node:os');
const fs = require('fs-extra'); const fs = require('fs-extra');
const yaml = require('yaml'); const yaml = require('yaml');
const { BaseIdeSetup } = require('./_base-ide'); const { BaseIdeSetup } = require('./_base-ide');
@ -15,7 +16,7 @@ const prompts = require('../../../lib/prompts');
*/ */
class KimiCliSetup extends BaseIdeSetup { class KimiCliSetup extends BaseIdeSetup {
constructor() { constructor() {
super('kimi-cli', 'Kimi Code CLI', true); super('kimi-cli', 'Kimi Code CLI', false);
} }
/** /**
@ -25,6 +26,9 @@ class KimiCliSetup extends BaseIdeSetup {
* @param {Object} options - Setup options * @param {Object} options - Setup options
*/ */
async setup(projectDir, bmadDir, options = {}) { async setup(projectDir, bmadDir, options = {}) {
if (!bmadDir) {
throw new Error('bmadDir is required for Kimi CLI setup');
}
if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`); if (!options.silent) await prompts.log.info(`Setting up ${this.name}...`);
const { artifacts, counts } = await this.collectClaudeArtifacts(projectDir, bmadDir, options); const { artifacts, counts } = await this.collectClaudeArtifacts(projectDir, bmadDir, options);
@ -40,7 +44,7 @@ class KimiCliSetup extends BaseIdeSetup {
const agentCount = await this.writeSkillArtifacts(destDir, agentArtifacts, 'agent-launcher'); const agentCount = await this.writeSkillArtifacts(destDir, agentArtifacts, 'agent-launcher');
// Collect and write task skills // Collect and write task skills
const tasks = await getTasksFromBmad(bmadDir, options.selectedModules || []); const tasks = await getTasksFromBmad(bmadDir);
const taskArtifacts = []; const taskArtifacts = [];
for (const task of tasks) { for (const task of tasks) {
const content = await this.readAndProcessWithProject( const content = await this.readAndProcessWithProject(
@ -104,8 +108,8 @@ class KimiCliSetup extends BaseIdeSetup {
if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) { if (entries && entries.some((entry) => entry && typeof entry === 'string' && entry.startsWith('bmad'))) {
return true; return true;
} }
} catch { } catch (error) {
// Ignore errors if (!options.silent) await prompts.log.debug(`Debug: Could not read directory ${dir}: ${error.message}`);
} }
} }
@ -208,7 +212,6 @@ class KimiCliSetup extends BaseIdeSetup {
const skillContent = this.transformToSkillFormat(artifact.content, skillName); const skillContent = this.transformToSkillFormat(artifact.content, skillName);
// Write SKILL.md with platform-native line endings // Write SKILL.md with platform-native line endings
const os = require('node:os');
const platformContent = skillContent.replaceAll('\n', os.EOL); const platformContent = skillContent.replaceAll('\n', os.EOL);
await fs.writeFile(path.join(skillDir, 'SKILL.md'), platformContent, 'utf8'); await fs.writeFile(path.join(skillDir, 'SKILL.md'), platformContent, 'utf8');
writtenCount++; writtenCount++;
@ -229,7 +232,7 @@ class KimiCliSetup extends BaseIdeSetup {
content = content.replaceAll('\r\n', '\n').replaceAll('\r', '\n'); content = content.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
// Parse frontmatter // Parse frontmatter
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/); const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
if (!fmMatch) { if (!fmMatch) {
// No frontmatter -- wrap with minimal frontmatter // No frontmatter -- wrap with minimal frontmatter
const fm = yaml.stringify({ name: skillName, description: skillName }).trimEnd(); const fm = yaml.stringify({ name: skillName, description: skillName }).trimEnd();
@ -304,7 +307,7 @@ class KimiCliSetup extends BaseIdeSetup {
* @param {string} destDir - Optional destination directory * @param {string} destDir - Optional destination directory
* @returns {string} Instructions text * @returns {string} Instructions text
*/ */
getProjectSpecificInstructions(projectDir = null, destDir = null) { getProjectSpecificInstructions(destDir = null) {
const lines = [ const lines = [
'Project-Specific Kimi CLI Configuration', 'Project-Specific Kimi CLI Configuration',
'', '',
@ -323,10 +326,10 @@ class KimiCliSetup extends BaseIdeSetup {
/** /**
* Cleanup Kimi CLI configuration * Cleanup Kimi CLI configuration
*/ */
async cleanup(projectDir = null) { async cleanup(projectDir = null, options = {}) {
if (projectDir) { if (projectDir) {
const destDir = this.getKimiSkillsDir(projectDir); const destDir = this.getKimiSkillsDir(projectDir);
await this.clearOldBmadSkills(destDir); await this.clearOldBmadSkills(destDir, options);
} }
} }
@ -352,7 +355,7 @@ class KimiCliSetup extends BaseIdeSetup {
`---\n${fm}\n---\n` + `---\n${fm}\n---\n` +
"\nYou must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.\n" + "\nYou must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.\n" +
'\n<agent-activation CRITICAL="TRUE">\n' + '\n<agent-activation CRITICAL="TRUE">\n' +
`1. LOAD the FULL agent file from @${agentPath}\n` + `1. LOAD the FULL agent file from ${agentPath}\n` +
'2. READ its entire contents - this contains the complete agent persona, menu, and instructions\n' + '2. READ its entire contents - this contains the complete agent persona, menu, and instructions\n' +
'3. FOLLOW every step in the <activation> section precisely\n' + '3. FOLLOW every step in the <activation> section precisely\n' +
'4. DISPLAY the welcome/greeting as instructed\n' + '4. DISPLAY the welcome/greeting as instructed\n' +
@ -361,7 +364,6 @@ class KimiCliSetup extends BaseIdeSetup {
'</agent-activation>\n'; '</agent-activation>\n';
// Write with platform-native line endings // Write with platform-native line endings
const os = require('node:os');
const platformContent = skillContent.replaceAll('\n', os.EOL); const platformContent = skillContent.replaceAll('\n', os.EOL);
const skillPath = path.join(skillDir, 'SKILL.md'); const skillPath = path.join(skillDir, 'SKILL.md');
await fs.writeFile(skillPath, platformContent, 'utf8'); await fs.writeFile(skillPath, platformContent, 'utf8');

View File

@ -8,7 +8,7 @@ const prompts = require('../../../lib/prompts');
* Dynamically discovers and loads IDE handlers * Dynamically discovers and loads IDE handlers
* *
* Loading strategy: * Loading strategy:
* 1. Custom installer files (codex.js, github-copilot.js, kilo.js, rovodev.js) - for platforms with unique installation logic * 1. Custom installer files (codex.js, github-copilot.js, kilo.js, rovodev.js, kimi-cli.js) - for platforms with unique installation logic
* 2. Config-driven handlers (from platform-codes.yaml) - for standard IDE installation patterns * 2. Config-driven handlers (from platform-codes.yaml) - for standard IDE installation patterns
*/ */
class IdeManager { class IdeManager {
@ -44,7 +44,7 @@ class IdeManager {
/** /**
* Dynamically load all IDE handlers * Dynamically load all IDE handlers
* 1. Load custom installer files first (codex.js, github-copilot.js, kilo.js, rovodev.js) * 1. Load custom installer files first (codex.js, github-copilot.js, kilo.js, rovodev.js, kimi-cli.js)
* 2. Load config-driven handlers from platform-codes.yaml * 2. Load config-driven handlers from platform-codes.yaml
*/ */
async loadHandlers() { async loadHandlers() {