prime-dev-cli 1.0.19 → 1.0.21

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.
Files changed (110) hide show
  1. package/dist/server/.next/BUILD_ID +1 -1
  2. package/dist/server/.next/app-build-manifest.json +1 -1
  3. package/dist/server/.next/app-path-routes-manifest.json +2 -0
  4. package/dist/server/.next/build-manifest.json +6 -6
  5. package/dist/server/.next/cache/.rscinfo +1 -1
  6. package/dist/server/.next/cache/.tsbuildinfo +1 -1
  7. package/dist/server/.next/cache/eslint/.cache_1qa5vxt +1 -1
  8. package/dist/server/.next/fallback-build-manifest.json +6 -6
  9. package/dist/server/.next/next-minimal-server.js.nft.json +1 -1
  10. package/dist/server/.next/next-server.js.nft.json +1 -1
  11. package/dist/server/.next/prerender-manifest.json +9 -9
  12. package/dist/server/.next/server/app/_not-found.html +1 -1
  13. package/dist/server/.next/server/app/_not-found.rsc +1 -1
  14. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route/app-build-manifest.json +10 -0
  15. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route/app-paths-manifest.json +3 -0
  16. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route/build-manifest.json +16 -0
  17. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route/next-font-manifest.json +6 -0
  18. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route/react-loadable-manifest.json +1 -0
  19. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route/server-reference-manifest.json +4 -0
  20. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js +8 -0
  21. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js.map +5 -0
  22. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js.nft.json +1 -0
  23. package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route_client-reference-manifest.js +2 -0
  24. package/dist/server/.next/server/app/api/admin-git-batch-merge/route/app-build-manifest.json +10 -0
  25. package/dist/server/.next/server/app/api/admin-git-batch-merge/route/app-paths-manifest.json +3 -0
  26. package/dist/server/.next/server/app/api/admin-git-batch-merge/route/build-manifest.json +16 -0
  27. package/dist/server/.next/server/app/api/admin-git-batch-merge/route/next-font-manifest.json +6 -0
  28. package/dist/server/.next/server/app/api/admin-git-batch-merge/route/react-loadable-manifest.json +1 -0
  29. package/dist/server/.next/server/app/api/admin-git-batch-merge/route/server-reference-manifest.json +4 -0
  30. package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js +8 -0
  31. package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js.map +5 -0
  32. package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js.nft.json +1 -0
  33. package/dist/server/.next/server/app/api/admin-git-batch-merge/route_client-reference-manifest.js +2 -0
  34. package/dist/server/.next/server/app/api/uat-git-flow/route.js +2 -2
  35. package/dist/server/.next/server/app/api/uat-git-flow/route.js.nft.json +1 -1
  36. package/dist/server/.next/server/app/api/uat-git-flow/step/route.js +2 -2
  37. package/dist/server/.next/server/app/api/uat-git-flow/step/route.js.nft.json +1 -1
  38. package/dist/server/.next/server/app/configuration.html +1 -1
  39. package/dist/server/.next/server/app/configuration.rsc +1 -1
  40. package/dist/server/.next/server/app/index.html +1 -1
  41. package/dist/server/.next/server/app/index.rsc +1 -1
  42. package/dist/server/.next/server/app/initialization/page/app-build-manifest.json +1 -1
  43. package/dist/server/.next/server/app/initialization/page_client-reference-manifest.js +1 -1
  44. package/dist/server/.next/server/app/initialization.html +1 -1
  45. package/dist/server/.next/server/app/initialization.rsc +2 -2
  46. package/dist/server/.next/server/app-paths-manifest.json +2 -0
  47. package/dist/server/.next/server/chunks/[root-of-the-server]__0879b2d6._.js.map +1 -1
  48. package/dist/server/.next/server/chunks/[root-of-the-server]__0d56f35b._.js.map +1 -1
  49. package/dist/server/.next/server/chunks/[root-of-the-server]__0e8a08fc._.js.map +1 -1
  50. package/dist/server/.next/server/chunks/[root-of-the-server]__1e792460._.js.map +1 -1
  51. package/dist/server/.next/server/chunks/[root-of-the-server]__2a29597f._.js.map +1 -1
  52. package/dist/server/.next/server/chunks/[root-of-the-server]__2a78acef._.js.map +1 -1
  53. package/dist/server/.next/server/chunks/[root-of-the-server]__2f8b52da._.js.map +1 -1
  54. package/dist/server/.next/server/chunks/[root-of-the-server]__2ffbf0d3._.js.map +1 -1
  55. package/dist/server/.next/server/chunks/[root-of-the-server]__452b5f9c._.js +13 -13
  56. package/dist/server/.next/server/chunks/[root-of-the-server]__452b5f9c._.js.map +1 -1
  57. package/dist/server/.next/server/chunks/[root-of-the-server]__4ec3205b._.js.map +1 -1
  58. package/dist/server/.next/server/chunks/[root-of-the-server]__4fd52ac1._.js +13 -13
  59. package/dist/server/.next/server/chunks/[root-of-the-server]__4fd52ac1._.js.map +1 -1
  60. package/dist/server/.next/server/chunks/[root-of-the-server]__5c9f62f9._.js.map +1 -1
  61. package/dist/server/.next/server/chunks/[root-of-the-server]__8637b7f1._.js.map +1 -1
  62. package/dist/server/.next/server/chunks/[root-of-the-server]__8a8561ea._.js +16 -0
  63. package/dist/server/.next/server/chunks/[root-of-the-server]__8a8561ea._.js.map +1 -0
  64. package/dist/server/.next/server/chunks/{[root-of-the-server]__4ab3dd83._.js → [root-of-the-server]__978c4dda._.js} +14 -14
  65. package/dist/server/.next/server/chunks/[root-of-the-server]__978c4dda._.js.map +1 -0
  66. package/dist/server/.next/server/chunks/[root-of-the-server]__a6fbefc6._.js.map +1 -1
  67. package/dist/server/.next/server/chunks/[root-of-the-server]__a74239fc._.js.map +1 -1
  68. package/dist/server/.next/server/chunks/[root-of-the-server]__aaa3fe74._.js.map +1 -1
  69. package/dist/server/.next/server/chunks/[root-of-the-server]__b176e8df._.js +14 -14
  70. package/dist/server/.next/server/chunks/[root-of-the-server]__b176e8df._.js.map +1 -1
  71. package/dist/server/.next/server/chunks/{[root-of-the-server]__6cbd50e9._.js → [root-of-the-server]__bc84f5d7._.js} +14 -14
  72. package/dist/server/.next/server/chunks/[root-of-the-server]__bc84f5d7._.js.map +1 -0
  73. package/dist/server/.next/server/chunks/[root-of-the-server]__c18498ef._.js.map +1 -1
  74. package/dist/server/.next/server/chunks/[root-of-the-server]__dda45cac._.js.map +1 -1
  75. package/dist/server/.next/server/chunks/[root-of-the-server]__de18efbd._.js +13 -13
  76. package/dist/server/.next/server/chunks/[root-of-the-server]__de18efbd._.js.map +1 -1
  77. package/dist/server/.next/server/chunks/[root-of-the-server]__e0b7050d._.js.map +1 -1
  78. package/dist/server/.next/server/chunks/[root-of-the-server]__ec681197._.js.map +1 -1
  79. package/dist/server/.next/server/chunks/[root-of-the-server]__f111df8e._.js +16 -0
  80. package/dist/server/.next/server/chunks/[root-of-the-server]__f111df8e._.js.map +1 -0
  81. package/dist/server/.next/server/chunks/_24087f66._.js +1 -1
  82. package/dist/server/.next/server/chunks/_24087f66._.js.map +1 -1
  83. package/dist/server/.next/server/chunks/_61c263b3._.js +1 -1
  84. package/dist/server/.next/server/chunks/_61c263b3._.js.map +1 -1
  85. package/dist/server/.next/server/chunks/ssr/packages_server_src_7cef6dbd._.js +1 -1
  86. package/dist/server/.next/server/chunks/ssr/packages_server_src_7cef6dbd._.js.map +1 -1
  87. package/dist/server/.next/server/middleware-build-manifest.js +4 -4
  88. package/dist/server/.next/server/pages/404.html +1 -1
  89. package/dist/server/.next/server/pages/500.html +1 -1
  90. package/dist/server/.next/server/pages/_app/build-manifest.json +2 -2
  91. package/dist/server/.next/server/pages/_error/build-manifest.json +2 -2
  92. package/dist/server/.next/server/server-reference-manifest.js +1 -1
  93. package/dist/server/.next/server/server-reference-manifest.json +1 -1
  94. package/dist/server/.next/static/chunks/{2602bf706e977560.js.map → 263bfd9c535a6eda.js.map} +1 -1
  95. package/dist/server/.next/static/chunks/{1091ba2f3c451a47.js → 2693a47bbc4fc75c.js} +1 -1
  96. package/dist/server/.next/static/chunks/{1aa036ed62a506c8.js → 352f266165580042.js} +2 -2
  97. package/dist/server/.next/static/chunks/67cde2756fdf3a91.js +3 -0
  98. package/dist/server/.next/static/chunks/{1154a499e8e3867b.js → ac48e758a0b74c2b.js} +1 -1
  99. package/dist/server/.next/static/chunks/c198f02ea70fda25.js.map +1 -0
  100. package/dist/server/.next/static/chunks/pages/_app.js +2 -2
  101. package/dist/server/.next/static/chunks/pages/_error.js +2 -2
  102. package/dist/server/.next/trace +1 -1
  103. package/package.json +1 -1
  104. package/dist/server/.next/server/chunks/[root-of-the-server]__4ab3dd83._.js.map +0 -1
  105. package/dist/server/.next/server/chunks/[root-of-the-server]__6cbd50e9._.js.map +0 -1
  106. package/dist/server/.next/static/chunks/99154153690ad580.js.map +0 -1
  107. package/dist/server/.next/static/chunks/9bc1bbb3fe6e5eb3.js +0 -3
  108. /package/dist/server/.next/static/{tz_bf3MbzRijrx8XdXPWA → TxLJ_6S5QAvwM1pkwjUrZ}/_buildManifest.js +0 -0
  109. /package/dist/server/.next/static/{tz_bf3MbzRijrx8XdXPWA → TxLJ_6S5QAvwM1pkwjUrZ}/_clientMiddlewareManifest.json +0 -0
  110. /package/dist/server/.next/static/{tz_bf3MbzRijrx8XdXPWA → TxLJ_6S5QAvwM1pkwjUrZ}/_ssgManifest.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/git-operations.ts","turbopack:///[project]/packages/server/src/app/api/uat-git-flow/state.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}","import { spawn, ChildProcess } from 'child_process';\nimport { existsSync, mkdirSync } from 'fs';\nimport { promises as fs } from 'fs';\nimport { join, basename } from 'path';\nimport {\n ProjectStatus,\n type GitOperationConfig,\n type ProjectProgress,\n} from './workspace-types';\n\n/**\n * 创建工作空间目录\n * @param workspacePath 工作空间路径\n * @returns 创建结果\n */\nexport async function createWorkspaceDirectory(workspacePath: string): Promise<{ success: boolean; error?: string }> {\n try {\n if (!existsSync(workspacePath)) {\n mkdirSync(workspacePath, { recursive: true });\n }\n return { success: true };\n } catch (error) {\n return { \n success: false, \n error: `创建工作空间目录失败: ${error instanceof Error ? error.message : String(error)}` \n };\n }\n}\n\n/**\n * 执行 Git 克隆操作\n * @param config Git 操作配置\n * @returns Promise<ProjectProgress>\n */\nexport async function cloneRepository(config: GitOperationConfig): Promise<ProjectProgress> {\n const { repoUrl, targetDir, timeout, onProgress, onError, onLog } = config;\n const projectName = basename(repoUrl, '.git');\n \n return new Promise<ProjectProgress>((resolve) => {\n const startTime = Date.now();\n \n // 更新开始状态\n const initialProgress: ProjectProgress = {\n projectName,\n status: ProjectStatus.CLONING,\n progress: 0,\n message: '开始克隆项目...',\n startTime,\n };\n onProgress?.(0, '开始克隆项目...');\n\n // 执行 git clone 命令\n const targetPath = join(targetDir, projectName);\n // 添加 --progress 参数来强制显示进度,--verbose 显示详细信息\n const gitArgs = ['clone', '--progress', '--verbose', repoUrl, targetPath];\n \n // 记录命令启动信息\n onLog?.(projectName, 'stdout', `[开始克隆] 执行命令: git ${gitArgs.join(' ')}\\n`);\n onLog?.(projectName, 'stdout', `[目标目录] ${targetPath}\\n`);\n onLog?.(projectName, 'stdout', `[仓库地址] ${repoUrl}\\n`);\n \n const gitProcess: ChildProcess = spawn('git', gitArgs, {\n cwd: targetDir,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let errorOutput = '';\n let progressValue = 0;\n \n // 记录进程启动成功\n onLog?.(projectName, 'stdout', `[进程启动] Git 进程 PID: ${gitProcess.pid}\\n`);\n\n // 设置超时\n const timeoutId = setTimeout(() => {\n onLog?.(projectName, 'stderr', `[超时警告] Git 进程运行超过 ${timeout / 1000}s,即将终止\\n`);\n gitProcess.kill('SIGTERM');\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆操作超时',\n error: `克隆操作超时 (${timeout / 1000}s)`,\n endTime: Date.now(),\n };\n onLog?.(projectName, 'stderr', `[进程终止] 克隆操作超时\\n`);\n onError?.(`${projectName}: 克隆操作超时`);\n resolve(errorResult);\n }, timeout);\n\n // 处理标准输出\n gitProcess.stdout?.on('data', (data: Buffer) => {\n const stdoutText = data.toString();\n \n // 实时发送日志\n onLog?.(projectName, 'stdout', stdoutText);\n \n // 模拟进度更新(Git 克隆没有内置进度,这里基于时间估算)\n progressValue = Math.min(progressValue + 10, 80);\n onProgress?.(progressValue, '正在克隆代码...');\n });\n\n // 处理错误输出\n gitProcess.stderr?.on('data', (data: Buffer) => {\n const stderrText = data.toString();\n errorOutput += stderrText;\n \n // 判断是进度信息还是错误信息\n const isProgressInfo = stderrText.includes('remote:') || \n stderrText.includes('Receiving objects') || \n stderrText.includes('Resolving deltas') ||\n stderrText.includes('Counting objects') ||\n stderrText.includes('Enumerating objects') ||\n stderrText.includes('Compressing objects') ||\n stderrText.includes('upload-pack') ||\n stderrText.includes('POST git-') ||\n stderrText.includes('正克隆到') ||\n stderrText.includes('Cloning into');\n \n // 根据内容类型发送不同的日志\n if (isProgressInfo) {\n onLog?.(projectName, 'progress', stderrText);\n } else {\n onLog?.(projectName, 'stderr', stderrText);\n }\n \n // Git 的进度信息通常在 stderr 中\n if (stderrText.includes('Receiving objects') || stderrText.includes('Resolving deltas')) {\n progressValue = Math.min(progressValue + 5, 90);\n onProgress?.(progressValue, '正在接收对象...');\n } else if (stderrText.includes('Counting objects')) {\n progressValue = Math.min(progressValue + 2, 70);\n onProgress?.(progressValue, '正在计算对象...');\n } else if (stderrText.includes('Enumerating objects')) {\n progressValue = Math.min(progressValue + 2, 50);\n onProgress?.(progressValue, '正在枚举对象...');\n }\n });\n\n // 处理进程结束\n gitProcess.on('close', (code: number | null) => {\n clearTimeout(timeoutId);\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n onLog?.(projectName, 'stdout', `[进程结束] Git 进程退出,代码: ${code},耗时: ${Math.round(duration / 1000)}s\\n`);\n \n if (code === 0) {\n // 克隆成功\n onLog?.(projectName, 'stdout', `[克隆成功] 项目已成功克隆到: ${targetPath}\\n`);\n const successResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.SUCCESS,\n progress: 100,\n message: '克隆完成',\n endTime,\n };\n onProgress?.(100, '克隆完成');\n resolve(successResult);\n } else {\n // 克隆失败\n const parsedError = parseGitError(errorOutput);\n onLog?.(projectName, 'stderr', `[克隆失败] 错误信息: ${parsedError}\\n`);\n onLog?.(projectName, 'stderr', `[完整错误输出]\\n${errorOutput}\\n`);\n \n const failureResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆失败',\n error: parsedError || `Git 进程退出,代码: ${code}`,\n endTime,\n };\n onError?.(`${projectName}: ${failureResult.error}`);\n resolve(failureResult);\n }\n });\n\n // 处理进程错误\n gitProcess.on('error', (error: Error) => {\n clearTimeout(timeoutId);\n onLog?.(projectName, 'stderr', `[进程错误] Git 进程启动失败: ${error.message}\\n`);\n onLog?.(projectName, 'stderr', `[错误详情] ${error.stack || 'No stack trace'}\\n`);\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '进程启动失败',\n error: `进程启动失败: ${error.message}`,\n endTime: Date.now(),\n };\n onError?.(`${projectName}: ${error.message}`);\n resolve(errorResult);\n });\n });\n}\n\n/**\n * 解析 Git 错误信息,提供用户友好的错误描述\n * @param errorOutput Git stderr 输出\n * @returns 用户友好的错误描述\n */\nfunction parseGitError(errorOutput: string): string {\n const lowerOutput = errorOutput.toLowerCase();\n \n if (lowerOutput.includes('authentication failed') || lowerOutput.includes('access denied')) {\n return '身份验证失败,请检查仓库访问权限';\n }\n \n if (lowerOutput.includes('repository not found') || lowerOutput.includes('not found')) {\n return '仓库不存在或无法访问';\n }\n \n if (lowerOutput.includes('network') || lowerOutput.includes('connection')) {\n return '网络连接问题,请检查网络设置';\n }\n \n if (lowerOutput.includes('timeout')) {\n return '网络超时,请重试';\n }\n \n if (lowerOutput.includes('permission denied')) {\n return '权限被拒绝,请检查文件系统权限';\n }\n \n if (lowerOutput.includes('already exists')) {\n return '目标目录已存在';\n }\n \n // 返回原始错误的前200个字符\n return errorOutput.slice(0, 200) + (errorOutput.length > 200 ? '...' : '');\n}\n\n/**\n * 验证 Git 仓库 URL 格式\n * @param url Git 仓库 URL\n * @returns 是否有效\n */\nexport function isValidGitUrl(url: string): boolean {\n const gitUrlPattern = /^(https?:\\/\\/|git@)[^\\s]+\\.git$/i;\n return gitUrlPattern.test(url);\n}\n\n/**\n * 清理项目名称,移除不安全字符\n * @param projectName 项目名称\n * @returns 清理后的项目名称\n */\nexport function sanitizeProjectName(projectName: string): string {\n return projectName.replace(/[^a-zA-Z0-9\\-_]/g, '');\n}\n\n/**\n * 项目检查结果类型\n */\nexport type ProjectCheckResult = {\n exists: boolean;\n status: 'not_exists' | 'complete' | 'incomplete';\n needsCleanup: boolean;\n};\n\n/**\n * 检查项目状态(详细版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<ProjectCheckResult> 详细的项目状态\n */\nexport async function checkProjectStatus(workspacePath: string, projectName: string): Promise<ProjectCheckResult> {\n try {\n const projectPath = join(workspacePath, projectName);\n \n // 检查项目目录是否存在\n if (!existsSync(projectPath)) {\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n \n // 检查是否为 Git 仓库(存在 .git 目录)\n const gitPath = join(projectPath, '.git');\n if (!existsSync(gitPath)) {\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n // 更严格的完整性检查\n const isComplete = await isGitRepositoryComplete(projectPath);\n if (!isComplete) {\n console.log(`检测到不完整的Git仓库: ${projectPath}`);\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n return {\n exists: true,\n status: 'complete',\n needsCleanup: false\n };\n } catch (error) {\n console.error(`检查项目 ${projectName} 状态时出错:`, error);\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n}\n\n/**\n * 检查项目是否已存在于工作空间中(兼容版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<boolean> 项目是否存在且为有效的 Git 仓库\n */\nexport async function checkProjectExists(workspacePath: string, projectName: string): Promise<boolean> {\n const result = await checkProjectStatus(workspacePath, projectName);\n return result.status === 'complete';\n}\n\n/**\n * 检查Git仓库是否完整\n * @param projectPath 项目路径\n * @returns Promise<boolean> 仓库是否完整\n */\nasync function isGitRepositoryComplete(projectPath: string): Promise<boolean> {\n try {\n const gitPath = join(projectPath, '.git');\n \n // 检查关键的Git文件是否存在\n const requiredFiles = ['HEAD', 'config', 'refs'];\n for (const file of requiredFiles) {\n const filePath = join(gitPath, file);\n if (!existsSync(filePath)) {\n return false;\n }\n }\n \n // 检查是否有实际的项目文件(不只是.git目录)\n const entries = await fs.readdir(projectPath);\n const nonGitFiles = entries.filter((entry: string) => entry !== '.git');\n \n // 如果只有.git目录,说明克隆未完成\n if (nonGitFiles.length === 0) {\n return false;\n }\n \n // 检查HEAD文件是否有效\n const headPath = join(gitPath, 'HEAD');\n const headContent = await fs.readFile(headPath, 'utf-8');\n if (!headContent.trim() || headContent.includes('unborn')) {\n return false;\n }\n \n return true;\n } catch (error) {\n console.error('检查Git仓库完整性时出错:', error);\n return false;\n }\n}\n\n/**\n * 清理不完整的项目目录\n * @param projectPath 项目路径\n */\nexport async function cleanupIncompleteProject(projectPath: string): Promise<void> {\n try {\n console.log(`正在清理不完整的项目: ${projectPath}`);\n await fs.rm(projectPath, { recursive: true, force: true });\n console.log(`清理完成: ${projectPath}`);\n } catch (error) {\n console.error(`清理项目失败 ${projectPath}:`, error);\n // 清理失败不抛出错误,避免阻塞后续流程\n }\n}\n\n/**\n * 批量检查多个项目的存在状态\n * @param workspacePath 工作空间路径\n * @param projectNames 项目名称列表\n * @returns Promise<Record<string, boolean>> 项目名称到存在状态的映射\n */\nexport async function checkMultipleProjectsExist(\n workspacePath: string, \n projectNames: string[]\n): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n \n // 并行检查所有项目\n const checks = projectNames.map(async (projectName) => {\n const exists = await checkProjectExists(workspacePath, projectName);\n results[projectName] = exists;\n });\n \n await Promise.all(checks);\n return results;\n} ","type AbortState = {\n aborted: boolean;\n updatedAt: number;\n};\n\nconst abortStates = new Map<string, AbortState>();\nconst ABORT_STATE_TTL = 1000 * 60 * 30;\n\nfunction cleanupAbortStates() {\n const now = Date.now();\n for (const [runId, state] of abortStates.entries()) {\n if (now - state.updatedAt > ABORT_STATE_TTL) {\n abortStates.delete(runId);\n }\n }\n}\n\nexport function createUatGitFlowState(runId: string) {\n cleanupAbortStates();\n abortStates.set(runId, { aborted: false, updatedAt: Date.now() });\n}\n\nexport function markUatGitFlowAbort(runId: string) {\n const existing = abortStates.get(runId);\n abortStates.set(runId, {\n aborted: true,\n updatedAt: Date.now(),\n });\n if (!existing) {\n cleanupAbortStates();\n }\n}\n\nexport function isUatGitFlowAborted(runId: string) {\n cleanupAbortStates();\n return abortStates.get(runId)?.aborted ?? false;\n}\n\nexport function clearUatGitFlowState(runId: string) {\n abortStates.delete(runId);\n}\n"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/lib/workspace-config.ts","turbopack:///[project]/packages/server/src/lib/git-operations.ts","turbopack:///[project]/packages/server/src/app/api/uat-git-flow/state.ts"],"sourcesContent":["import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","import { readFile, writeFile, access, constants, rename } from 'fs/promises';\nimport type { ProjectsConfig } from './workspace-types';\nimport { PROJECT_CONFIG_PATH } from './workspace-types';\n\n/**\n * 读取并解析项目配置文件\n * @returns {Promise<ProjectsConfig>} 项目配置对象\n */\nexport async function getProjectsConfig(): Promise<ProjectsConfig> {\n try {\n await access(PROJECT_CONFIG_PATH, constants.F_OK);\n } catch {\n // 文件不存在,创建并写入空对象\n await saveProjectsConfig({});\n return {};\n }\n\n try {\n const configContent = await readFile(PROJECT_CONFIG_PATH, 'utf-8');\n // 如果文件为空,返回空对象\n if (!configContent) {\n return {};\n }\n return JSON.parse(configContent);\n } catch (error) {\n console.error('读取或解析项目配置文件失败:', error);\n // 在出错时返回空对象或抛出错误,这里选择抛出以通知调用者\n throw new Error('无法加载项目配置');\n }\n}\n\n/**\n * 将项目配置写入文件(原子操作)\n * @param {ProjectsConfig} config - 要保存的配置对象\n */\nexport async function saveProjectsConfig(config: ProjectsConfig): Promise<void> {\n const tempConfigPath = PROJECT_CONFIG_PATH + '.tmp';\n try {\n await writeFile(tempConfigPath, JSON.stringify(config, null, 2), 'utf-8');\n await rename(tempConfigPath, PROJECT_CONFIG_PATH);\n } catch (error) {\n console.error('保存项目配置文件失败:', error);\n throw new Error('无法保存项目配置');\n }\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n}","import { spawn, ChildProcess } from 'child_process';\nimport { existsSync, mkdirSync } from 'fs';\nimport { promises as fs } from 'fs';\nimport { join, basename } from 'path';\nimport {\n ProjectStatus,\n type GitOperationConfig,\n type ProjectProgress,\n} from './workspace-types';\n\n/**\n * 创建工作空间目录\n * @param workspacePath 工作空间路径\n * @returns 创建结果\n */\nexport async function createWorkspaceDirectory(workspacePath: string): Promise<{ success: boolean; error?: string }> {\n try {\n if (!existsSync(workspacePath)) {\n mkdirSync(workspacePath, { recursive: true });\n }\n return { success: true };\n } catch (error) {\n return { \n success: false, \n error: `创建工作空间目录失败: ${error instanceof Error ? error.message : String(error)}` \n };\n }\n}\n\n/**\n * 执行 Git 克隆操作\n * @param config Git 操作配置\n * @returns Promise<ProjectProgress>\n */\nexport async function cloneRepository(config: GitOperationConfig): Promise<ProjectProgress> {\n const { repoUrl, targetDir, timeout, onProgress, onError, onLog } = config;\n const projectName = basename(repoUrl, '.git');\n \n return new Promise<ProjectProgress>((resolve) => {\n const startTime = Date.now();\n \n // 更新开始状态\n const initialProgress: ProjectProgress = {\n projectName,\n status: ProjectStatus.CLONING,\n progress: 0,\n message: '开始克隆项目...',\n startTime,\n };\n onProgress?.(0, '开始克隆项目...');\n\n // 执行 git clone 命令\n const targetPath = join(targetDir, projectName);\n // 添加 --progress 参数来强制显示进度,--verbose 显示详细信息\n const gitArgs = ['clone', '--progress', '--verbose', repoUrl, targetPath];\n \n // 记录命令启动信息\n onLog?.(projectName, 'stdout', `[开始克隆] 执行命令: git ${gitArgs.join(' ')}\\n`);\n onLog?.(projectName, 'stdout', `[目标目录] ${targetPath}\\n`);\n onLog?.(projectName, 'stdout', `[仓库地址] ${repoUrl}\\n`);\n \n const gitProcess: ChildProcess = spawn('git', gitArgs, {\n cwd: targetDir,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let errorOutput = '';\n let progressValue = 0;\n \n // 记录进程启动成功\n onLog?.(projectName, 'stdout', `[进程启动] Git 进程 PID: ${gitProcess.pid}\\n`);\n\n // 设置超时\n const timeoutId = setTimeout(() => {\n onLog?.(projectName, 'stderr', `[超时警告] Git 进程运行超过 ${timeout / 1000}s,即将终止\\n`);\n gitProcess.kill('SIGTERM');\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆操作超时',\n error: `克隆操作超时 (${timeout / 1000}s)`,\n endTime: Date.now(),\n };\n onLog?.(projectName, 'stderr', `[进程终止] 克隆操作超时\\n`);\n onError?.(`${projectName}: 克隆操作超时`);\n resolve(errorResult);\n }, timeout);\n\n // 处理标准输出\n gitProcess.stdout?.on('data', (data: Buffer) => {\n const stdoutText = data.toString();\n \n // 实时发送日志\n onLog?.(projectName, 'stdout', stdoutText);\n \n // 模拟进度更新(Git 克隆没有内置进度,这里基于时间估算)\n progressValue = Math.min(progressValue + 10, 80);\n onProgress?.(progressValue, '正在克隆代码...');\n });\n\n // 处理错误输出\n gitProcess.stderr?.on('data', (data: Buffer) => {\n const stderrText = data.toString();\n errorOutput += stderrText;\n \n // 判断是进度信息还是错误信息\n const isProgressInfo = stderrText.includes('remote:') || \n stderrText.includes('Receiving objects') || \n stderrText.includes('Resolving deltas') ||\n stderrText.includes('Counting objects') ||\n stderrText.includes('Enumerating objects') ||\n stderrText.includes('Compressing objects') ||\n stderrText.includes('upload-pack') ||\n stderrText.includes('POST git-') ||\n stderrText.includes('正克隆到') ||\n stderrText.includes('Cloning into');\n \n // 根据内容类型发送不同的日志\n if (isProgressInfo) {\n onLog?.(projectName, 'progress', stderrText);\n } else {\n onLog?.(projectName, 'stderr', stderrText);\n }\n \n // Git 的进度信息通常在 stderr 中\n if (stderrText.includes('Receiving objects') || stderrText.includes('Resolving deltas')) {\n progressValue = Math.min(progressValue + 5, 90);\n onProgress?.(progressValue, '正在接收对象...');\n } else if (stderrText.includes('Counting objects')) {\n progressValue = Math.min(progressValue + 2, 70);\n onProgress?.(progressValue, '正在计算对象...');\n } else if (stderrText.includes('Enumerating objects')) {\n progressValue = Math.min(progressValue + 2, 50);\n onProgress?.(progressValue, '正在枚举对象...');\n }\n });\n\n // 处理进程结束\n gitProcess.on('close', (code: number | null) => {\n clearTimeout(timeoutId);\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n onLog?.(projectName, 'stdout', `[进程结束] Git 进程退出,代码: ${code},耗时: ${Math.round(duration / 1000)}s\\n`);\n \n if (code === 0) {\n // 克隆成功\n onLog?.(projectName, 'stdout', `[克隆成功] 项目已成功克隆到: ${targetPath}\\n`);\n const successResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.SUCCESS,\n progress: 100,\n message: '克隆完成',\n endTime,\n };\n onProgress?.(100, '克隆完成');\n resolve(successResult);\n } else {\n // 克隆失败\n const parsedError = parseGitError(errorOutput);\n onLog?.(projectName, 'stderr', `[克隆失败] 错误信息: ${parsedError}\\n`);\n onLog?.(projectName, 'stderr', `[完整错误输出]\\n${errorOutput}\\n`);\n \n const failureResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '克隆失败',\n error: parsedError || `Git 进程退出,代码: ${code}`,\n endTime,\n };\n onError?.(`${projectName}: ${failureResult.error}`);\n resolve(failureResult);\n }\n });\n\n // 处理进程错误\n gitProcess.on('error', (error: Error) => {\n clearTimeout(timeoutId);\n onLog?.(projectName, 'stderr', `[进程错误] Git 进程启动失败: ${error.message}\\n`);\n onLog?.(projectName, 'stderr', `[错误详情] ${error.stack || 'No stack trace'}\\n`);\n \n const errorResult: ProjectProgress = {\n ...initialProgress,\n status: ProjectStatus.FAILED,\n progress: progressValue,\n message: '进程启动失败',\n error: `进程启动失败: ${error.message}`,\n endTime: Date.now(),\n };\n onError?.(`${projectName}: ${error.message}`);\n resolve(errorResult);\n });\n });\n}\n\n/**\n * 解析 Git 错误信息,提供用户友好的错误描述\n * @param errorOutput Git stderr 输出\n * @returns 用户友好的错误描述\n */\nfunction parseGitError(errorOutput: string): string {\n const lowerOutput = errorOutput.toLowerCase();\n \n if (lowerOutput.includes('authentication failed') || lowerOutput.includes('access denied')) {\n return '身份验证失败,请检查仓库访问权限';\n }\n \n if (lowerOutput.includes('repository not found') || lowerOutput.includes('not found')) {\n return '仓库不存在或无法访问';\n }\n \n if (lowerOutput.includes('network') || lowerOutput.includes('connection')) {\n return '网络连接问题,请检查网络设置';\n }\n \n if (lowerOutput.includes('timeout')) {\n return '网络超时,请重试';\n }\n \n if (lowerOutput.includes('permission denied')) {\n return '权限被拒绝,请检查文件系统权限';\n }\n \n if (lowerOutput.includes('already exists')) {\n return '目标目录已存在';\n }\n \n // 返回原始错误的前200个字符\n return errorOutput.slice(0, 200) + (errorOutput.length > 200 ? '...' : '');\n}\n\n/**\n * 验证 Git 仓库 URL 格式\n * @param url Git 仓库 URL\n * @returns 是否有效\n */\nexport function isValidGitUrl(url: string): boolean {\n const gitUrlPattern = /^(https?:\\/\\/|git@)[^\\s]+\\.git$/i;\n return gitUrlPattern.test(url);\n}\n\n/**\n * 清理项目名称,移除不安全字符\n * @param projectName 项目名称\n * @returns 清理后的项目名称\n */\nexport function sanitizeProjectName(projectName: string): string {\n return projectName.replace(/[^a-zA-Z0-9\\-_]/g, '');\n}\n\n/**\n * 项目检查结果类型\n */\nexport type ProjectCheckResult = {\n exists: boolean;\n status: 'not_exists' | 'complete' | 'incomplete';\n needsCleanup: boolean;\n};\n\n/**\n * 检查项目状态(详细版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<ProjectCheckResult> 详细的项目状态\n */\nexport async function checkProjectStatus(workspacePath: string, projectName: string): Promise<ProjectCheckResult> {\n try {\n const projectPath = join(workspacePath, projectName);\n \n // 检查项目目录是否存在\n if (!existsSync(projectPath)) {\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n \n // 检查是否为 Git 仓库(存在 .git 目录)\n const gitPath = join(projectPath, '.git');\n if (!existsSync(gitPath)) {\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n // 更严格的完整性检查\n const isComplete = await isGitRepositoryComplete(projectPath);\n if (!isComplete) {\n console.log(`检测到不完整的Git仓库: ${projectPath}`);\n return {\n exists: true,\n status: 'incomplete',\n needsCleanup: true\n };\n }\n \n return {\n exists: true,\n status: 'complete',\n needsCleanup: false\n };\n } catch (error) {\n console.error(`检查项目 ${projectName} 状态时出错:`, error);\n return {\n exists: false,\n status: 'not_exists',\n needsCleanup: false\n };\n }\n}\n\n/**\n * 检查项目是否已存在于工作空间中(兼容版本)\n * @param workspacePath 工作空间路径\n * @param projectName 项目名称\n * @returns Promise<boolean> 项目是否存在且为有效的 Git 仓库\n */\nexport async function checkProjectExists(workspacePath: string, projectName: string): Promise<boolean> {\n const result = await checkProjectStatus(workspacePath, projectName);\n return result.status === 'complete';\n}\n\n/**\n * 检查Git仓库是否完整\n * @param projectPath 项目路径\n * @returns Promise<boolean> 仓库是否完整\n */\nasync function isGitRepositoryComplete(projectPath: string): Promise<boolean> {\n try {\n const gitPath = join(projectPath, '.git');\n \n // 检查关键的Git文件是否存在\n const requiredFiles = ['HEAD', 'config', 'refs'];\n for (const file of requiredFiles) {\n const filePath = join(gitPath, file);\n if (!existsSync(filePath)) {\n return false;\n }\n }\n \n // 检查是否有实际的项目文件(不只是.git目录)\n const entries = await fs.readdir(projectPath);\n const nonGitFiles = entries.filter((entry: string) => entry !== '.git');\n \n // 如果只有.git目录,说明克隆未完成\n if (nonGitFiles.length === 0) {\n return false;\n }\n \n // 检查HEAD文件是否有效\n const headPath = join(gitPath, 'HEAD');\n const headContent = await fs.readFile(headPath, 'utf-8');\n if (!headContent.trim() || headContent.includes('unborn')) {\n return false;\n }\n \n return true;\n } catch (error) {\n console.error('检查Git仓库完整性时出错:', error);\n return false;\n }\n}\n\n/**\n * 清理不完整的项目目录\n * @param projectPath 项目路径\n */\nexport async function cleanupIncompleteProject(projectPath: string): Promise<void> {\n try {\n console.log(`正在清理不完整的项目: ${projectPath}`);\n await fs.rm(projectPath, { recursive: true, force: true });\n console.log(`清理完成: ${projectPath}`);\n } catch (error) {\n console.error(`清理项目失败 ${projectPath}:`, error);\n // 清理失败不抛出错误,避免阻塞后续流程\n }\n}\n\n/**\n * 批量检查多个项目的存在状态\n * @param workspacePath 工作空间路径\n * @param projectNames 项目名称列表\n * @returns Promise<Record<string, boolean>> 项目名称到存在状态的映射\n */\nexport async function checkMultipleProjectsExist(\n workspacePath: string, \n projectNames: string[]\n): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n \n // 并行检查所有项目\n const checks = projectNames.map(async (projectName) => {\n const exists = await checkProjectExists(workspacePath, projectName);\n results[projectName] = exists;\n });\n \n await Promise.all(checks);\n return results;\n} ","type AbortState = {\n aborted: boolean;\n updatedAt: number;\n};\n\nconst abortStates = new Map<string, AbortState>();\nconst ABORT_STATE_TTL = 1000 * 60 * 30;\n\nfunction cleanupAbortStates() {\n const now = Date.now();\n for (const [runId, state] of abortStates.entries()) {\n if (now - state.updatedAt > ABORT_STATE_TTL) {\n abortStates.delete(runId);\n }\n }\n}\n\nexport function createUatGitFlowState(runId: string) {\n cleanupAbortStates();\n abortStates.set(runId, { aborted: false, updatedAt: Date.now() });\n}\n\nexport function markUatGitFlowAbort(runId: string) {\n const existing = abortStates.get(runId);\n abortStates.set(runId, {\n aborted: true,\n updatedAt: Date.now(),\n });\n if (!existing) {\n cleanupAbortStates();\n }\n}\n\nexport function isUatGitFlowAborted(runId: string) {\n cleanupAbortStates();\n return abortStates.get(runId)?.aborted ?? false;\n}\n\nexport function clearUatGitFlowState(runId: string) {\n abortStates.delete(runId);\n}\n"],"names":[],"mappings":"ubAAA,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAKO,IAAM,EAAmB,CAE9B,eAAgB,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,GAAA,EAAA,OAAA,AAAM,IAAK,YAAa,EAA7B,WAAK,MAGrB,YAAa,IAGb,sBAAuB,KAAK,GAAG,CAAC,EAAG,KAAK,GAAG,CAAC,CAAA,EAAA,EAAA,IAAA,AAAG,IAAI,MAAM,CAAE,IAG3D,iBAH4C,EAGxB,CACtB,EAEa,EAAsB,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,CAAA,EAAA,EAAA,OAAA,AAAM,IAAK,cAAhB,UA2B5B,CA3BiC,GA2B5B,EAAA,SAAA,CAAA,6JAAA,s3CC/CZ,IAAA,EAAA,EAAA,CAAA,CAAA,MAEA,EAAA,EAAA,CAAA,CAAA,OAMO,eAAe,IACpB,GAAI,CACF,MAAM,CAAA,EAAA,EAAA,MAAA,AAAK,EAAE,EAAA,mBAAmB,CAAE,EAAA,GAA5B,MAAqC,CAAC,IAAI,AAAnC,CACf,CAAE,KAAM,CAGN,OADA,MAAM,AAH4B,EAGT,CAAC,GACnB,CAAC,CACV,CAEA,GAAI,CACF,IAAM,EAAgB,MAAM,CAAA,EAAA,EAAA,QAAO,AAAP,EAAS,EAAA,mBAAmB,CAAE,GAA9B,MAE5B,GAAI,CAAC,EACH,CAHmC,KAG5B,CAAC,EAEV,IAHoB,GAGb,KAAK,KAAK,CAAC,EACpB,CAAE,MAAO,EAAO,CAGd,MAFA,QAAQ,KAAK,CAAC,iBAAkB,GAE1B,AAAI,MAAM,WAClB,CACF,CAMO,eAAe,EAAmB,CAAsB,EAC7D,IAAM,EAAiB,EAAA,mBAAmB,CAAG,OAC7C,GAAI,CACF,KAFqB,CAEf,CAAA,EAAA,EAAA,SAAA,AAAQ,EAAE,EAAgB,KAAK,SAAS,CAAC,EAAQ,KAAjD,AAAuD,GAAI,SACjE,MAAM,CAAA,EAAA,EAAA,MAAA,AAAK,EAAE,EAAgB,EAAA,mBAAmB,CAClD,CAAE,EADM,IACC,EAAO,CAEd,MAH6B,AAE7B,QAAQ,KAAK,CAAC,cAAe,GACnB,AAAJ,MAAU,WAClB,CACF,CAKO,IAAK,EAAA,SAAA,CAAA,mIAAA,gYCjDZ,IAAA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAEA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OAWO,eAAe,EAAyB,CAAqB,EAClE,GAAI,CAIF,MAHI,AAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,IACd,CAAA,EAAA,EAAA,OAD8B,EAC9B,AAAQ,EAAE,EAAe,CAAE,CADxB,UACmC,CAAK,GAEtC,CAAE,MAFP,GAEgB,CAAK,CACzB,CAAE,MAAO,EAAO,CACd,MAAO,CACL,QAAS,GACT,MAAO,CAAC,YAAY,EAAE,aAAiB,MAAQ,EAAM,OAAO,CAAG,OAAO,GAAA,CAAQ,AAChF,CACF,CACF,CAOO,eAAe,EAAgB,CAA0B,EAC9D,GAAM,SAAE,CAAO,WAAE,CAAS,SAAE,CAAO,YAAE,CAAU,SAAE,CAAO,OAAE,CAAK,CAAE,CAAG,EAC9D,EAAc,CAAA,EAAA,EAAA,QAAA,AAAO,EAAE,EAAS,QAEtC,OAAO,IAAI,KAFS,GAEgB,AAAC,IACnC,IAAM,EAAY,KAAK,GAAG,GAGpB,EAAmC,aACvC,EACA,OAAQ,EAAA,aAAa,CAAC,OAAO,CAC7B,SAAU,EACV,GAFQ,KAEC,sBACT,CACF,EACA,IAAa,EAAG,aAGhB,IAAM,EAAa,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAW,GAE7B,EAAU,CAAC,QAAS,aAAc,CAFrB,WAEkC,EAAS,EAAW,CAGzE,IAAQ,EAAa,SAAU,CAAC,iBAAiB,EAAE,EAAQ,IAAI,CAAC,KAAK;AAAE,CAAC,EACxE,IAAQ,EAAa,SAAU,CAAC,OAAO,EAAE,WAAW;AAAE,CAAC,EACvD,IAAQ,EAAa,SAAU,CAAC,OAAO,EAAE,QAAQ;AAAE,CAAC,EAEpD,IAAM,EAA2B,GAAA,EAAA,KAAI,AAAJ,EAAM,MAAO,EAAS,CACrD,IAAK,EACL,MAAO,CAAC,OAAQ,AAFe,OAEP,OAAO,AACjC,GAEI,EAAc,GACd,EAAgB,EAGpB,IAAQ,EAAa,SAAU,CAAC,mBAAmB,EAAE,EAAW,GAAG,CAAC;AAAE,CAAC,EAGvE,IAAM,EAAY,WAAW,KAC3B,IAAQ,EAAa,SAAU,CAAC,kBAAkB,EAAE,EAAU,IAAK;AAAQ,CAAC,EAC5E,EAAW,IAAI,CAAC,WAEhB,IAAM,EAA+B,CACnC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,SAAU,EACV,IAFQ,IAEC,SACT,MAAO,CAAC,QAAQ,EAAE,EAAU,IAAK,EAAE,CAAC,CACpC,QAAS,KAAK,GAAG,EACnB,EACA,IAAQ,EAAa,SAAU,CAAC;AAAe,CAAC,EAChD,IAAU,CAAA,EAAG,EAAY,QAAQ,CAAC,EAClC,EAAQ,EACV,EAAG,GAGH,EAAW,MAAM,EAAE,GAAG,OAAQ,AAAC,IAC7B,IAAM,EAAa,EAAK,QAAQ,GAGhC,IAAQ,EAAa,SAAU,GAG/B,EAAgB,KAAK,GAAG,CAAC,EAAgB,GAAI,IAC7C,IAAa,EAAe,YAC9B,GAGA,EAAW,MAAM,EAAE,GAAG,OAAQ,AAAC,IAC7B,IAAM,EAAa,EAAK,QAAQ,GAChC,GAAe,EAGQ,EAAW,QAAQ,CAAC,YACtB,EAAW,QAAQ,CAAC,sBACpB,EAAW,QAAQ,CAAC,qBACpB,EAAW,QAAQ,CAAC,qBACpB,EAAW,QAAQ,CAAC,wBACpB,EAAW,QAAQ,CAAC,wBACpB,EAAW,QAAQ,CAAC,gBACpB,EAAW,QAAQ,CAAC,cACpB,EAAW,QAAQ,CAAC,SACpB,EAAW,QAAQ,CAAC,gBAIvC,IAAQ,EAAa,WAAY,GAEjC,IAAQ,EAAa,SAAU,GAI7B,EAAW,QAAQ,CAAC,sBAAwB,EAAW,QAAQ,CAAC,qBAAqB,AACvF,EAAgB,KAAK,GAAG,CAAC,EAAgB,EAAG,IAC5C,IAAa,EAAe,cACnB,EAAW,QAAQ,CAAC,qBAAqB,AAClD,EAAgB,KAAK,GAAG,CAAC,EAAgB,EAAG,IAC5C,IAAa,EAAe,cACnB,EAAW,QAAQ,CAAC,wBAAwB,CACrD,EAAgB,KAAK,GAAG,CAAC,EAAgB,EAAG,IAC5C,IAAa,EAAe,aAEhC,GAGA,EAAW,EAAE,CAAC,QAAS,AAAC,IACtB,aAAa,GACb,IAAM,EAAU,KAAK,GAAG,GAClB,EAAW,EAAU,EAI3B,GAFA,IAAQ,EAAa,SAAU,CAAC,oBAAoB,EAAE,EAAK,KAAK,EAAE,KAAK,KAAK,CAAC,EAAW,KAAM;AAAG,CAAC,EAErF,IAAT,EAAY,CAEd,IAAQ,EAAa,SAAU,CAAC,iBAAiB,EAAE,WAAW;AAAE,CAAC,EACjE,IAAM,EAAiC,CACrC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,OAAO,CAC7B,SAAU,IACV,CAFQ,OAEC,eACT,CACF,EACA,IAAa,IAAK,QAClB,EAAQ,EACV,KAAO,CAEL,IAAM,EAAc,AA0C5B,SAAS,AAAc,CAAmB,EACxC,IAAM,EAAc,EAAY,WAAW,UAE3C,AAAI,EAAY,QAAQ,CAAC,0BAA4B,EAAY,QAAQ,CAAC,iBACjE,CADmF,kBAIxF,EAAY,QAAQ,CAAC,yBAA2B,EAAY,QAAQ,CAAC,aAChE,CAD8E,YAInF,EAAY,QAAQ,CAAC,YAAc,EAAY,QAAQ,CAAC,cACnD,CADkE,gBAIvE,EAAY,QAAQ,CAAC,WAChB,CAD4B,UAIjC,EAAY,QAAQ,CAAC,qBAChB,CADsC,iBAI3C,EAAY,QAAQ,CAAC,kBAChB,CADmC,SAKrC,EAAY,KAAK,CAAC,EAAG,MAAQ,CAAD,CAAa,MAAM,CAAG,IAAM,MAAQ,EAAA,CAAE,AAC3E,EAvE0C,GAClC,IAAQ,EAAa,SAAU,CAAC,aAAa,EAAE,YAAY;AAAE,CAAC,EAC9D,IAAQ,EAAa,SAAU,CAAC;AAAU,EAAE,YAAY;AAAE,CAAC,EAE3D,IAAM,EAAiC,CACrC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,SAAU,EACV,IAFQ,IAEC,OACT,MAAO,GAAe,CAAC,aAAa,EAAE,EAAA,CAAM,SAC5C,CACF,EACA,IAAU,CAAA,EAAG,EAAY,EAAE,EAAE,EAAc,KAAK,CAAA,CAAE,EAClD,EAAQ,EACV,CACF,GAGA,EAAW,EAAE,CAAC,QAAS,AAAC,IACtB,aAAa,GACb,IAAQ,EAAa,SAAU,CAAC,mBAAmB,EAAE,EAAM,OAAO,CAAC;AAAE,CAAC,EACtE,IAAQ,EAAa,SAAU,CAAC,OAAO,EAAE,EAAM,KAAK,EAAI,iBAAiB;AAAE,CAAC,EAE5E,IAAM,EAA+B,CACnC,GAAG,CAAe,CAClB,OAAQ,EAAA,aAAa,CAAC,MAAM,CAC5B,SAAU,EACV,IAFQ,IAEC,SACT,MAAO,CAAC,QAAQ,EAAE,EAAM,OAAO,CAAA,CAAE,CACjC,QAAS,KAAK,GAAG,EACnB,EACA,IAAU,CAAA,EAAG,EAAY,EAAE,EAAE,EAAM,OAAO,CAAA,CAAE,EAC5C,EAAQ,EACV,EACF,EACF,CA2CO,SAAS,EAAc,CAAW,EAEvC,MADsB,AACf,mCAAc,IAAI,CAAC,EAC5B,CAOO,SAAS,EAAoB,CAAmB,EACrD,OAAO,EAAY,OAAO,CAAC,mBAAoB,GACjD,CAiBO,eAAe,EAAmB,CAAqB,CAAE,CAAmB,EACjF,GAAI,CACF,IAAM,EAAc,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAe,GAGxC,GAAI,CAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,GACd,CAJkB,KAIX,CACL,IAF0B,IAElB,EACR,IAHC,GAGO,aACR,cAAc,CAChB,EAIF,IAAM,EAAU,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAa,QAClC,GAAI,CAAC,CAAA,EAAA,EAAA,UAAA,AAAS,CADE,CACA,GACd,MAAO,CACL,AAFsB,OAEd,GACR,IAHC,GAGO,aACR,cAAc,CAChB,EAKF,GAAI,CADe,AACd,MADoB,EAAwB,GAG/C,CAFe,MACf,QAAQ,GAAG,CAAC,CAAC,cAAc,EAAE,EAAA,CAAa,EACnC,CACL,QAAQ,EACR,OAAQ,aACR,aAAc,EAChB,EAGF,MAAO,CACL,QAAQ,EACR,OAAQ,WACR,cAAc,CAChB,CACF,CAAE,MAAO,EAAO,CAEd,OADA,QAAQ,KAAK,CAAC,CAAC,KAAK,EAAE,EAAY,OAAO,CAAC,CAAE,GACrC,CACL,QAAQ,EACR,OAAQ,aACR,cAAc,CAChB,CACF,CACF,CAQO,eAAe,EAAmB,CAAqB,CAAE,CAAmB,EAEjF,MAAyB,aAAlB,CADQ,MAAM,EAAmB,EAAe,EAAA,EACzC,MAAM,AACtB,CAOA,eAAe,EAAwB,CAAmB,EACxD,GAAI,CACF,IAAM,EAAU,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAa,QAIlC,IAAK,IAAM,IADW,CAAC,GACJ,IADY,AAHf,SAGyB,OAAO,CACd,CAChC,IAAM,EAAW,CAAA,EAAA,EAAA,IAAA,AAAG,EAAE,EAAS,GAC/B,GAAI,CAAC,CAAA,EAAA,EAAA,UAAA,AAAS,EAAE,GACd,CAFe,MAER,CADkB,AAG7B,CAIA,IAAM,EAAc,CADJ,KANT,CAMe,EAAA,QAAE,CAAC,OAAO,CAAC,EAAA,EACL,MAAM,CAAC,AAAC,GAA4B,KAD1C,IACgC,GAGtD,GAA2B,GAAG,CAA1B,EAAY,MAAM,CACpB,OAAO,EAIT,IAAM,EAAW,CAAA,EAAA,EAAA,IAAG,AAAH,EAAK,EAAS,QACzB,EAAc,MAAM,EAAA,QAAE,CAAC,CADZ,OACoB,CAAC,EAAU,SAChD,GAAI,CAAC,EAAY,CADS,GACL,IAAM,EAAY,QAAQ,CAAC,UAC9C,CADyD,MAClD,EAGT,OAAO,CACT,CAAE,MAAO,EAAO,CAEd,OADA,QAAQ,KAAK,CAAC,iBAAkB,IACzB,CACT,CACF,CAMO,eAAe,EAAyB,CAAmB,EAChE,GAAI,CACF,QAAQ,GAAG,CAAC,CAAC,YAAY,EAAE,EAAA,CAAa,EACxC,MAAM,EAAA,QAAE,CAAC,EAAE,CAAC,EAAa,CAAE,WAAW,EAAM,OAAO,CAAK,AAAlD,GACN,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,EAAA,CAAa,CACpC,CAAE,MAAO,EAAO,CACd,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,EAAY,CAAC,CAAC,CAAE,EAE1C,CACF,CAQO,eAAe,EACpB,CAAqB,CACrB,CAAsB,EAEtB,IAAM,EAAmC,CAAC,EAGpC,EAAS,EAAa,GAAG,CAAC,MAAO,IACrC,IAAM,EAAS,MAAM,EAAmB,EAAe,GACvD,CAAO,CAAC,EAAY,CAAG,CACzB,GAGA,OADA,MAAM,QAAQ,GAAG,CAAC,GACX,CACT,oKC/YA,IAAM,EAAc,IAAI,IAGxB,SAAS,IACP,IAAM,EAAM,KAAK,GAAG,GACpB,IAAK,GAAM,CAAC,EAAO,EAAM,GAAI,EAAY,OAAO,GAAI,AAC9C,EAAM,EAAM,SAAS,CALL,EAKQ,IAC1B,CANyB,CAMb,IANkB,EAMZ,CAAC,EAGzB,CAEO,CAN0C,QAMjC,EAAsB,CAAa,EACjD,IACA,EAAY,GAAG,CAAC,EAAO,CAAE,SAAS,EAAO,UAAW,KAAK,GAAG,EAAG,EACjE,CAEO,SAAS,EAAoB,CAAa,EAC/C,IAAM,EAAW,EAAY,GAAG,CAAC,GACjC,EAAY,GAAG,CAAC,EAAO,CACrB,SAAS,EACT,UAAW,KAAK,GAAG,EACrB,GACI,AAAC,GACH,GAEJ,CAEO,GALU,MAKD,EAAoB,CAAa,EAE/C,OADA,IACO,EAAY,GAAG,CAAC,IAAQ,SAAW,EAC5C,CAEO,SAAS,EAAqB,CAAa,EAChD,EAAY,MAAM,CAAC,EACrB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/compiled/os-browserify/browser.js","turbopack:///[project]/node_modules/.pnpm/next@15.3.4_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/next/dist/compiled/path-browserify/index.js","turbopack:///[project]/packages/server/src/lib/workspace-types.ts","turbopack:///[project]/packages/server/src/components/project-initializer.tsx"],"sourcesContent":["(function(){if(typeof __nccwpck_require__!==\"undefined\")__nccwpck_require__.ab=__dirname+\"/\";var n={};!function(){var e=n;e.endianness=function(){return\"LE\"};e.hostname=function(){if(typeof location!==\"undefined\"){return location.hostname}else return\"\"};e.loadavg=function(){return[]};e.uptime=function(){return 0};e.freemem=function(){return Number.MAX_VALUE};e.totalmem=function(){return Number.MAX_VALUE};e.cpus=function(){return[]};e.type=function(){return\"Browser\"};e.release=function(){if(typeof navigator!==\"undefined\"){return navigator.appVersion}return\"\"};e.networkInterfaces=e.getNetworkInterfaces=function(){return{}};e.arch=function(){return\"javascript\"};e.platform=function(){return\"browser\"};e.tmpdir=e.tmpDir=function(){return\"/tmp\"};e.EOL=\"\\n\";e.homedir=function(){return\"/\"}}();module.exports=n})();","(function(){\"use strict\";var e={114:function(e){function assertPath(e){if(typeof e!==\"string\"){throw new TypeError(\"Path must be a string. Received \"+JSON.stringify(e))}}function normalizeStringPosix(e,r){var t=\"\";var i=0;var n=-1;var a=0;var f;for(var l=0;l<=e.length;++l){if(l<e.length)f=e.charCodeAt(l);else if(f===47)break;else f=47;if(f===47){if(n===l-1||a===1){}else if(n!==l-1&&a===2){if(t.length<2||i!==2||t.charCodeAt(t.length-1)!==46||t.charCodeAt(t.length-2)!==46){if(t.length>2){var s=t.lastIndexOf(\"/\");if(s!==t.length-1){if(s===-1){t=\"\";i=0}else{t=t.slice(0,s);i=t.length-1-t.lastIndexOf(\"/\")}n=l;a=0;continue}}else if(t.length===2||t.length===1){t=\"\";i=0;n=l;a=0;continue}}if(r){if(t.length>0)t+=\"/..\";else t=\"..\";i=2}}else{if(t.length>0)t+=\"/\"+e.slice(n+1,l);else t=e.slice(n+1,l);i=l-n-1}n=l;a=0}else if(f===46&&a!==-1){++a}else{a=-1}}return t}function _format(e,r){var t=r.dir||r.root;var i=r.base||(r.name||\"\")+(r.ext||\"\");if(!t){return i}if(t===r.root){return t+i}return t+e+i}var r={resolve:function resolve(){var e=\"\";var r=false;var t;for(var i=arguments.length-1;i>=-1&&!r;i--){var n;if(i>=0)n=arguments[i];else{if(t===undefined)t=\"\";n=t}assertPath(n);if(n.length===0){continue}e=n+\"/\"+e;r=n.charCodeAt(0)===47}e=normalizeStringPosix(e,!r);if(r){if(e.length>0)return\"/\"+e;else return\"/\"}else if(e.length>0){return e}else{return\".\"}},normalize:function normalize(e){assertPath(e);if(e.length===0)return\".\";var r=e.charCodeAt(0)===47;var t=e.charCodeAt(e.length-1)===47;e=normalizeStringPosix(e,!r);if(e.length===0&&!r)e=\".\";if(e.length>0&&t)e+=\"/\";if(r)return\"/\"+e;return e},isAbsolute:function isAbsolute(e){assertPath(e);return e.length>0&&e.charCodeAt(0)===47},join:function join(){if(arguments.length===0)return\".\";var e;for(var t=0;t<arguments.length;++t){var i=arguments[t];assertPath(i);if(i.length>0){if(e===undefined)e=i;else e+=\"/\"+i}}if(e===undefined)return\".\";return r.normalize(e)},relative:function relative(e,t){assertPath(e);assertPath(t);if(e===t)return\"\";e=r.resolve(e);t=r.resolve(t);if(e===t)return\"\";var i=1;for(;i<e.length;++i){if(e.charCodeAt(i)!==47)break}var n=e.length;var a=n-i;var f=1;for(;f<t.length;++f){if(t.charCodeAt(f)!==47)break}var l=t.length;var s=l-f;var o=a<s?a:s;var u=-1;var h=0;for(;h<=o;++h){if(h===o){if(s>o){if(t.charCodeAt(f+h)===47){return t.slice(f+h+1)}else if(h===0){return t.slice(f+h)}}else if(a>o){if(e.charCodeAt(i+h)===47){u=h}else if(h===0){u=0}}break}var c=e.charCodeAt(i+h);var v=t.charCodeAt(f+h);if(c!==v)break;else if(c===47)u=h}var g=\"\";for(h=i+u+1;h<=n;++h){if(h===n||e.charCodeAt(h)===47){if(g.length===0)g+=\"..\";else g+=\"/..\"}}if(g.length>0)return g+t.slice(f+u);else{f+=u;if(t.charCodeAt(f)===47)++f;return t.slice(f)}},_makeLong:function _makeLong(e){return e},dirname:function dirname(e){assertPath(e);if(e.length===0)return\".\";var r=e.charCodeAt(0);var t=r===47;var i=-1;var n=true;for(var a=e.length-1;a>=1;--a){r=e.charCodeAt(a);if(r===47){if(!n){i=a;break}}else{n=false}}if(i===-1)return t?\"/\":\".\";if(t&&i===1)return\"//\";return e.slice(0,i)},basename:function basename(e,r){if(r!==undefined&&typeof r!==\"string\")throw new TypeError('\"ext\" argument must be a string');assertPath(e);var t=0;var i=-1;var n=true;var a;if(r!==undefined&&r.length>0&&r.length<=e.length){if(r.length===e.length&&r===e)return\"\";var f=r.length-1;var l=-1;for(a=e.length-1;a>=0;--a){var s=e.charCodeAt(a);if(s===47){if(!n){t=a+1;break}}else{if(l===-1){n=false;l=a+1}if(f>=0){if(s===r.charCodeAt(f)){if(--f===-1){i=a}}else{f=-1;i=l}}}}if(t===i)i=l;else if(i===-1)i=e.length;return e.slice(t,i)}else{for(a=e.length-1;a>=0;--a){if(e.charCodeAt(a)===47){if(!n){t=a+1;break}}else if(i===-1){n=false;i=a+1}}if(i===-1)return\"\";return e.slice(t,i)}},extname:function extname(e){assertPath(e);var r=-1;var t=0;var i=-1;var n=true;var a=0;for(var f=e.length-1;f>=0;--f){var l=e.charCodeAt(f);if(l===47){if(!n){t=f+1;break}continue}if(i===-1){n=false;i=f+1}if(l===46){if(r===-1)r=f;else if(a!==1)a=1}else if(r!==-1){a=-1}}if(r===-1||i===-1||a===0||a===1&&r===i-1&&r===t+1){return\"\"}return e.slice(r,i)},format:function format(e){if(e===null||typeof e!==\"object\"){throw new TypeError('The \"pathObject\" argument must be of type Object. Received type '+typeof e)}return _format(\"/\",e)},parse:function parse(e){assertPath(e);var r={root:\"\",dir:\"\",base:\"\",ext:\"\",name:\"\"};if(e.length===0)return r;var t=e.charCodeAt(0);var i=t===47;var n;if(i){r.root=\"/\";n=1}else{n=0}var a=-1;var f=0;var l=-1;var s=true;var o=e.length-1;var u=0;for(;o>=n;--o){t=e.charCodeAt(o);if(t===47){if(!s){f=o+1;break}continue}if(l===-1){s=false;l=o+1}if(t===46){if(a===-1)a=o;else if(u!==1)u=1}else if(a!==-1){u=-1}}if(a===-1||l===-1||u===0||u===1&&a===l-1&&a===f+1){if(l!==-1){if(f===0&&i)r.base=r.name=e.slice(1,l);else r.base=r.name=e.slice(f,l)}}else{if(f===0&&i){r.name=e.slice(1,a);r.base=e.slice(1,l)}else{r.name=e.slice(f,a);r.base=e.slice(f,l)}r.ext=e.slice(a,l)}if(f>0)r.dir=e.slice(0,f-1);else if(i)r.dir=\"/\";return r},sep:\"/\",delimiter:\":\",win32:null,posix:null};r.posix=r;e.exports=r}};var r={};function __nccwpck_require__(t){var i=r[t];if(i!==undefined){return i.exports}var n=r[t]={exports:{}};var a=true;try{e[t](n,n.exports,__nccwpck_require__);a=false}finally{if(a)delete r[t]}return n.exports}if(typeof __nccwpck_require__!==\"undefined\")__nccwpck_require__.ab=__dirname+\"/\";var t=__nccwpck_require__(114);module.exports=t})();","import { homedir, cpus } from 'os';\nimport { join } from 'path';\n\n/**\n * 工作空间配置常量\n */\nexport const WORKSPACE_CONFIG = {\n // 工作空间根目录路径\n WORKSPACE_ROOT: join(homedir(), 'Documents', 'prime-workspace'),\n\n // Git 操作超时时间 (毫秒)\n GIT_TIMEOUT: 300000, // 5分钟\n\n // 最大并发克隆数量(基于CPU核心数,最小2个,最大8个)\n MAX_CONCURRENT_CLONES: Math.max(2, Math.min(cpus().length, 8)),\n\n // 重试次数限制\n MAX_RETRY_ATTEMPTS: 3,\n} as const;\n\nexport const PROJECT_CONFIG_PATH = join(homedir(), '.prime-projects.json');\n\nexport interface ProjectConfig {\n repo: string;\n mockingIntercept?: boolean;\n mockOpen?: boolean;\n envs: {\n [envName: string]: {\n host: string;\n currentProxy: string;\n proxyEnv: {\n [key: string]: string;\n };\n envFileName: string;\n proxyKey: string;\n subApps?: string[];\n };\n };\n}\n\nexport interface ProjectsConfig {\n [projectName: string]: ProjectConfig;\n}\n\n/**\n * 项目状态枚举\n */\nexport enum ProjectStatus {\n PENDING = 'pending',\n EXISTING = 'existing',\n CLONING = 'cloning',\n SUCCESS = 'success',\n FAILED = 'failed',\n RETRYING = 'retrying',\n INCOMPLETE = 'incomplete', // 不完整的项目,需要清理\n}\n\n/**\n * 项目进度信息接口\n */\nexport interface ProjectProgress {\n projectName: string;\n status: ProjectStatus;\n progress: number; // 0-100\n message: string;\n error?: string;\n startTime?: number;\n endTime?: number;\n}\n\n/**\n * 初始化结果接口\n */\nexport interface InitializationResult {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n failedProjects: string[];\n workspacePath: string;\n duration: number;\n}\n\n/**\n * Git 操作配置接口\n */\nexport interface GitOperationConfig {\n repoUrl: string;\n targetDir: string;\n timeout: number;\n onProgress?: (progress: number, message: string) => void;\n onError?: (error: string) => void;\n onLog?: (projectName: string, logType: 'stdout' | 'stderr' | 'progress', content: string) => void;\n} ","\"use client\";\n\nimport { useEffect, useState, type ChangeEvent } from 'react';\nimport { useRouter } from 'next/navigation';\nimport { Button } from '@/components/ui/button';\nimport { EditorSplitButton } from '@/components/EditorSplitButton';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog';\nimport { ProjectStatus } from '@/lib/workspace-types';\nimport type { EditorType } from '@/lib/editor-operations';\n\ninterface ProjectState {\n name: string;\n status: ProjectStatus;\n progress: number;\n message: string;\n error?: string;\n canRetry: boolean;\n isOpening?: boolean;\n isCleaningUp?: boolean;\n needsCleanup?: boolean;\n logs?: Array<{type: 'stdout' | 'stderr' | 'progress', content: string, timestamp: number}>;\n}\n\ninterface InitializationState {\n isInitializing: boolean;\n isCompleted: boolean;\n isLoading: boolean;\n hasCompleted: boolean;\n globalProgress: number;\n globalMessage: string;\n projects: Record<string, ProjectState>;\n completionSummary?: {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n duration: number;\n };\n}\n\nconst ProjectInitializer = () => {\n const router = useRouter();\n const [state, setState] = useState<InitializationState>({\n isInitializing: false,\n isCompleted: false,\n isLoading: true,\n hasCompleted: false,\n globalProgress: 0,\n globalMessage: '正在检查工作空间状态...',\n projects: {},\n });\n\n const [uatForm, setUatForm] = useState({\n selectedProjects: [] as string[],\n createBranch: 'release/GDirect-',\n baseBranch: 'main',\n mergeBranch: '',\n });\n\n const [uatRunState, setUatRunState] = useState({\n isRunning: false,\n operationLogs: [] as string[],\n feedbacks: [] as string[],\n runId: '',\n });\n\n const [isAdmin, setIsAdmin] = useState(false);\n\n const [pendingStep, setPendingStep] = useState<{\n stepId: string;\n projectName: string;\n description: string;\n command: string;\n } | null>(null);\n const [isConfirmOpen, setIsConfirmOpen] = useState(false);\n const useStepConfirm = false;\n const [showResultDialog, setShowResultDialog] = useState(false);\n const [projectResults, setProjectResults] = useState<Array<{\n projectName: string;\n success: boolean;\n reason?: string;\n rollbackActions?: string[];\n }>>([]);\n \n const [expandedLogs, setExpandedLogs] = useState<Record<string, boolean>>({});\n\n // 页面加载时检查工作空间状态\n useEffect(() => {\n checkWorkspaceStatus();\n }, []);\n\n useEffect(() => {\n const fetchAdminStatus = async () => {\n try {\n const response = await fetch('/api/admin-status');\n const data = await response.json();\n setIsAdmin(Boolean(data?.isAdmin));\n } catch (error) {\n console.error('获取管理员状态失败:', error);\n setIsAdmin(false);\n }\n };\n fetchAdminStatus();\n }, []);\n\n // 检查工作空间状态\n const checkWorkspaceStatus = async () => {\n try {\n setState(prev => ({\n ...prev,\n isLoading: true,\n globalMessage: '正在检查工作空间状态...',\n }));\n\n const response = await fetch('/api/check-workspace');\n const data = await response.json();\n\n if (data.success) {\n const projectStates: Record<string, ProjectState> = {};\n data.projects.forEach((project: { name: string; status: ProjectStatus; message: string; needsCleanup?: boolean }) => {\n projectStates[project.name] = {\n name: project.name,\n status: project.status,\n progress: project.status === ProjectStatus.EXISTING ? 100 : 0,\n message: project.message,\n canRetry: false,\n needsCleanup: project.needsCleanup || false,\n };\n });\n\n setState(prev => ({\n ...prev,\n isLoading: false,\n projects: projectStates,\n globalMessage: data.message || '检查完成',\n }));\n } else {\n setState(prev => ({\n ...prev,\n isLoading: false,\n globalMessage: data.error || '检查工作空间状态失败',\n }));\n }\n } catch (error) {\n setState(prev => ({\n ...prev,\n isLoading: false,\n globalMessage: '无法连接到服务器,请刷新页面重试',\n }));\n console.error('检查工作空间状态失败:', error);\n }\n };\n\n // 开始初始化工作空间\n const startInitialization = () => {\n setState(prev => ({\n ...prev,\n isInitializing: true,\n isCompleted: false,\n hasCompleted: false,\n globalProgress: 0,\n globalMessage: '正在连接服务器...',\n projects: {},\n completionSummary: undefined,\n }));\n\n // 创建 EventSource 连接\n const eventSource = new EventSource('/api/initialize-workspace');\n\n eventSource.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data);\n handleSSEMessage(data);\n } catch (error) {\n console.error('解析 SSE 消息失败:', error);\n }\n };\n\n eventSource.onerror = () => {\n setState(prev => {\n // 如果已经收到完成消息,则不显示错误(这是正常的连接关闭)\n if (prev.hasCompleted) {\n return prev;\n }\n \n return {\n ...prev,\n isInitializing: false,\n globalMessage: '连接服务器失败,请重试',\n };\n });\n eventSource.close();\n };\n\n // 监听连接关闭\n eventSource.addEventListener('error', () => {\n eventSource.close();\n });\n };\n\n // 处理 SSE 消息\n const handleSSEMessage = (data: {\n type: string;\n progress?: number;\n message?: string;\n projects?: string[];\n projectName?: string;\n error?: string;\n logType?: 'stdout' | 'stderr' | 'progress';\n content?: string;\n timestamp?: number;\n result?: {\n success: boolean;\n totalProjects: number;\n successCount: number;\n failedCount: number;\n duration: number;\n };\n }) => {\n switch (data.type) {\n case 'initialization':\n case 'workspace_created':\n case 'projects_loaded':\n setState(prev => ({\n ...prev,\n globalProgress: (data.progress as number) || 0,\n globalMessage: (data.message as string) || '',\n }));\n \n // 如果收到项目列表,初始化项目状态\n if (data.projects && Array.isArray(data.projects)) {\n const projectStates: Record<string, ProjectState> = {};\n data.projects.forEach((projectName: string) => {\n projectStates[projectName] = {\n name: projectName,\n status: ProjectStatus.PENDING,\n progress: 0,\n message: '等待开始...',\n canRetry: false,\n };\n });\n setState(prev => ({ ...prev, projects: projectStates }));\n }\n break;\n\n case 'project_existing':\n if (data.projectName) {\n const projectName = data.projectName;\n setState(prev => ({\n ...prev,\n globalProgress: data.progress ?? prev.globalProgress,\n globalMessage: data.message ?? '',\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.EXISTING,\n message: '项目已存在',\n progress: 100,\n canRetry: false,\n },\n },\n }));\n }\n break;\n\n case 'project_start':\n if (data.projectName) {\n const projectName = data.projectName;\n setState(prev => ({\n ...prev,\n globalProgress: data.progress ?? prev.globalProgress,\n globalMessage: data.message ?? '',\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.CLONING,\n message: '开始克隆...',\n progress: 0,\n },\n },\n }));\n }\n break;\n\n case 'project_progress':\n if (data.projectName) {\n const projectName = data.projectName;\n setState(prev => ({\n ...prev,\n globalProgress: data.progress ?? prev.globalProgress,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n message: data.message ?? '',\n progress: Math.min(data.progress ?? 0, 100),\n },\n },\n }));\n }\n break;\n\n case 'project_success':\n if (data.projectName) {\n const projectName = data.projectName;\n setState(prev => ({\n ...prev,\n globalProgress: data.progress ?? prev.globalProgress,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.SUCCESS,\n message: '克隆成功',\n progress: 100,\n canRetry: false,\n },\n },\n }));\n }\n break;\n\n case 'project_failed':\n if (data.projectName) {\n const projectName = data.projectName;\n setState(prev => ({\n ...prev,\n globalProgress: data.progress ?? prev.globalProgress,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.FAILED,\n message: '克隆失败',\n error: data.error,\n canRetry: true,\n },\n },\n }));\n }\n break;\n\n case 'command_log':\n if (data.projectName && data.logType && data.content !== undefined && data.timestamp) {\n const projectName = data.projectName;\n const logType = data.logType as 'stdout' | 'stderr' | 'progress';\n const content = data.content as string;\n const timestamp = data.timestamp as number;\n \n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n logs: [\n ...(prev.projects[projectName]?.logs || []),\n {\n type: logType,\n content: content,\n timestamp: timestamp,\n }\n ].slice(-1000), // 保留最新的1000条日志\n },\n },\n }));\n }\n break;\n\n case 'completion':\n setState(prev => ({\n ...prev,\n isInitializing: false,\n isCompleted: true,\n hasCompleted: true,\n globalProgress: 100,\n globalMessage: data.message ?? '初始化完成',\n completionSummary: data.result ? {\n success: data.result.success,\n totalProjects: data.result.totalProjects,\n successCount: data.result.successCount,\n failedCount: data.result.failedCount,\n duration: data.result.duration,\n } : undefined,\n }));\n break;\n\n case 'error':\n setState(prev => ({\n ...prev,\n isInitializing: false,\n hasCompleted: true,\n globalMessage: data.message ?? '发生错误',\n globalProgress: data.progress ?? prev.globalProgress,\n }));\n break;\n }\n };\n\n // 在编辑器中打开项目(使用 editor schema 协议)\n const openProject = async (projectName: string, editor: EditorType = 'cursor') => {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n isOpening: true,\n },\n },\n }));\n\n try {\n const response = await fetch('/api/open-project', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ projectName, editor }),\n });\n\n const result = await response.json();\n\n if (result.success && result.editorUrl) {\n // 使用编辑器 schema 协议打开项目\n // 创建临时链接并点击,这样可以触发系统调用对应的编辑器应用程序\n const link = document.createElement('a');\n link.href = result.editorUrl;\n link.style.display = 'none';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n } else {\n console.error('打开项目失败:', result.error);\n }\n\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n isOpening: false,\n },\n },\n }));\n } catch (error) {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n isOpening: false,\n },\n },\n }));\n console.error('打开项目失败:', error);\n }\n };\n\n // 清理不完整的项目\n const cleanupProject = async (projectName: string) => {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n isCleaningUp: true,\n },\n },\n }));\n\n try {\n const response = await fetch('/api/cleanup-project', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ projectName }),\n });\n\n const result = await response.json();\n\n if (result.success) {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.PENDING,\n message: '已清理,待克隆',\n isCleaningUp: false,\n needsCleanup: false,\n },\n },\n }));\n } else {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n isCleaningUp: false,\n error: result.error,\n },\n },\n }));\n }\n } catch (error) {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n isCleaningUp: false,\n error: error instanceof Error ? error.message : String(error),\n },\n },\n }));\n }\n };\n\n // 重试单个项目\n const retryProject = async (projectName: string) => {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.RETRYING,\n message: '正在重试...',\n progress: 0,\n canRetry: false,\n },\n },\n }));\n\n try {\n const response = await fetch('/api/retry-project', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ projectName }),\n });\n\n const result = await response.json();\n\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: result.success ? ProjectStatus.SUCCESS : ProjectStatus.FAILED,\n message: result.message,\n error: result.error,\n progress: result.success ? 100 : prev.projects[projectName].progress,\n canRetry: !result.success,\n },\n },\n }));\n } catch (error) {\n setState(prev => ({\n ...prev,\n projects: {\n ...prev.projects,\n [projectName]: {\n ...prev.projects[projectName],\n status: ProjectStatus.FAILED,\n message: '重试失败',\n error: error instanceof Error ? error.message : String(error),\n canRetry: true,\n },\n },\n }));\n }\n };\n\n // 获取状态样式\n const getStatusColor = (status: ProjectStatus) => {\n switch (status) {\n case ProjectStatus.EXISTING:\n return 'text-green-600 bg-green-50 border-green-200';\n case ProjectStatus.SUCCESS:\n return 'text-green-600 bg-green-50 border-green-200';\n case ProjectStatus.FAILED:\n return 'text-red-600 bg-red-50 border-red-200';\n case ProjectStatus.INCOMPLETE:\n return 'text-orange-600 bg-orange-50 border-orange-200';\n case ProjectStatus.CLONING:\n case ProjectStatus.RETRYING:\n return 'text-blue-600 bg-blue-50 border-blue-200';\n case ProjectStatus.PENDING:\n return 'text-gray-600 bg-gray-50 border-gray-200';\n default:\n return 'text-gray-600 bg-gray-50 border-gray-200';\n }\n };\n\n const getStatusText = (status: ProjectStatus) => {\n switch (status) {\n case ProjectStatus.PENDING:\n return '待克隆';\n case ProjectStatus.EXISTING:\n return '已存在';\n case ProjectStatus.CLONING:\n return '克隆中';\n case ProjectStatus.SUCCESS:\n return '成功';\n case ProjectStatus.FAILED:\n return '失败';\n case ProjectStatus.INCOMPLETE:\n return '不完整';\n case ProjectStatus.RETRYING:\n return '重试中';\n default:\n return '未知';\n }\n };\n\n // 判断是否所有项目都已存在\n const isAllProjectsExisting = () => {\n const projectValues = Object.values(state.projects);\n return projectValues.length > 0 && \n projectValues.every(project => project.status === ProjectStatus.EXISTING);\n };\n\n // 导航到项目配置页面\n const navigateToProjectConfig = (projectName: string) => {\n router.push(`/configuration?project=${encodeURIComponent(projectName)}`);\n };\n\n const handleProjectSelection = (event: ChangeEvent<HTMLSelectElement>) => {\n const selectedProjects = Array.from(event.target.selectedOptions).map(option => option.value);\n setUatForm(prev => ({\n ...prev,\n selectedProjects,\n }));\n };\n\n const updateUatField = (\n field: 'createBranch' | 'baseBranch' | 'mergeBranch',\n value: string\n ) => {\n setUatForm(prev => ({\n ...prev,\n [field]: value,\n }));\n };\n\n const runUatGitFlow = async (dryRun: boolean) => {\n const feedbacks: string[] = [];\n\n if (uatForm.selectedProjects.length === 0) {\n feedbacks.push('请先选择至少一个项目。');\n }\n\n if (!uatForm.createBranch.trim()) {\n feedbacks.push('请填写创建分支名。');\n }\n\n if (!uatForm.baseBranch.trim()) {\n feedbacks.push('请填写从 origin 哪个分支创建。');\n }\n\n if (!uatForm.mergeBranch.trim()) {\n feedbacks.push('请填写被合并分支名称。');\n }\n\n if (feedbacks.length > 0) {\n setUatRunState({\n isRunning: false,\n operationLogs: [],\n feedbacks,\n runId: '',\n });\n return;\n }\n\n const runId = `uat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n setUatRunState({\n isRunning: true,\n operationLogs: [],\n feedbacks: [],\n runId,\n });\n\n if (dryRun || !useStepConfirm) {\n try {\n const response = await fetch('/api/uat-git-flow', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n projects: uatForm.selectedProjects,\n createBranch: uatForm.createBranch.trim(),\n baseBranch: uatForm.baseBranch.trim(),\n mergeBranch: uatForm.mergeBranch.trim(),\n dryRun,\n runId,\n }),\n });\n\n const result = await response.json();\n\n setUatRunState({\n isRunning: false,\n operationLogs: Array.isArray(result.operationLogs) ? result.operationLogs : [],\n feedbacks: Array.isArray(result.feedbacks) ? result.feedbacks : [result.error || '执行失败'],\n runId: '',\n });\n if (Array.isArray(result.projectResults)) {\n setProjectResults(result.projectResults);\n setShowResultDialog(true);\n }\n } catch (error) {\n setUatRunState({\n isRunning: false,\n operationLogs: [],\n feedbacks: [error instanceof Error ? error.message : '执行失败'],\n runId: '',\n });\n setProjectResults([]);\n setShowResultDialog(false);\n }\n return;\n }\n\n try {\n const response = await fetch('/api/uat-git-flow/step', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'start',\n projects: uatForm.selectedProjects,\n createBranch: uatForm.createBranch.trim(),\n baseBranch: uatForm.baseBranch.trim(),\n mergeBranch: uatForm.mergeBranch.trim(),\n runId,\n }),\n });\n\n const result = await response.json();\n const logs = Array.isArray(result.operationLogs) ? result.operationLogs : [];\n const feedback = Array.isArray(result.feedbacks) ? result.feedbacks : [result.error || '执行失败'];\n\n if (!result.success) {\n setUatRunState({\n isRunning: false,\n operationLogs: logs,\n feedbacks: feedback,\n runId: '',\n });\n return;\n }\n\n setUatRunState(prev => ({\n ...prev,\n isRunning: !result.isComplete,\n operationLogs: logs,\n feedbacks: feedback,\n runId,\n }));\n\n if (result.nextStep) {\n setPendingStep(result.nextStep);\n setIsConfirmOpen(true);\n } else {\n setPendingStep(null);\n setIsConfirmOpen(false);\n setUatRunState(prev => ({ ...prev, isRunning: false, runId: '' }));\n if (Array.isArray(result.projectResults)) {\n setProjectResults(result.projectResults);\n setShowResultDialog(true);\n }\n }\n } catch (error) {\n setUatRunState({\n isRunning: false,\n operationLogs: [],\n feedbacks: [error instanceof Error ? error.message : '执行失败'],\n runId: '',\n });\n setPendingStep(null);\n setIsConfirmOpen(false);\n }\n };\n\n const confirmNextStep = async () => {\n if (!pendingStep || !uatRunState.runId) return;\n try {\n const response = await fetch('/api/uat-git-flow/step', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'execute',\n runId: uatRunState.runId,\n stepId: pendingStep.stepId,\n }),\n });\n\n const result = await response.json();\n const logs = Array.isArray(result.operationLogs) ? result.operationLogs : [];\n const feedback = Array.isArray(result.feedbacks) ? result.feedbacks : [result.error || '执行失败'];\n\n if (!result.success) {\n setUatRunState(prev => ({\n ...prev,\n isRunning: false,\n operationLogs: logs,\n feedbacks: feedback,\n runId: '',\n }));\n setPendingStep(null);\n setIsConfirmOpen(false);\n return;\n }\n\n setUatRunState(prev => ({\n ...prev,\n operationLogs: logs,\n feedbacks: feedback,\n isRunning: !result.isComplete,\n runId: result.isComplete ? '' : prev.runId,\n }));\n\n if (result.nextStep) {\n setPendingStep(result.nextStep);\n setIsConfirmOpen(true);\n } else {\n setPendingStep(null);\n setIsConfirmOpen(false);\n if (Array.isArray(result.projectResults)) {\n setProjectResults(result.projectResults);\n setShowResultDialog(true);\n }\n }\n } catch (error) {\n setUatRunState(prev => ({\n ...prev,\n isRunning: false,\n operationLogs: prev.operationLogs,\n feedbacks: [...prev.feedbacks, error instanceof Error ? error.message : '执行失败'],\n runId: '',\n }));\n setPendingStep(null);\n setIsConfirmOpen(false);\n }\n };\n\n const abortUatGitFlow = async () => {\n if (!uatRunState.runId) return;\n try {\n const response = await fetch(useStepConfirm ? '/api/uat-git-flow/step' : '/api/uat-git-flow/abort', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: useStepConfirm\n ? JSON.stringify({ action: 'abort', runId: uatRunState.runId })\n : JSON.stringify({ runId: uatRunState.runId }),\n });\n const result = await response.json();\n if (result && Array.isArray(result.operationLogs)) {\n setUatRunState(prev => ({\n ...prev,\n isRunning: false,\n operationLogs: result.operationLogs,\n feedbacks: Array.isArray(result.feedbacks) ? result.feedbacks : prev.feedbacks,\n runId: '',\n }));\n } else {\n setUatRunState(prev => ({\n ...prev,\n isRunning: false,\n runId: '',\n }));\n }\n if (Array.isArray(result.projectResults)) {\n setProjectResults(result.projectResults);\n setShowResultDialog(true);\n }\n setPendingStep(null);\n setIsConfirmOpen(false);\n } catch (error) {\n setUatRunState(prev => ({\n ...prev,\n feedbacks: [...prev.feedbacks, error instanceof Error ? error.message : '中断失败'],\n }));\n }\n };\n\n const handleConfirmOpenChange = (open: boolean) => {\n if (!open && pendingStep && uatRunState.isRunning) {\n return;\n }\n setIsConfirmOpen(open);\n };\n\n return (\n <div className=\"container mx-auto p-4 sm:p-6 md:p-8\">\n <div className=\"flex justify-between items-center mb-6\">\n <h1 className=\"text-2xl font-bold\">项目初始化</h1>\n {state.isLoading ? (\n <Button disabled>检查中...</Button>\n ) : (\n <Button \n onClick={startInitialization}\n disabled={state.isInitializing}\n >\n {state.isInitializing ? '初始化中...' : '创建项目空间'}\n </Button>\n )}\n </div>\n\n {/* 全局进度 */}\n {(state.isInitializing || state.isCompleted) && !isAllProjectsExisting() && (\n <div className=\"mb-6 p-4 bg-gray-50 rounded-lg\">\n <div className=\"flex justify-between items-center mb-2\">\n <span className=\"text-sm font-medium\">{state.globalMessage}</span>\n <span className=\"text-sm text-gray-600\">{state.globalProgress}%</span>\n </div>\n <div className=\"w-full bg-gray-200 rounded-full h-2\">\n <div \n className=\"bg-blue-600 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${state.globalProgress}%` }}\n />\n </div>\n </div>\n )}\n\n {/* 完成总结 */}\n {state.completionSummary && !isAllProjectsExisting() && (\n <div className={`mb-6 p-4 rounded-lg border ${\n state.completionSummary.success \n ? 'bg-green-50 border-green-200' \n : 'bg-yellow-50 border-yellow-200'\n }`}>\n <h3 className=\"font-semibold mb-2\">初始化完成</h3>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 text-sm\">\n <div>总项目数: {state.completionSummary.totalProjects}</div>\n <div className=\"text-green-600\">成功: {state.completionSummary.successCount}</div>\n <div className=\"text-red-600\">失败: {state.completionSummary.failedCount}</div>\n <div>耗时: {Math.round(state.completionSummary.duration / 1000)}s</div>\n </div>\n </div>\n )}\n\n {/* 项目列表 */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4\">\n {Object.keys(state.projects).length > 0 ? (\n Object.values(state.projects).map((project) => (\n <div \n key={project.name} \n className={`border rounded-lg p-4 ${getStatusColor(project.status)}`}\n >\n <div className=\"flex justify-between items-start mb-2\">\n <h2 \n className=\"font-semibold cursor-pointer hover:text-blue-600 transition-colors\"\n onClick={() => navigateToProjectConfig(project.name)}\n title=\"点击进入项目配置\"\n >\n {project.name}\n </h2>\n <span className=\"text-xs px-2 py-1 rounded-full bg-white\">\n {getStatusText(project.status)}\n </span>\n </div>\n \n <p className=\"text-sm mb-2\">{project.message}</p>\n \n {project.status === ProjectStatus.CLONING || project.status === ProjectStatus.RETRYING ? (\n <div className=\"mb-2\">\n <div className=\"w-full bg-white rounded-full h-1\">\n <div \n className=\"bg-current h-1 rounded-full transition-all duration-300\"\n style={{ width: `${project.progress}%` }}\n />\n </div>\n <span className=\"text-xs\">{project.progress}%</span>\n </div>\n ) : null}\n\n {project.error && (\n <p className=\"text-xs text-red-600 mb-2\">{project.error}</p>\n )}\n\n <div className=\"space-y-2\">\n {project.canRetry && (\n <Button \n size=\"sm\"\n variant=\"outline\"\n onClick={() => retryProject(project.name)}\n className=\"w-full\"\n >\n 重试\n </Button>\n )}\n \n {project.needsCleanup && project.status === ProjectStatus.INCOMPLETE && (\n <Button \n size=\"sm\"\n variant=\"destructive\"\n onClick={() => cleanupProject(project.name)}\n disabled={project.isCleaningUp}\n className=\"w-full\"\n >\n {project.isCleaningUp ? '清理中...' : '清理项目'}\n </Button>\n )}\n \n {(project.status === ProjectStatus.EXISTING || project.status === ProjectStatus.SUCCESS) && (\n <EditorSplitButton\n onOpen={(editor) => openProject(project.name, editor)}\n loading={project.isOpening}\n loadingText=\"打开中...\"\n size=\"sm\"\n variant=\"default\"\n className=\"w-full\"\n />\n )}\n \n {project.logs && project.logs.length > 0 && (\n <Button \n size=\"sm\"\n variant=\"outline\"\n onClick={() => setExpandedLogs(prev => ({\n ...prev,\n [project.name]: !prev[project.name]\n }))}\n className=\"w-full\"\n >\n {expandedLogs[project.name] ? '隐藏日志' : `查看日志 (${project.logs.length})`}\n </Button>\n )}\n </div>\n\n {/* 日志显示区域 */}\n {expandedLogs[project.name] && project.logs && project.logs.length > 0 && (\n <div className=\"mt-3 border-t pt-3\">\n <div className=\"bg-black text-white rounded text-xs font-mono p-2 max-h-48 overflow-y-auto\">\n {project.logs.map((log, index) => (\n <div key={index} className={`mb-1 ${\n log.type === 'stderr' \n ? 'text-red-400' \n : log.type === 'progress' \n ? 'text-yellow-400' \n : 'text-green-400'\n }`}>\n <span className=\"text-gray-500 mr-2\">\n {new Date(log.timestamp).toLocaleTimeString()}\n </span>\n <span className=\"text-blue-400 mr-2\">[{log.type}]</span>\n <span className=\"whitespace-pre-wrap\">{log.content}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n ))\n ) : (\n <div className=\"col-span-full text-center text-gray-500 py-8\">\n {state.isLoading ? '正在检查项目状态...' : \n state.isInitializing ? '正在加载项目...' : \n '点击\"创建项目空间\"开始初始化'}\n </div>\n )}\n </div>\n\n {/* UAT Git 操作流 */}\n {isAdmin && (\n <div className=\"mt-8 rounded-lg border bg-white p-4 shadow-sm\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-4\">\n <h2 className=\"text-lg font-semibold\">UAT上线前 Git 操作流</h2>\n <div className=\"flex flex-wrap gap-2\">\n <Button\n onClick={() => runUatGitFlow(false)}\n disabled={uatRunState.isRunning}\n >\n {uatRunState.isRunning ? '执行中...' : '执行'}\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => runUatGitFlow(true)}\n disabled={uatRunState.isRunning}\n >\n DRY RUN\n </Button>\n <Button\n variant=\"destructive\"\n onClick={abortUatGitFlow}\n disabled={!uatRunState.isRunning}\n >\n 中断\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"uat-projects\">选择项目</Label>\n <select\n id=\"uat-projects\"\n multiple\n value={uatForm.selectedProjects}\n onChange={handleProjectSelection}\n className=\"w-full min-h-[140px] rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\"\n >\n {Object.keys(state.projects).length === 0 ? (\n <option value=\"\" disabled>暂无可用项目</option>\n ) : (\n Object.keys(state.projects).map(projectName => (\n <option key={projectName} value={projectName}>\n {projectName}\n </option>\n ))\n )}\n </select>\n <p className=\"text-xs text-gray-500\">按住 Command / Ctrl 可多选</p>\n </div>\n\n <div className=\"grid gap-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"uat-create-branch\">创建分支名</Label>\n <Input\n id=\"uat-create-branch\"\n value={uatForm.createBranch}\n onChange={(event) => updateUatField('createBranch', event.target.value)}\n placeholder=\"例如: release/uat-2026-01\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"uat-base-branch\">从 origin 哪个分支创建</Label>\n <Input\n id=\"uat-base-branch\"\n value={uatForm.baseBranch}\n onChange={(event) => updateUatField('baseBranch', event.target.value)}\n placeholder=\"例如: develop\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"uat-merge-branch\">被合并分支名称</Label>\n <Input\n id=\"uat-merge-branch\"\n value={uatForm.mergeBranch}\n onChange={(event) => updateUatField('mergeBranch', event.target.value)}\n placeholder=\"例如: release/candidate\"\n />\n </div>\n </div>\n </div>\n\n <div className=\"mt-6 grid gap-4 md:grid-cols-2\">\n <div className=\"rounded-lg border p-3\">\n <h3 className=\"text-sm font-semibold mb-2\">操作记录</h3>\n {uatRunState.operationLogs.length === 0 ? (\n <p className=\"text-xs text-gray-500\">暂无记录</p>\n ) : (\n <div className=\"bg-black text-white rounded text-xs font-mono p-2 max-h-48 overflow-y-auto\">\n {uatRunState.operationLogs.map((log, index) => (\n <div key={index} className=\"mb-1 whitespace-pre-wrap\">\n {log}\n </div>\n ))}\n </div>\n )}\n </div>\n <div className=\"rounded-lg border p-3\">\n <h3 className=\"text-sm font-semibold mb-2\">反馈信息</h3>\n {uatRunState.feedbacks.length === 0 ? (\n <p className=\"text-xs text-gray-500\">暂无反馈</p>\n ) : (\n <div className=\"space-y-1 text-sm\">\n {uatRunState.feedbacks.map((message, index) => (\n <div key={index} className=\"rounded bg-gray-50 px-2 py-1 text-gray-700\">\n {message}\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n\n <Dialog open={useStepConfirm && isConfirmOpen} onOpenChange={handleConfirmOpenChange}>\n <DialogContent showCloseButton={false}>\n <DialogHeader>\n <DialogTitle>确认执行下一步</DialogTitle>\n <DialogDescription>\n {pendingStep ? `${pendingStep.projectName} · ${pendingStep.description}` : '准备下一步执行'}\n </DialogDescription>\n </DialogHeader>\n <div className=\"rounded-md border bg-gray-50 p-3 text-sm font-mono text-gray-700\">\n {pendingStep ? pendingStep.command : ''}\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={abortUatGitFlow}>\n 取消执行\n </Button>\n <Button onClick={confirmNextStep} disabled={!pendingStep}>\n 确认并执行\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n <Dialog open={isAdmin && showResultDialog} onOpenChange={setShowResultDialog}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>操作结果</DialogTitle>\n <DialogDescription>查看所有项目执行结果</DialogDescription>\n </DialogHeader>\n <div className=\"space-y-2\">\n {projectResults.length === 0 ? (\n <p className=\"text-sm text-gray-500\">暂无结果</p>\n ) : (\n projectResults.map((result) => (\n <div\n key={result.projectName}\n className={`rounded-md border px-3 py-2 text-sm ${\n result.success ? 'bg-green-50 text-green-700' : 'bg-red-50 text-red-700'\n }`}\n >\n <div className=\"flex items-start justify-between\">\n <span className=\"font-medium\">{result.projectName}</span>\n <span className=\"ml-4 text-right\">\n {result.success ? '成功' : result.reason || '失败'}\n </span>\n </div>\n {!result.success && result.rollbackActions && result.rollbackActions.length > 0 && (\n <div className=\"mt-2 text-xs text-gray-600\">\n <div className=\"font-semibold text-gray-700\">已回滚操作:</div>\n <ul className=\"mt-1 list-disc pl-4\">\n {result.rollbackActions.map((action, index) => (\n <li key={`${result.projectName}-rollback-${index}`}>{action}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n ))\n )}\n </div>\n <DialogFooter>\n <Button onClick={() => setShowResultDialog(false)}>关闭</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n};\n\nexport default ProjectInitializer;\n"],"names":[],"mappings":"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","ignoreList":[0,1]}
@@ -1,3 +0,0 @@
1
- (globalThis.TURBOPACK=globalThis.TURBOPACK||[]).push(["object"==typeof document?document.currentScript:void 0,{86442:function(e){var s,{g:t,__dirname:r,m:a,e:n}=e;"undefined"!=typeof __nccwpck_require__&&(__nccwpck_require__.ab=r+"/"),(s={}).endianness=function(){return"LE"},s.hostname=function(){return"undefined"!=typeof location?location.hostname:""},s.loadavg=function(){return[]},s.uptime=function(){return 0},s.freemem=function(){return Number.MAX_VALUE},s.totalmem=function(){return Number.MAX_VALUE},s.cpus=function(){return[]},s.type=function(){return"Browser"},s.release=function(){return"undefined"!=typeof navigator?navigator.appVersion:""},s.networkInterfaces=s.getNetworkInterfaces=function(){return{}},s.arch=function(){return"javascript"},s.platform=function(){return"browser"},s.tmpdir=s.tmpDir=function(){return"/tmp"},s.EOL="\n",s.homedir=function(){return"/"},a.exports=s},87733:function(e){var{g:s,__dirname:t,m:r,e:a}=e;!function(){"use strict";var e={114:function(e){function s(e){if("string"!=typeof e)throw TypeError("Path must be a string. Received "+JSON.stringify(e))}function t(e,s){for(var t,r="",a=0,n=-1,o=0,i=0;i<=e.length;++i){if(i<e.length)t=e.charCodeAt(i);else if(47===t)break;else t=47;if(47===t){if(n===i-1||1===o);else if(n!==i-1&&2===o){if(r.length<2||2!==a||46!==r.charCodeAt(r.length-1)||46!==r.charCodeAt(r.length-2)){if(r.length>2){var c=r.lastIndexOf("/");if(c!==r.length-1){-1===c?(r="",a=0):a=(r=r.slice(0,c)).length-1-r.lastIndexOf("/"),n=i,o=0;continue}}else if(2===r.length||1===r.length){r="",a=0,n=i,o=0;continue}}s&&(r.length>0?r+="/..":r="..",a=2)}else r.length>0?r+="/"+e.slice(n+1,i):r=e.slice(n+1,i),a=i-n-1;n=i,o=0}else 46===t&&-1!==o?++o:o=-1}return r}var r={resolve:function(){for(var e,r,a="",n=!1,o=arguments.length-1;o>=-1&&!n;o--)o>=0?r=arguments[o]:(void 0===e&&(e=""),r=e),s(r),0!==r.length&&(a=r+"/"+a,n=47===r.charCodeAt(0));if(a=t(a,!n),n)if(a.length>0)return"/"+a;else return"/";return a.length>0?a:"."},normalize:function(e){if(s(e),0===e.length)return".";var r=47===e.charCodeAt(0),a=47===e.charCodeAt(e.length-1);return(0!==(e=t(e,!r)).length||r||(e="."),e.length>0&&a&&(e+="/"),r)?"/"+e:e},isAbsolute:function(e){return s(e),e.length>0&&47===e.charCodeAt(0)},join:function(){if(0==arguments.length)return".";for(var e,t=0;t<arguments.length;++t){var a=arguments[t];s(a),a.length>0&&(void 0===e?e=a:e+="/"+a)}return void 0===e?".":r.normalize(e)},relative:function(e,t){if(s(e),s(t),e===t||(e=r.resolve(e))===(t=r.resolve(t)))return"";for(var a=1;a<e.length&&47===e.charCodeAt(a);++a);for(var n=e.length,o=n-a,i=1;i<t.length&&47===t.charCodeAt(i);++i);for(var c=t.length-i,l=o<c?o:c,d=-1,u=0;u<=l;++u){if(u===l){if(c>l){if(47===t.charCodeAt(i+u))return t.slice(i+u+1);else if(0===u)return t.slice(i+u)}else o>l&&(47===e.charCodeAt(a+u)?d=u:0===u&&(d=0));break}var g=e.charCodeAt(a+u);if(g!==t.charCodeAt(i+u))break;47===g&&(d=u)}var p="";for(u=a+d+1;u<=n;++u)(u===n||47===e.charCodeAt(u))&&(0===p.length?p+="..":p+="/..");return p.length>0?p+t.slice(i+d):(i+=d,47===t.charCodeAt(i)&&++i,t.slice(i))},_makeLong:function(e){return e},dirname:function(e){if(s(e),0===e.length)return".";for(var t=e.charCodeAt(0),r=47===t,a=-1,n=!0,o=e.length-1;o>=1;--o)if(47===(t=e.charCodeAt(o))){if(!n){a=o;break}}else n=!1;return -1===a?r?"/":".":r&&1===a?"//":e.slice(0,a)},basename:function(e,t){if(void 0!==t&&"string"!=typeof t)throw TypeError('"ext" argument must be a string');s(e);var r,a=0,n=-1,o=!0;if(void 0!==t&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";var i=t.length-1,c=-1;for(r=e.length-1;r>=0;--r){var l=e.charCodeAt(r);if(47===l){if(!o){a=r+1;break}}else -1===c&&(o=!1,c=r+1),i>=0&&(l===t.charCodeAt(i)?-1==--i&&(n=r):(i=-1,n=c))}return a===n?n=c:-1===n&&(n=e.length),e.slice(a,n)}for(r=e.length-1;r>=0;--r)if(47===e.charCodeAt(r)){if(!o){a=r+1;break}}else -1===n&&(o=!1,n=r+1);return -1===n?"":e.slice(a,n)},extname:function(e){s(e);for(var t=-1,r=0,a=-1,n=!0,o=0,i=e.length-1;i>=0;--i){var c=e.charCodeAt(i);if(47===c){if(!n){r=i+1;break}continue}-1===a&&(n=!1,a=i+1),46===c?-1===t?t=i:1!==o&&(o=1):-1!==t&&(o=-1)}return -1===t||-1===a||0===o||1===o&&t===a-1&&t===r+1?"":e.slice(t,a)},format:function(e){var s,t;if(null===e||"object"!=typeof e)throw TypeError('The "pathObject" argument must be of type Object. Received type '+typeof e);return s=e.dir||e.root,t=e.base||(e.name||"")+(e.ext||""),s?s===e.root?s+t:s+"/"+t:t},parse:function(e){s(e);var t,r={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return r;var a=e.charCodeAt(0),n=47===a;n?(r.root="/",t=1):t=0;for(var o=-1,i=0,c=-1,l=!0,d=e.length-1,u=0;d>=t;--d){if(47===(a=e.charCodeAt(d))){if(!l){i=d+1;break}continue}-1===c&&(l=!1,c=d+1),46===a?-1===o?o=d:1!==u&&(u=1):-1!==o&&(u=-1)}return -1===o||-1===c||0===u||1===u&&o===c-1&&o===i+1?-1!==c&&(0===i&&n?r.base=r.name=e.slice(1,c):r.base=r.name=e.slice(i,c)):(0===i&&n?(r.name=e.slice(1,o),r.base=e.slice(1,c)):(r.name=e.slice(i,o),r.base=e.slice(i,c)),r.ext=e.slice(o,c)),i>0?r.dir=e.slice(0,i-1):n&&(r.dir="/"),r},sep:"/",delimiter:":",win32:null,posix:null};r.posix=r,e.exports=r}},s={};function a(t){var r=s[t];if(void 0!==r)return r.exports;var n=s[t]={exports:{}},o=!0;try{e[t](n,n.exports,a),o=!1}finally{o&&delete s[t]}return n.exports}a.ab=t+"/",r.exports=a(114)}()},7647:e=>{"use strict";var{g:s,__dirname:t}=e;{e.s({PROJECT_CONFIG_PATH:()=>t,ProjectStatus:()=>n,WORKSPACE_CONFIG:()=>s});var r=e.i(86442),a=e.i(87733);let s={WORKSPACE_ROOT:(0,a.join)((0,r.homedir)(),"Documents","prime-workspace"),GIT_TIMEOUT:3e5,MAX_CONCURRENT_CLONES:Math.max(2,Math.min((0,r.cpus)().length,8)),MAX_RETRY_ATTEMPTS:3},t=(0,a.join)((0,r.homedir)(),".prime-projects.json");var n=function(e){return e.PENDING="pending",e.EXISTING="existing",e.CLONING="cloning",e.SUCCESS="success",e.FAILED="failed",e.RETRYING="retrying",e.INCOMPLETE="incomplete",e}({})}},9993:e=>{"use strict";var{g:s,__dirname:t}=e;{e.s({default:()=>s});var r=e.i(20393),a=e.i(19886),n=e.i(42152),o=e.i(86871),i=e.i(75777),c=e.i(70599),l=e.i(80226),d=e.i(19579),u=e.i(7647);let s=()=>{let e=(0,n.useRouter)(),[s,t]=(0,a.useState)({isInitializing:!1,isCompleted:!1,isLoading:!0,hasCompleted:!1,globalProgress:0,globalMessage:"正在检查工作空间状态...",projects:{}}),[g,p]=(0,a.useState)({selectedProjects:[],createBranch:"release/GDirect-",baseBranch:"main",mergeBranch:""}),[m,h]=(0,a.useState)({isRunning:!1,operationLogs:[],feedbacks:[],runId:""}),[j,f]=(0,a.useState)(!1),[b,x]=(0,a.useState)(null),[y,N]=(0,a.useState)(!1),[v,C]=(0,a.useState)(!1),[S,P]=(0,a.useState)([]),[I,w]=(0,a.useState)({});(0,a.useEffect)(()=>{A()},[]),(0,a.useEffect)(()=>{(async()=>{try{let e=await fetch("/api/admin-status"),s=await e.json();f(!!s?.isAdmin)}catch(e){console.error("获取管理员状态失败:",e),f(!1)}})()},[]);let A=async()=>{try{t(e=>({...e,isLoading:!0,globalMessage:"正在检查工作空间状态..."}));let e=await fetch("/api/check-workspace"),s=await e.json();if(s.success){let e={};s.projects.forEach(s=>{e[s.name]={name:s.name,status:s.status,progress:100*(s.status===u.ProjectStatus.EXISTING),message:s.message,canRetry:!1,needsCleanup:s.needsCleanup||!1}}),t(t=>({...t,isLoading:!1,projects:e,globalMessage:s.message||"检查完成"}))}else t(e=>({...e,isLoading:!1,globalMessage:s.error||"检查工作空间状态失败"}))}catch(e){t(e=>({...e,isLoading:!1,globalMessage:"无法连接到服务器,请刷新页面重试"})),console.error("检查工作空间状态失败:",e)}},k=e=>{switch(e.type){case"initialization":case"workspace_created":case"projects_loaded":if(t(s=>({...s,globalProgress:e.progress||0,globalMessage:e.message||""})),e.projects&&Array.isArray(e.projects)){let s={};e.projects.forEach(e=>{s[e]={name:e,status:u.ProjectStatus.PENDING,progress:0,message:"等待开始...",canRetry:!1}}),t(e=>({...e,projects:s}))}break;case"project_existing":if(e.projectName){let s=e.projectName;t(t=>({...t,globalProgress:e.progress??t.globalProgress,globalMessage:e.message??"",projects:{...t.projects,[s]:{...t.projects[s],status:u.ProjectStatus.EXISTING,message:"项目已存在",progress:100,canRetry:!1}}}))}break;case"project_start":if(e.projectName){let s=e.projectName;t(t=>({...t,globalProgress:e.progress??t.globalProgress,globalMessage:e.message??"",projects:{...t.projects,[s]:{...t.projects[s],status:u.ProjectStatus.CLONING,message:"开始克隆...",progress:0}}}))}break;case"project_progress":if(e.projectName){let s=e.projectName;t(t=>({...t,globalProgress:e.progress??t.globalProgress,projects:{...t.projects,[s]:{...t.projects[s],message:e.message??"",progress:Math.min(e.progress??0,100)}}}))}break;case"project_success":if(e.projectName){let s=e.projectName;t(t=>({...t,globalProgress:e.progress??t.globalProgress,projects:{...t.projects,[s]:{...t.projects[s],status:u.ProjectStatus.SUCCESS,message:"克隆成功",progress:100,canRetry:!1}}}))}break;case"project_failed":if(e.projectName){let s=e.projectName;t(t=>({...t,globalProgress:e.progress??t.globalProgress,projects:{...t.projects,[s]:{...t.projects[s],status:u.ProjectStatus.FAILED,message:"克隆失败",error:e.error,canRetry:!0}}}))}break;case"command_log":if(e.projectName&&e.logType&&void 0!==e.content&&e.timestamp){let s=e.projectName,r=e.logType,a=e.content,n=e.timestamp;t(e=>({...e,projects:{...e.projects,[s]:{...e.projects[s],logs:[...e.projects[s]?.logs||[],{type:r,content:a,timestamp:n}].slice(-1e3)}}}))}break;case"completion":t(s=>({...s,isInitializing:!1,isCompleted:!0,hasCompleted:!0,globalProgress:100,globalMessage:e.message??"初始化完成",completionSummary:e.result?{success:e.result.success,totalProjects:e.result.totalProjects,successCount:e.result.successCount,failedCount:e.result.failedCount,duration:e.result.duration}:void 0}));break;case"error":t(s=>({...s,isInitializing:!1,hasCompleted:!0,globalMessage:e.message??"发生错误",globalProgress:e.progress??s.globalProgress}))}},E=async(e,s="cursor")=>{t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],isOpening:!0}}}));try{let r=await fetch("/api/open-project",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:e,editor:s})}),a=await r.json();if(a.success&&a.editorUrl){let e=document.createElement("a");e.href=a.editorUrl,e.style.display="none",document.body.appendChild(e),e.click(),document.body.removeChild(e)}else console.error("打开项目失败:",a.error);t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],isOpening:!1}}}))}catch(s){t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],isOpening:!1}}})),console.error("打开项目失败:",s)}},R=async e=>{t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],isCleaningUp:!0}}}));try{let s=await fetch("/api/cleanup-project",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:e})}),r=await s.json();r.success?t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],status:u.ProjectStatus.PENDING,message:"已清理,待克隆",isCleaningUp:!1,needsCleanup:!1}}})):t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],isCleaningUp:!1,error:r.error}}}))}catch(s){t(t=>({...t,projects:{...t.projects,[e]:{...t.projects[e],isCleaningUp:!1,error:s instanceof Error?s.message:String(s)}}}))}},T=async e=>{t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],status:u.ProjectStatus.RETRYING,message:"正在重试...",progress:0,canRetry:!1}}}));try{let s=await fetch("/api/retry-project",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectName:e})}),r=await s.json();t(s=>({...s,projects:{...s.projects,[e]:{...s.projects[e],status:r.success?u.ProjectStatus.SUCCESS:u.ProjectStatus.FAILED,message:r.message,error:r.error,progress:r.success?100:s.projects[e].progress,canRetry:!r.success}}}))}catch(s){t(t=>({...t,projects:{...t.projects,[e]:{...t.projects[e],status:u.ProjectStatus.FAILED,message:"重试失败",error:s instanceof Error?s.message:String(s),canRetry:!0}}}))}},O=e=>{switch(e){case u.ProjectStatus.EXISTING:case u.ProjectStatus.SUCCESS:return"text-green-600 bg-green-50 border-green-200";case u.ProjectStatus.FAILED:return"text-red-600 bg-red-50 border-red-200";case u.ProjectStatus.INCOMPLETE:return"text-orange-600 bg-orange-50 border-orange-200";case u.ProjectStatus.CLONING:case u.ProjectStatus.RETRYING:return"text-blue-600 bg-blue-50 border-blue-200";case u.ProjectStatus.PENDING:default:return"text-gray-600 bg-gray-50 border-gray-200"}},L=e=>{switch(e){case u.ProjectStatus.PENDING:return"待克隆";case u.ProjectStatus.EXISTING:return"已存在";case u.ProjectStatus.CLONING:return"克隆中";case u.ProjectStatus.SUCCESS:return"成功";case u.ProjectStatus.FAILED:return"失败";case u.ProjectStatus.INCOMPLETE:return"不完整";case u.ProjectStatus.RETRYING:return"重试中";default:return"未知"}},B=()=>{let e=Object.values(s.projects);return e.length>0&&e.every(e=>e.status===u.ProjectStatus.EXISTING)},D=s=>{e.push(`/configuration?project=${encodeURIComponent(s)}`)},_=(e,s)=>{p(t=>({...t,[e]:s}))},M=async e=>{let s=[];if(0===g.selectedProjects.length&&s.push("请先选择至少一个项目。"),g.createBranch.trim()||s.push("请填写创建分支名。"),g.baseBranch.trim()||s.push("请填写从 origin 哪个分支创建。"),g.mergeBranch.trim()||s.push("请填写被合并分支名称。"),s.length>0)return void h({isRunning:!1,operationLogs:[],feedbacks:s,runId:""});let t=`uat-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;h({isRunning:!0,operationLogs:[],feedbacks:[],runId:t});try{let s=await fetch("/api/uat-git-flow",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projects:g.selectedProjects,createBranch:g.createBranch.trim(),baseBranch:g.baseBranch.trim(),mergeBranch:g.mergeBranch.trim(),dryRun:e,runId:t})}),r=await s.json();h({isRunning:!1,operationLogs:Array.isArray(r.operationLogs)?r.operationLogs:[],feedbacks:Array.isArray(r.feedbacks)?r.feedbacks:[r.error||"执行失败"],runId:""}),Array.isArray(r.projectResults)&&(P(r.projectResults),C(!0))}catch(e){h({isRunning:!1,operationLogs:[],feedbacks:[e instanceof Error?e.message:"执行失败"],runId:""}),P([]),C(!1)}},G=async()=>{if(b&&m.runId)try{let e=await fetch("/api/uat-git-flow/step",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"execute",runId:m.runId,stepId:b.stepId})}),s=await e.json(),t=Array.isArray(s.operationLogs)?s.operationLogs:[],r=Array.isArray(s.feedbacks)?s.feedbacks:[s.error||"执行失败"];if(!s.success){h(e=>({...e,isRunning:!1,operationLogs:t,feedbacks:r,runId:""})),x(null),N(!1);return}h(e=>({...e,operationLogs:t,feedbacks:r,isRunning:!s.isComplete,runId:s.isComplete?"":e.runId})),s.nextStep?(x(s.nextStep),N(!0)):(x(null),N(!1),Array.isArray(s.projectResults)&&(P(s.projectResults),C(!0)))}catch(e){h(s=>({...s,isRunning:!1,operationLogs:s.operationLogs,feedbacks:[...s.feedbacks,e instanceof Error?e.message:"执行失败"],runId:""})),x(null),N(!1)}},U=async()=>{if(m.runId)try{let e=await fetch("/api/uat-git-flow/abort",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({runId:m.runId})}),s=await e.json();s&&Array.isArray(s.operationLogs)?h(e=>({...e,isRunning:!1,operationLogs:s.operationLogs,feedbacks:Array.isArray(s.feedbacks)?s.feedbacks:e.feedbacks,runId:""})):h(e=>({...e,isRunning:!1,runId:""})),Array.isArray(s.projectResults)&&(P(s.projectResults),C(!0)),x(null),N(!1)}catch(e){h(s=>({...s,feedbacks:[...s.feedbacks,e instanceof Error?e.message:"中断失败"]}))}};return(0,r.jsxs)("div",{className:"container mx-auto p-4 sm:p-6 md:p-8",children:[(0,r.jsxs)("div",{className:"flex justify-between items-center mb-6",children:[(0,r.jsx)("h1",{className:"text-2xl font-bold",children:"项目初始化"}),s.isLoading?(0,r.jsx)(o.Button,{disabled:!0,children:"检查中..."}):(0,r.jsx)(o.Button,{onClick:()=>{t(e=>({...e,isInitializing:!0,isCompleted:!1,hasCompleted:!1,globalProgress:0,globalMessage:"正在连接服务器...",projects:{},completionSummary:void 0}));let e=new EventSource("/api/initialize-workspace");e.onmessage=e=>{try{let s=JSON.parse(e.data);k(s)}catch(e){console.error("解析 SSE 消息失败:",e)}},e.onerror=()=>{t(e=>e.hasCompleted?e:{...e,isInitializing:!1,globalMessage:"连接服务器失败,请重试"}),e.close()},e.addEventListener("error",()=>{e.close()})},disabled:s.isInitializing,children:s.isInitializing?"初始化中...":"创建项目空间"})]}),(s.isInitializing||s.isCompleted)&&!B()&&(0,r.jsxs)("div",{className:"mb-6 p-4 bg-gray-50 rounded-lg",children:[(0,r.jsxs)("div",{className:"flex justify-between items-center mb-2",children:[(0,r.jsx)("span",{className:"text-sm font-medium",children:s.globalMessage}),(0,r.jsxs)("span",{className:"text-sm text-gray-600",children:[s.globalProgress,"%"]})]}),(0,r.jsx)("div",{className:"w-full bg-gray-200 rounded-full h-2",children:(0,r.jsx)("div",{className:"bg-blue-600 h-2 rounded-full transition-all duration-300",style:{width:`${s.globalProgress}%`}})})]}),s.completionSummary&&!B()&&(0,r.jsxs)("div",{className:`mb-6 p-4 rounded-lg border ${s.completionSummary.success?"bg-green-50 border-green-200":"bg-yellow-50 border-yellow-200"}`,children:[(0,r.jsx)("h3",{className:"font-semibold mb-2",children:"初始化完成"}),(0,r.jsxs)("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 text-sm",children:[(0,r.jsxs)("div",{children:["总项目数: ",s.completionSummary.totalProjects]}),(0,r.jsxs)("div",{className:"text-green-600",children:["成功: ",s.completionSummary.successCount]}),(0,r.jsxs)("div",{className:"text-red-600",children:["失败: ",s.completionSummary.failedCount]}),(0,r.jsxs)("div",{children:["耗时: ",Math.round(s.completionSummary.duration/1e3),"s"]})]})]}),(0,r.jsx)("div",{className:"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4",children:Object.keys(s.projects).length>0?Object.values(s.projects).map(e=>(0,r.jsxs)("div",{className:`border rounded-lg p-4 ${O(e.status)}`,children:[(0,r.jsxs)("div",{className:"flex justify-between items-start mb-2",children:[(0,r.jsx)("h2",{className:"font-semibold cursor-pointer hover:text-blue-600 transition-colors",onClick:()=>D(e.name),title:"点击进入项目配置",children:e.name}),(0,r.jsx)("span",{className:"text-xs px-2 py-1 rounded-full bg-white",children:L(e.status)})]}),(0,r.jsx)("p",{className:"text-sm mb-2",children:e.message}),e.status===u.ProjectStatus.CLONING||e.status===u.ProjectStatus.RETRYING?(0,r.jsxs)("div",{className:"mb-2",children:[(0,r.jsx)("div",{className:"w-full bg-white rounded-full h-1",children:(0,r.jsx)("div",{className:"bg-current h-1 rounded-full transition-all duration-300",style:{width:`${e.progress}%`}})}),(0,r.jsxs)("span",{className:"text-xs",children:[e.progress,"%"]})]}):null,e.error&&(0,r.jsx)("p",{className:"text-xs text-red-600 mb-2",children:e.error}),(0,r.jsxs)("div",{className:"space-y-2",children:[e.canRetry&&(0,r.jsx)(o.Button,{size:"sm",variant:"outline",onClick:()=>T(e.name),className:"w-full",children:"重试"}),e.needsCleanup&&e.status===u.ProjectStatus.INCOMPLETE&&(0,r.jsx)(o.Button,{size:"sm",variant:"destructive",onClick:()=>R(e.name),disabled:e.isCleaningUp,className:"w-full",children:e.isCleaningUp?"清理中...":"清理项目"}),(e.status===u.ProjectStatus.EXISTING||e.status===u.ProjectStatus.SUCCESS)&&(0,r.jsx)(i.EditorSplitButton,{onOpen:s=>E(e.name,s),loading:e.isOpening,loadingText:"打开中...",size:"sm",variant:"default",className:"w-full"}),e.logs&&e.logs.length>0&&(0,r.jsx)(o.Button,{size:"sm",variant:"outline",onClick:()=>w(s=>({...s,[e.name]:!s[e.name]})),className:"w-full",children:I[e.name]?"隐藏日志":`查看日志 (${e.logs.length})`})]}),I[e.name]&&e.logs&&e.logs.length>0&&(0,r.jsx)("div",{className:"mt-3 border-t pt-3",children:(0,r.jsx)("div",{className:"bg-black text-white rounded text-xs font-mono p-2 max-h-48 overflow-y-auto",children:e.logs.map((e,s)=>(0,r.jsxs)("div",{className:`mb-1 ${"stderr"===e.type?"text-red-400":"progress"===e.type?"text-yellow-400":"text-green-400"}`,children:[(0,r.jsx)("span",{className:"text-gray-500 mr-2",children:new Date(e.timestamp).toLocaleTimeString()}),(0,r.jsxs)("span",{className:"text-blue-400 mr-2",children:["[",e.type,"]"]}),(0,r.jsx)("span",{className:"whitespace-pre-wrap",children:e.content})]},s))})})]},e.name)):(0,r.jsx)("div",{className:"col-span-full text-center text-gray-500 py-8",children:s.isLoading?"正在检查项目状态...":s.isInitializing?"正在加载项目...":'点击"创建项目空间"开始初始化'})}),j&&(0,r.jsxs)("div",{className:"mt-8 rounded-lg border bg-white p-4 shadow-sm",children:[(0,r.jsxs)("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-4",children:[(0,r.jsx)("h2",{className:"text-lg font-semibold",children:"UAT上线前 Git 操作流"}),(0,r.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,r.jsx)(o.Button,{onClick:()=>M(!1),disabled:m.isRunning,children:m.isRunning?"执行中...":"执行"}),(0,r.jsx)(o.Button,{variant:"outline",onClick:()=>M(!0),disabled:m.isRunning,children:"DRY RUN"}),(0,r.jsx)(o.Button,{variant:"destructive",onClick:U,disabled:!m.isRunning,children:"中断"})]})]}),(0,r.jsxs)("div",{className:"grid gap-4 md:grid-cols-2",children:[(0,r.jsxs)("div",{className:"space-y-2",children:[(0,r.jsx)(l.Label,{htmlFor:"uat-projects",children:"选择项目"}),(0,r.jsx)("select",{id:"uat-projects",multiple:!0,value:g.selectedProjects,onChange:e=>{let s=Array.from(e.target.selectedOptions).map(e=>e.value);p(e=>({...e,selectedProjects:s}))},className:"w-full min-h-[140px] rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",children:0===Object.keys(s.projects).length?(0,r.jsx)("option",{value:"",disabled:!0,children:"暂无可用项目"}):Object.keys(s.projects).map(e=>(0,r.jsx)("option",{value:e,children:e},e))}),(0,r.jsx)("p",{className:"text-xs text-gray-500",children:"按住 Command / Ctrl 可多选"})]}),(0,r.jsxs)("div",{className:"grid gap-4",children:[(0,r.jsxs)("div",{className:"space-y-2",children:[(0,r.jsx)(l.Label,{htmlFor:"uat-create-branch",children:"创建分支名"}),(0,r.jsx)(c.Input,{id:"uat-create-branch",value:g.createBranch,onChange:e=>_("createBranch",e.target.value),placeholder:"例如: release/uat-2026-01"})]}),(0,r.jsxs)("div",{className:"space-y-2",children:[(0,r.jsx)(l.Label,{htmlFor:"uat-base-branch",children:"从 origin 哪个分支创建"}),(0,r.jsx)(c.Input,{id:"uat-base-branch",value:g.baseBranch,onChange:e=>_("baseBranch",e.target.value),placeholder:"例如: develop"})]}),(0,r.jsxs)("div",{className:"space-y-2",children:[(0,r.jsx)(l.Label,{htmlFor:"uat-merge-branch",children:"被合并分支名称"}),(0,r.jsx)(c.Input,{id:"uat-merge-branch",value:g.mergeBranch,onChange:e=>_("mergeBranch",e.target.value),placeholder:"例如: release/candidate"})]})]})]}),(0,r.jsxs)("div",{className:"mt-6 grid gap-4 md:grid-cols-2",children:[(0,r.jsxs)("div",{className:"rounded-lg border p-3",children:[(0,r.jsx)("h3",{className:"text-sm font-semibold mb-2",children:"操作记录"}),0===m.operationLogs.length?(0,r.jsx)("p",{className:"text-xs text-gray-500",children:"暂无记录"}):(0,r.jsx)("div",{className:"bg-black text-white rounded text-xs font-mono p-2 max-h-48 overflow-y-auto",children:m.operationLogs.map((e,s)=>(0,r.jsx)("div",{className:"mb-1 whitespace-pre-wrap",children:e},s))})]}),(0,r.jsxs)("div",{className:"rounded-lg border p-3",children:[(0,r.jsx)("h3",{className:"text-sm font-semibold mb-2",children:"反馈信息"}),0===m.feedbacks.length?(0,r.jsx)("p",{className:"text-xs text-gray-500",children:"暂无反馈"}):(0,r.jsx)("div",{className:"space-y-1 text-sm",children:m.feedbacks.map((e,s)=>(0,r.jsx)("div",{className:"rounded bg-gray-50 px-2 py-1 text-gray-700",children:e},s))})]})]})]}),(0,r.jsx)(d.Dialog,{open:!1,onOpenChange:e=>{!e&&b&&m.isRunning||N(e)},children:(0,r.jsxs)(d.DialogContent,{showCloseButton:!1,children:[(0,r.jsxs)(d.DialogHeader,{children:[(0,r.jsx)(d.DialogTitle,{children:"确认执行下一步"}),(0,r.jsx)(d.DialogDescription,{children:b?`${b.projectName} \xb7 ${b.description}`:"准备下一步执行"})]}),(0,r.jsx)("div",{className:"rounded-md border bg-gray-50 p-3 text-sm font-mono text-gray-700",children:b?b.command:""}),(0,r.jsxs)(d.DialogFooter,{children:[(0,r.jsx)(o.Button,{variant:"outline",onClick:U,children:"取消执行"}),(0,r.jsx)(o.Button,{onClick:G,disabled:!b,children:"确认并执行"})]})]})}),(0,r.jsx)(d.Dialog,{open:j&&v,onOpenChange:C,children:(0,r.jsxs)(d.DialogContent,{children:[(0,r.jsxs)(d.DialogHeader,{children:[(0,r.jsx)(d.DialogTitle,{children:"操作结果"}),(0,r.jsx)(d.DialogDescription,{children:"查看所有项目执行结果"})]}),(0,r.jsx)("div",{className:"space-y-2",children:0===S.length?(0,r.jsx)("p",{className:"text-sm text-gray-500",children:"暂无结果"}):S.map(e=>(0,r.jsxs)("div",{className:`rounded-md border px-3 py-2 text-sm ${e.success?"bg-green-50 text-green-700":"bg-red-50 text-red-700"}`,children:[(0,r.jsxs)("div",{className:"flex items-start justify-between",children:[(0,r.jsx)("span",{className:"font-medium",children:e.projectName}),(0,r.jsx)("span",{className:"ml-4 text-right",children:e.success?"成功":e.reason||"失败"})]}),!e.success&&e.rollbackActions&&e.rollbackActions.length>0&&(0,r.jsxs)("div",{className:"mt-2 text-xs text-gray-600",children:[(0,r.jsx)("div",{className:"font-semibold text-gray-700",children:"已回滚操作:"}),(0,r.jsx)("ul",{className:"mt-1 list-disc pl-4",children:e.rollbackActions.map((s,t)=>(0,r.jsx)("li",{children:s},`${e.projectName}-rollback-${t}`))})]})]},e.projectName))}),(0,r.jsx)(d.DialogFooter,{children:(0,r.jsx)(o.Button,{onClick:()=>C(!1),children:"关闭"})})]})})]})}}}}]);
2
-
3
- //# sourceMappingURL=99154153690ad580.js.map