cw-ai-backlog
Version:
AI-powered tool to generate backlog items from meeting documents and output to Google Sheets
216 lines (183 loc) • 6.84 kB
JavaScript
const fs = require('fs-extra');
const path = require('path');
const os = require('os');
const chalk = require('chalk');
/**
* 顯示配置檔案位置資訊
*/
async function showConfigPaths() {
console.log(chalk.blue('\n📁 配置檔案位置資訊\n'));
const configPaths = [
{
path: './ai_backlog.config.js',
description: '當前目錄配置檔案',
priority: 1
},
{
path: path.join(os.homedir(), '.ai_backlog.config.js'),
description: '全域配置檔案(推薦)',
priority: 2
},
{
path: path.join(os.homedir(), '.config', 'ai-backlog', 'config.js'),
description: 'XDG 標準配置檔案',
priority: 3
}
];
console.log(chalk.yellow('查找順序(優先度由高到低):\n'));
let activeConfigFound = false;
for (const config of configPaths) {
const exists = await fs.pathExists(config.path);
const fullPath = path.resolve(config.path);
if (exists && !activeConfigFound) {
console.log(chalk.green(`✅ ${config.priority}. ${config.description}`));
console.log(chalk.green(` 路徑: ${fullPath}`));
console.log(chalk.green(` 狀態: 目前使用中\n`));
activeConfigFound = true;
} else if (exists) {
console.log(chalk.gray(`📄 ${config.priority}. ${config.description}`));
console.log(chalk.gray(` 路徑: ${fullPath}`));
console.log(chalk.gray(` 狀態: 存在但未使用\n`));
} else {
console.log(chalk.dim(`⭕ ${config.priority}. ${config.description}`));
console.log(chalk.dim(` 路徑: ${fullPath}`));
console.log(chalk.dim(` 狀態: 不存在\n`));
}
}
if (!activeConfigFound) {
console.log(chalk.red('❌ 未找到任何配置檔案'));
console.log(chalk.yellow('💡 執行以下指令建立配置檔案:'));
console.log(chalk.cyan(' ai-backlog example.txt'));
console.log('');
}
console.log(chalk.blue('📝 快速編輯配置檔案:'));
const globalConfigPath = path.join(os.homedir(), '.ai_backlog.config.js');
console.log(chalk.cyan(` nano ${globalConfigPath}`));
console.log(chalk.cyan(` code ${globalConfigPath}`));
console.log('');
}
/**
* 快速編輯全域配置檔案
*/
async function editGlobalConfig() {
const globalConfigPath = path.join(os.homedir(), '.ai_backlog.config.js');
// 如果配置檔案不存在,先建立它
if (!(await fs.pathExists(globalConfigPath))) {
console.log(chalk.yellow('全域配置檔案不存在,正在建立...'));
await createExampleConfig(globalConfigPath);
console.log(chalk.green(`✅ 已建立配置檔案: ${globalConfigPath}`));
}
console.log(chalk.blue('\n📝 開啟配置檔案進行編輯...\n'));
console.log(chalk.cyan(`檔案位置: ${globalConfigPath}`));
// 嘗試使用不同的編輯器開啟
const { spawn } = require('child_process');
// 優先使用 VS Code
try {
const code = spawn('code', [globalConfigPath], {
stdio: 'inherit',
detached: true
});
code.on('error', () => {
// 如果 VS Code 不存在,嘗試使用系統預設編輯器
console.log(chalk.yellow('VS Code 未找到,請手動開啟配置檔案:'));
console.log(chalk.cyan(`nano ${globalConfigPath}`));
console.log(chalk.cyan(`vim ${globalConfigPath}`));
console.log(chalk.cyan(`open ${globalConfigPath}`));
});
code.unref();
console.log(chalk.green('✅ 配置檔案已在 VS Code 中開啟'));
} catch (error) {
console.log(chalk.yellow('請手動開啟配置檔案:'));
console.log(chalk.cyan(`nano ${globalConfigPath}`));
console.log(chalk.cyan(`vim ${globalConfigPath}`));
console.log(chalk.cyan(`open ${globalConfigPath}`));
}
}
/**
* 載入配置檔案
* @param {string} configPath 配置檔案路徑
* @returns {Object} 配置物件
*/
async function loadConfig(configPath) {
const defaultConfig = {
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-4.1-nano',
keepPhrases: [],
customPrompt: [],
googleCredentials: null,
googleSheetUrl: null,
maxTokens: 4000,
temperature: 0.1
};
try {
// 如果指定了明確的配置路徑,直接使用
if (configPath !== './ai_backlog.config.js') {
if (await fs.pathExists(configPath)) {
const userConfig = require(path.resolve(configPath));
return { ...defaultConfig, ...userConfig };
} else {
throw new Error(`指定的配置檔案不存在: ${configPath}`);
}
}
// 按優先順序查找配置檔案
const configPaths = [
'./ai_backlog.config.js', // 當前目錄
path.join(os.homedir(), '.ai_backlog.config.js'), // 使用者家目錄
path.join(os.homedir(), '.config', 'ai-backlog', 'config.js') // XDG 標準目錄
];
for (const configFile of configPaths) {
if (await fs.pathExists(configFile)) {
const userConfig = require(path.resolve(configFile));
// 不在這裡 console.log,讓 CLI 處理 spinner
return { ...defaultConfig, ...userConfig };
}
}
// 如果沒有找到配置檔案,提示使用者執行互動式設定
console.log(chalk.yellow('\n⚠️ 未找到配置檔案'));
console.log(chalk.blue('💡 建議執行互動式設定來建立配置檔案:'));
console.log(chalk.cyan(' ai-backlog --setup'));
console.log('');
throw new Error('請先執行 ai-backlog --setup 來建立配置檔案');
} catch (error) {
throw error;
}
}
/**
* 創建範例配置檔案
* @param {string} configPath 配置檔案路徑
*/
async function createExampleConfig(configPath) {
const exampleConfig = `module.exports = {
// OpenAI API Key (必填)
apiKey: process.env.OPENAI_API_KEY || '你的-openai-api-key',
// 使用的模型
model: 'gpt-4.1-nano', // 或 'gpt-4-turbo', 'gpt-3.5-turbo'
// 保留字 - 在分析時需要特別注意的詞彙
keepPhrases: [
'使用者體驗',
'效能優化',
'安全性',
// 新增更多保留字...
],
// 自訂 prompt 指示 - 會加入到 AI 分析指令中
customPrompt: [
// '只分析紫色標記的內容',
// '專注於特定標題以下的內容',
// '忽略草稿或註解部分',
// 新增您的自訂指示...
],
// Google Docs API 憑證檔案路徑 (可選)
googleCredentials: null, // './path/to/credentials.json'
// Google Sheets URL (必填 - 用於輸出 backlog)
googleSheetUrl: null, // 'https://docs.google.com/spreadsheets/d/your-sheet-id/edit'
// AI 參數設定
maxTokens: 4000,
temperature: 0.1
};`;
await fs.writeFile(configPath, exampleConfig);
}
module.exports = {
loadConfig,
showConfigPaths,
editGlobalConfig
};