yg-team-cli 2.1.1 → 2.1.2
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.
- package/dist/cli.js +144 -125
- package/dist/cli.js.map +1 -1
- package/dist/index.js +144 -125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -420,7 +420,7 @@ __export(user_config_exports, {
|
|
|
420
420
|
UserConfigManager: () => UserConfigManager,
|
|
421
421
|
userConfigManager: () => userConfigManager
|
|
422
422
|
});
|
|
423
|
-
import
|
|
423
|
+
import path5 from "path";
|
|
424
424
|
import os from "os";
|
|
425
425
|
import crypto from "crypto";
|
|
426
426
|
var UserConfigManager, userConfigManager;
|
|
@@ -433,8 +433,8 @@ var init_user_config = __esm({
|
|
|
433
433
|
UserConfigManager = class {
|
|
434
434
|
configPath;
|
|
435
435
|
constructor() {
|
|
436
|
-
const configDir =
|
|
437
|
-
this.configPath =
|
|
436
|
+
const configDir = path5.join(os.homedir(), ".team-cli");
|
|
437
|
+
this.configPath = path5.join(configDir, "config.json");
|
|
438
438
|
}
|
|
439
439
|
/**
|
|
440
440
|
* 加载用户配置
|
|
@@ -461,7 +461,7 @@ var init_user_config = __esm({
|
|
|
461
461
|
*/
|
|
462
462
|
async save(config) {
|
|
463
463
|
try {
|
|
464
|
-
const configDir =
|
|
464
|
+
const configDir = path5.dirname(this.configPath);
|
|
465
465
|
await FileUtils.ensureDir(configDir);
|
|
466
466
|
const configToSave = { ...config };
|
|
467
467
|
if (configToSave.gitlab?.accessToken) {
|
|
@@ -567,7 +567,7 @@ var init_user_config = __esm({
|
|
|
567
567
|
* 获取配置目录
|
|
568
568
|
*/
|
|
569
569
|
getConfigDir() {
|
|
570
|
-
return
|
|
570
|
+
return path5.dirname(this.configPath);
|
|
571
571
|
}
|
|
572
572
|
/**
|
|
573
573
|
* 获取配置文件路径
|
|
@@ -782,15 +782,15 @@ var init_gitlab_api = __esm({
|
|
|
782
782
|
* 从 Git URL 中提取项目路径
|
|
783
783
|
*/
|
|
784
784
|
static parseProjectPath(repository) {
|
|
785
|
-
let
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
const parts =
|
|
785
|
+
let path18 = repository;
|
|
786
|
+
path18 = path18.replace(/^https?:\/\//, "");
|
|
787
|
+
path18 = path18.replace(/^git@/, "");
|
|
788
|
+
const parts = path18.split("/");
|
|
789
789
|
if (parts.length > 1) {
|
|
790
|
-
|
|
790
|
+
path18 = parts.slice(1).join("/");
|
|
791
791
|
}
|
|
792
|
-
|
|
793
|
-
return
|
|
792
|
+
path18 = path18.replace(/\.git$/, "");
|
|
793
|
+
return path18;
|
|
794
794
|
}
|
|
795
795
|
/**
|
|
796
796
|
* 编码项目路径用于 API 请求
|
|
@@ -852,7 +852,7 @@ init_esm_shims();
|
|
|
852
852
|
init_logger();
|
|
853
853
|
import { Command } from "commander";
|
|
854
854
|
import inquirer from "inquirer";
|
|
855
|
-
import
|
|
855
|
+
import path6 from "path";
|
|
856
856
|
import fs2 from "fs-extra";
|
|
857
857
|
|
|
858
858
|
// src/lib/claude.ts
|
|
@@ -860,6 +860,7 @@ init_esm_shims();
|
|
|
860
860
|
init_logger();
|
|
861
861
|
init_utils();
|
|
862
862
|
import { execa } from "execa";
|
|
863
|
+
import path3 from "path";
|
|
863
864
|
var ClaudeAI = class {
|
|
864
865
|
verbose;
|
|
865
866
|
constructor(verbose = false) {
|
|
@@ -893,7 +894,7 @@ var ClaudeAI = class {
|
|
|
893
894
|
async prompt(promptText, options) {
|
|
894
895
|
const spinner = logger.startLoading("\u6B63\u5728\u8C03\u7528 Claude...");
|
|
895
896
|
try {
|
|
896
|
-
|
|
897
|
+
let finalPrompt = promptText;
|
|
897
898
|
const validContextFiles = [];
|
|
898
899
|
if (options?.contextFiles && options.contextFiles.length > 0) {
|
|
899
900
|
for (const file of options.contextFiles) {
|
|
@@ -904,11 +905,29 @@ var ClaudeAI = class {
|
|
|
904
905
|
logger.warn(`\u4E0A\u4E0B\u6587\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u5DF2\u8DF3\u8FC7: ${file}`);
|
|
905
906
|
}
|
|
906
907
|
}
|
|
907
|
-
|
|
908
|
-
|
|
908
|
+
if (validContextFiles.length > 0) {
|
|
909
|
+
const contextParts = [];
|
|
910
|
+
for (const file of validContextFiles) {
|
|
911
|
+
try {
|
|
912
|
+
const content = await FileUtils.read(file);
|
|
913
|
+
const fileName = path3.basename(file);
|
|
914
|
+
contextParts.push(`## Context from ${fileName}
|
|
915
|
+
|
|
916
|
+
${content}`);
|
|
917
|
+
} catch (error) {
|
|
918
|
+
logger.warn(`\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 ${file}\uFF0C\u5DF2\u8DF3\u8FC7`);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
if (contextParts.length > 0) {
|
|
922
|
+
finalPrompt = `${contextParts.join("\n\n---\n\n")}
|
|
923
|
+
|
|
924
|
+
---
|
|
925
|
+
|
|
926
|
+
${promptText}`;
|
|
927
|
+
}
|
|
909
928
|
}
|
|
910
929
|
}
|
|
911
|
-
args
|
|
930
|
+
const args = ["--no-confirm", "-p", finalPrompt];
|
|
912
931
|
const result = await execa("claude", args, {
|
|
913
932
|
stdio: this.verbose ? "inherit" : "pipe",
|
|
914
933
|
timeout: options?.timeout || 3e5,
|
|
@@ -1185,7 +1204,7 @@ init_esm_shims();
|
|
|
1185
1204
|
init_utils();
|
|
1186
1205
|
init_logger();
|
|
1187
1206
|
import { execa as execa2 } from "execa";
|
|
1188
|
-
import
|
|
1207
|
+
import path4 from "path";
|
|
1189
1208
|
var DEFAULT_TEMPLATES = {
|
|
1190
1209
|
frontend: {
|
|
1191
1210
|
repository: "https://gitlab.yungu-inc.org/static/fe-tpl-ai"
|
|
@@ -1195,7 +1214,7 @@ var DEFAULT_TEMPLATES = {
|
|
|
1195
1214
|
}
|
|
1196
1215
|
};
|
|
1197
1216
|
function getConfigPath(projectPath) {
|
|
1198
|
-
return
|
|
1217
|
+
return path4.join(projectPath, ".team-cli", "template.json");
|
|
1199
1218
|
}
|
|
1200
1219
|
async function readTemplateConfig(projectPath) {
|
|
1201
1220
|
const configPath = getConfigPath(projectPath);
|
|
@@ -1211,7 +1230,7 @@ async function readTemplateConfig(projectPath) {
|
|
|
1211
1230
|
}
|
|
1212
1231
|
}
|
|
1213
1232
|
async function saveTemplateConfig(projectPath, config) {
|
|
1214
|
-
const configDir =
|
|
1233
|
+
const configDir = path4.join(projectPath, ".team-cli");
|
|
1215
1234
|
await FileUtils.ensureDir(configDir);
|
|
1216
1235
|
const configPath = getConfigPath(projectPath);
|
|
1217
1236
|
const content = JSON.stringify(config, null, 2);
|
|
@@ -1335,7 +1354,7 @@ var initCommand = new Command("init").argument("[project-name]", "\u9879\u76EE\u
|
|
|
1335
1354
|
logger.info("\u8BF7\u5B89\u88C5 Claude CLI: npm install -g @anthropic-ai/claude-code");
|
|
1336
1355
|
process.exit(1);
|
|
1337
1356
|
}
|
|
1338
|
-
const projectPath =
|
|
1357
|
+
const projectPath = path6.resolve(options.dir, projectName);
|
|
1339
1358
|
if (await FileUtils.exists(projectPath)) {
|
|
1340
1359
|
logger.error(`\u76EE\u5F55\u5DF2\u5B58\u5728: ${projectPath}`);
|
|
1341
1360
|
logger.info("\u8BF7\u9009\u62E9\u5176\u4ED6\u9879\u76EE\u540D\u79F0\u6216\u5220\u9664\u73B0\u6709\u76EE\u5F55");
|
|
@@ -1354,11 +1373,11 @@ var initCommand = new Command("init").argument("[project-name]", "\u9879\u76EE\u
|
|
|
1354
1373
|
title: "\u521B\u5EFA\u9879\u76EE\u76EE\u5F55",
|
|
1355
1374
|
task: async () => {
|
|
1356
1375
|
await FileUtils.ensureDir(projectPath);
|
|
1357
|
-
await FileUtils.ensureDir(
|
|
1358
|
-
await FileUtils.ensureDir(
|
|
1359
|
-
await FileUtils.ensureDir(
|
|
1360
|
-
await FileUtils.ensureDir(
|
|
1361
|
-
await FileUtils.ensureDir(
|
|
1376
|
+
await FileUtils.ensureDir(path6.join(projectPath, "frontend"));
|
|
1377
|
+
await FileUtils.ensureDir(path6.join(projectPath, "backend"));
|
|
1378
|
+
await FileUtils.ensureDir(path6.join(projectPath, "docs/specs"));
|
|
1379
|
+
await FileUtils.ensureDir(path6.join(projectPath, "docs/api"));
|
|
1380
|
+
await FileUtils.ensureDir(path6.join(projectPath, "docs/sessions"));
|
|
1362
1381
|
}
|
|
1363
1382
|
},
|
|
1364
1383
|
{
|
|
@@ -1538,7 +1557,7 @@ docs/
|
|
|
1538
1557
|
\u2514\u2500\u2500 sessions/ # \u5F00\u53D1\u4F1A\u8BDD\u8BB0\u5F55
|
|
1539
1558
|
\`\`\`
|
|
1540
1559
|
`;
|
|
1541
|
-
await FileUtils.write(
|
|
1560
|
+
await FileUtils.write(path6.join(projectPath, "TECH_STACK.md"), content);
|
|
1542
1561
|
}
|
|
1543
1562
|
async function generateConventions(projectPath) {
|
|
1544
1563
|
const content = `# \u5F00\u53D1\u89C4\u8303
|
|
@@ -1841,7 +1860,7 @@ test('renders user name', () => {
|
|
|
1841
1860
|
});
|
|
1842
1861
|
\`\`\`
|
|
1843
1862
|
`;
|
|
1844
|
-
await FileUtils.write(
|
|
1863
|
+
await FileUtils.write(path6.join(projectPath, "CONVENTIONS.md"), content);
|
|
1845
1864
|
}
|
|
1846
1865
|
async function generateAIMemory(projectPath, projectName) {
|
|
1847
1866
|
const content = `# AI Memory - \u9879\u76EE\u72B6\u6001\u8BB0\u5F55
|
|
@@ -1900,7 +1919,7 @@ async function generateAIMemory(projectPath, projectName) {
|
|
|
1900
1919
|
| Bug ID | \u65E5\u671F | \u95EE\u9898\u63CF\u8FF0 | \u72B6\u6001 |
|
|
1901
1920
|
|--------|------|---------|------|
|
|
1902
1921
|
`;
|
|
1903
|
-
await FileUtils.write(
|
|
1922
|
+
await FileUtils.write(path6.join(projectPath, "AI_MEMORY.md"), content);
|
|
1904
1923
|
}
|
|
1905
1924
|
async function generateSpecTemplate(projectPath) {
|
|
1906
1925
|
const content = `# [\u529F\u80FD\u6807\u9898]
|
|
@@ -1964,14 +1983,14 @@ async function generateSpecTemplate(projectPath) {
|
|
|
1964
1983
|
----
|
|
1965
1984
|
*\u751F\u6210\u4E8E: {{TIMESTAMP}} by team-cli*
|
|
1966
1985
|
`;
|
|
1967
|
-
await FileUtils.write(
|
|
1986
|
+
await FileUtils.write(path6.join(projectPath, "docs/specs/template.md"), content);
|
|
1968
1987
|
}
|
|
1969
1988
|
async function cloneBackendTemplate(projectPath, versionOptions) {
|
|
1970
1989
|
const templateRepo = process.env.TEMPLATE_REPO || "git@gitlab.yungu-inc.org:yungu-app/java-scaffold-template.git";
|
|
1971
|
-
const backendPath =
|
|
1990
|
+
const backendPath = path6.join(projectPath, "backend");
|
|
1972
1991
|
try {
|
|
1973
1992
|
const { execaCommand } = await import("execa");
|
|
1974
|
-
const tempDir =
|
|
1993
|
+
const tempDir = path6.join(projectPath, ".template-temp");
|
|
1975
1994
|
if (versionOptions?.tag || versionOptions?.branch) {
|
|
1976
1995
|
const { userConfigManager: userConfigManager2 } = await Promise.resolve().then(() => (init_user_config(), user_config_exports));
|
|
1977
1996
|
const { GitLabAPI: GitLabAPI2 } = await Promise.resolve().then(() => (init_gitlab_api(), gitlab_api_exports));
|
|
@@ -2018,7 +2037,7 @@ async function cloneBackendTemplate(projectPath, versionOptions) {
|
|
|
2018
2037
|
filter: (src) => !src.includes(".git")
|
|
2019
2038
|
});
|
|
2020
2039
|
await fs2.remove(tempDir);
|
|
2021
|
-
const gitDir =
|
|
2040
|
+
const gitDir = path6.join(backendPath, ".git");
|
|
2022
2041
|
if (await FileUtils.exists(gitDir)) {
|
|
2023
2042
|
await FileUtils.remove(gitDir);
|
|
2024
2043
|
}
|
|
@@ -2029,13 +2048,13 @@ async function cloneBackendTemplate(projectPath, versionOptions) {
|
|
|
2029
2048
|
});
|
|
2030
2049
|
} catch (error) {
|
|
2031
2050
|
logger.warn("\u514B\u9686\u540E\u7AEF\u6A21\u677F\u5931\u8D25\uFF0C\u521B\u5EFA\u57FA\u7840\u7ED3\u6784");
|
|
2032
|
-
await FileUtils.ensureDir(
|
|
2033
|
-
await FileUtils.ensureDir(
|
|
2034
|
-
await FileUtils.ensureDir(
|
|
2051
|
+
await FileUtils.ensureDir(path6.join(backendPath, "src/main/java/com/example"));
|
|
2052
|
+
await FileUtils.ensureDir(path6.join(backendPath, "src/main/resources"));
|
|
2053
|
+
await FileUtils.ensureDir(path6.join(backendPath, "src/test/java"));
|
|
2035
2054
|
}
|
|
2036
2055
|
}
|
|
2037
2056
|
async function generateFrontendScaffold(projectPath) {
|
|
2038
|
-
const frontendPath =
|
|
2057
|
+
const frontendPath = path6.join(projectPath, "frontend");
|
|
2039
2058
|
try {
|
|
2040
2059
|
const prompt = `Read TECH_STACK.md and CONVENTIONS.md.
|
|
2041
2060
|
Initialize a Next.js 14 frontend in ./frontend with:
|
|
@@ -2048,16 +2067,16 @@ Initialize a Next.js 14 frontend in ./frontend with:
|
|
|
2048
2067
|
Do not run any servers, just generate the folder structure and configuration files.`;
|
|
2049
2068
|
await claudeAI.prompt(prompt, {
|
|
2050
2069
|
contextFiles: [
|
|
2051
|
-
|
|
2052
|
-
|
|
2070
|
+
path6.join(projectPath, "TECH_STACK.md"),
|
|
2071
|
+
path6.join(projectPath, "CONVENTIONS.md")
|
|
2053
2072
|
]
|
|
2054
2073
|
});
|
|
2055
2074
|
} catch (error) {
|
|
2056
2075
|
logger.warn("Claude \u751F\u6210\u524D\u7AEF\u5931\u8D25\uFF0C\u5C06\u521B\u5EFA\u57FA\u7840\u7ED3\u6784");
|
|
2057
|
-
await FileUtils.ensureDir(
|
|
2058
|
-
await FileUtils.ensureDir(
|
|
2059
|
-
await FileUtils.ensureDir(
|
|
2060
|
-
await FileUtils.ensureDir(
|
|
2076
|
+
await FileUtils.ensureDir(path6.join(frontendPath, "src/app"));
|
|
2077
|
+
await FileUtils.ensureDir(path6.join(frontendPath, "src/components"));
|
|
2078
|
+
await FileUtils.ensureDir(path6.join(frontendPath, "src/lib"));
|
|
2079
|
+
await FileUtils.ensureDir(path6.join(frontendPath, "public"));
|
|
2061
2080
|
}
|
|
2062
2081
|
}
|
|
2063
2082
|
async function generateDockerFiles(projectPath) {
|
|
@@ -2084,7 +2103,7 @@ init_utils();
|
|
|
2084
2103
|
init_logger();
|
|
2085
2104
|
import { Command as Command2 } from "commander";
|
|
2086
2105
|
import inquirer2 from "inquirer";
|
|
2087
|
-
import
|
|
2106
|
+
import path7 from "path";
|
|
2088
2107
|
import { Listr as Listr2 } from "listr2";
|
|
2089
2108
|
var breakdownCommand = new Command2("breakdown").argument("[spec-file]", "Spec \u6587\u4EF6\u8DEF\u5F84").description("\u5C06 spec \u62C6\u5206\u4E3A milestones \u548C todos").action(async (specFile) => {
|
|
2090
2109
|
try {
|
|
@@ -2130,9 +2149,9 @@ var breakdownCommand = new Command2("breakdown").argument("[spec-file]", "Spec \
|
|
|
2130
2149
|
choices: ctx.specs
|
|
2131
2150
|
}
|
|
2132
2151
|
]);
|
|
2133
|
-
return
|
|
2152
|
+
return path7.join("docs/specs", selectedFile);
|
|
2134
2153
|
}
|
|
2135
|
-
const fullPath = specFile.startsWith("docs/specs/") ? specFile :
|
|
2154
|
+
const fullPath = specFile.startsWith("docs/specs/") ? specFile : path7.join("docs/specs", specFile);
|
|
2136
2155
|
const exists = await FileUtils.exists(fullPath);
|
|
2137
2156
|
if (!exists) {
|
|
2138
2157
|
throw new Error(`Spec \u6587\u4EF6\u4E0D\u5B58\u5728: ${specFile}`);
|
|
@@ -2264,7 +2283,7 @@ init_utils();
|
|
|
2264
2283
|
init_logger();
|
|
2265
2284
|
import { Command as Command3 } from "commander";
|
|
2266
2285
|
import inquirer3 from "inquirer";
|
|
2267
|
-
import
|
|
2286
|
+
import path8 from "path";
|
|
2268
2287
|
var devCommand = new Command3("dev").description("\u5F00\u53D1\u6A21\u5F0F\uFF0C\u6267\u884C\u5177\u4F53\u4EFB\u52A1").action(async () => {
|
|
2269
2288
|
try {
|
|
2270
2289
|
logger.header("\u5F00\u53D1\u6A21\u5F0F");
|
|
@@ -2309,7 +2328,7 @@ async function selectSpec() {
|
|
|
2309
2328
|
}
|
|
2310
2329
|
const specs = [];
|
|
2311
2330
|
for (let i = 0; i < specFiles.length; i++) {
|
|
2312
|
-
const file =
|
|
2331
|
+
const file = path8.join(specDir, specFiles[i]);
|
|
2313
2332
|
const spec = await FileUtils.read(file);
|
|
2314
2333
|
const status = parseSpecStatus(spec);
|
|
2315
2334
|
const dependencies = parseDependencies(spec);
|
|
@@ -2623,8 +2642,8 @@ async function generateSessionLog(specFile, milestone, todo, taskDescription, re
|
|
|
2623
2642
|
const sessionDir = "docs/sessions";
|
|
2624
2643
|
await FileUtils.ensureDir(sessionDir);
|
|
2625
2644
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2626
|
-
const specName =
|
|
2627
|
-
const logFile =
|
|
2645
|
+
const specName = path8.basename(specFile, ".md");
|
|
2646
|
+
const logFile = path8.join(sessionDir, `${timestamp}_${specName}.md`);
|
|
2628
2647
|
const content = `# \u5F00\u53D1\u4F1A\u8BDD\u8BB0\u5F55
|
|
2629
2648
|
|
|
2630
2649
|
**\u65F6\u95F4**: ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN")}
|
|
@@ -2661,7 +2680,7 @@ init_utils();
|
|
|
2661
2680
|
init_logger();
|
|
2662
2681
|
import { Command as Command4 } from "commander";
|
|
2663
2682
|
import inquirer4 from "inquirer";
|
|
2664
|
-
import
|
|
2683
|
+
import path9 from "path";
|
|
2665
2684
|
import { Listr as Listr3 } from "listr2";
|
|
2666
2685
|
var addFeatureCommand = new Command4("add-feature").argument("<feature-name>", "\u529F\u80FD\u540D\u79F0").description("\u6DFB\u52A0\u65B0\u529F\u80FD\uFF08\u652F\u6301 PRD \u6216\u7B80\u5355\u63CF\u8FF0\u6A21\u5F0F\uFF09").action(async (featureName) => {
|
|
2667
2686
|
try {
|
|
@@ -2680,7 +2699,7 @@ var addFeatureCommand = new Command4("add-feature").argument("<feature-name>", "
|
|
|
2680
2699
|
process.exit(1);
|
|
2681
2700
|
}
|
|
2682
2701
|
const featureSlug = StringUtils2.toKebabCase(featureName);
|
|
2683
|
-
const specFile =
|
|
2702
|
+
const specFile = path9.join("docs/specs", `${featureSlug}.md`);
|
|
2684
2703
|
const specExists = await FileUtils.exists(specFile);
|
|
2685
2704
|
if (specExists) {
|
|
2686
2705
|
logger.error(`Spec \u6587\u4EF6\u5DF2\u5B58\u5728: ${specFile}`);
|
|
@@ -2739,7 +2758,7 @@ async function addFeatureFromPrd(featureName, featureSlug, specFile) {
|
|
|
2739
2758
|
const specs = files.filter((f) => !f.includes("template"));
|
|
2740
2759
|
ctx2.completedSpecs = [];
|
|
2741
2760
|
for (const file of specs) {
|
|
2742
|
-
const status = await SpecUtils.getSpecStatus(
|
|
2761
|
+
const status = await SpecUtils.getSpecStatus(path9.join(specDir, file));
|
|
2743
2762
|
if (status === "\u5DF2\u5B8C\u6210") {
|
|
2744
2763
|
ctx2.completedSpecs.push(file.replace(".md", ""));
|
|
2745
2764
|
}
|
|
@@ -2811,7 +2830,7 @@ async function addFeatureSimple(featureName, featureSlug, specFile) {
|
|
|
2811
2830
|
const specs = files.filter((f) => !f.includes("template"));
|
|
2812
2831
|
ctx2.completedSpecs = [];
|
|
2813
2832
|
for (const file of specs) {
|
|
2814
|
-
const status = await SpecUtils.getSpecStatus(
|
|
2833
|
+
const status = await SpecUtils.getSpecStatus(path9.join(specDir, file));
|
|
2815
2834
|
if (status === "\u5DF2\u5B8C\u6210") {
|
|
2816
2835
|
ctx2.completedSpecs.push(file.replace(".md", ""));
|
|
2817
2836
|
}
|
|
@@ -2908,7 +2927,7 @@ async function buildProjectContext() {
|
|
|
2908
2927
|
const files = await FileUtils.findFiles("*.md", "docs/specs");
|
|
2909
2928
|
const specs = files.filter((f) => !f.includes("template"));
|
|
2910
2929
|
for (const file of specs) {
|
|
2911
|
-
const status = await SpecUtils.getSpecStatus(
|
|
2930
|
+
const status = await SpecUtils.getSpecStatus(path9.join("docs/specs", file));
|
|
2912
2931
|
context.push(` - ${file.replace(".md", "")} [${status}]`);
|
|
2913
2932
|
}
|
|
2914
2933
|
}
|
|
@@ -3152,7 +3171,7 @@ init_esm_shims();
|
|
|
3152
3171
|
init_utils();
|
|
3153
3172
|
init_logger();
|
|
3154
3173
|
import { Command as Command5 } from "commander";
|
|
3155
|
-
import
|
|
3174
|
+
import path10 from "path";
|
|
3156
3175
|
import { Listr as Listr4 } from "listr2";
|
|
3157
3176
|
var splitPrdCommand = new Command5("split-prd").argument("<prd-folder>", "PRD \u6587\u6863\u76EE\u5F55").description("\u5C06 PRD \u62C6\u5206\u6210\u591A\u4E2A specs").action(async (prdFolder) => {
|
|
3158
3177
|
try {
|
|
@@ -3182,7 +3201,7 @@ var splitPrdCommand = new Command5("split-prd").argument("<prd-folder>", "PRD \u
|
|
|
3182
3201
|
ctx2.prdFiles = [];
|
|
3183
3202
|
for (const ext of supportedExtensions) {
|
|
3184
3203
|
const files = await FileUtils.findFiles(`*.${ext}`, prdFolder);
|
|
3185
|
-
ctx2.prdFiles.push(...files.map((f) =>
|
|
3204
|
+
ctx2.prdFiles.push(...files.map((f) => path10.join(prdFolder, f)));
|
|
3186
3205
|
}
|
|
3187
3206
|
if (ctx2.prdFiles.length === 0) {
|
|
3188
3207
|
throw new Error(
|
|
@@ -3200,7 +3219,7 @@ var splitPrdCommand = new Command5("split-prd").argument("<prd-folder>", "PRD \u
|
|
|
3200
3219
|
{
|
|
3201
3220
|
title: "\u626B\u63CF\u622A\u56FE\u6587\u4EF6",
|
|
3202
3221
|
task: async (ctx2) => {
|
|
3203
|
-
const screenshotDir =
|
|
3222
|
+
const screenshotDir = path10.join(prdFolder, "screenshots");
|
|
3204
3223
|
const dirExists = await FileUtils.exists(screenshotDir);
|
|
3205
3224
|
if (!dirExists) {
|
|
3206
3225
|
logger.info("\u672A\u627E\u5230 screenshots \u76EE\u5F55\uFF0C\u8DF3\u8FC7\u622A\u56FE");
|
|
@@ -3211,7 +3230,7 @@ var splitPrdCommand = new Command5("split-prd").argument("<prd-folder>", "PRD \u
|
|
|
3211
3230
|
ctx2.screenshots = [];
|
|
3212
3231
|
for (const ext of imageExtensions) {
|
|
3213
3232
|
const files = await FileUtils.findFiles(`*.${ext}`, screenshotDir);
|
|
3214
|
-
ctx2.screenshots.push(...files.map((f) =>
|
|
3233
|
+
ctx2.screenshots.push(...files.map((f) => path10.join(screenshotDir, f)));
|
|
3215
3234
|
}
|
|
3216
3235
|
logger.success(`\u627E\u5230 ${ctx2.screenshots.length} \u4E2A\u622A\u56FE\u6587\u4EF6`);
|
|
3217
3236
|
}
|
|
@@ -3222,8 +3241,8 @@ var splitPrdCommand = new Command5("split-prd").argument("<prd-folder>", "PRD \u
|
|
|
3222
3241
|
const entries = await FileUtils.findFiles("*/", prdFolder);
|
|
3223
3242
|
ctx2.demoRepos = [];
|
|
3224
3243
|
for (const entry of entries) {
|
|
3225
|
-
const dirPath =
|
|
3226
|
-
const gitDir =
|
|
3244
|
+
const dirPath = path10.join(prdFolder, entry);
|
|
3245
|
+
const gitDir = path10.join(dirPath, ".git");
|
|
3227
3246
|
const hasGit = await FileUtils.exists(gitDir);
|
|
3228
3247
|
if (hasGit) {
|
|
3229
3248
|
ctx2.demoRepos.push(dirPath);
|
|
@@ -3396,7 +3415,7 @@ init_utils();
|
|
|
3396
3415
|
init_logger();
|
|
3397
3416
|
import { Command as Command6 } from "commander";
|
|
3398
3417
|
import inquirer5 from "inquirer";
|
|
3399
|
-
import
|
|
3418
|
+
import path11 from "path";
|
|
3400
3419
|
import { Listr as Listr5 } from "listr2";
|
|
3401
3420
|
var bugfixCommand = new Command6("bugfix").description("\u521B\u5EFA Bugfix \u8BB0\u5F55").action(async () => {
|
|
3402
3421
|
try {
|
|
@@ -3445,7 +3464,7 @@ var bugfixCommand = new Command6("bugfix").description("\u521B\u5EFA Bugfix \u8B
|
|
|
3445
3464
|
const relatedSpec = await findRelatedSpec(answers.description);
|
|
3446
3465
|
const bugfixDir = "docs/bugfixes";
|
|
3447
3466
|
await FileUtils.ensureDir(bugfixDir);
|
|
3448
|
-
const bugfixFile =
|
|
3467
|
+
const bugfixFile = path11.join(bugfixDir, `${timestamp}_${bugId}.md`);
|
|
3449
3468
|
const content = formatBugfixDocument({
|
|
3450
3469
|
id: bugId,
|
|
3451
3470
|
severity: answers.severity,
|
|
@@ -3521,7 +3540,7 @@ var hotfixCommand = new Command6("hotfix").description("\u7D27\u6025\u4FEE\u590D
|
|
|
3521
3540
|
const timestamp = DateUtils.format(/* @__PURE__ */ new Date(), "YYYY-MM-DD HH:mm:ss");
|
|
3522
3541
|
const hotfixDir = "docs/hotfixes";
|
|
3523
3542
|
await FileUtils.ensureDir(hotfixDir);
|
|
3524
|
-
const hotfixFile =
|
|
3543
|
+
const hotfixFile = path11.join(hotfixDir, `${timestamp}_${hotfixId}.md`);
|
|
3525
3544
|
const content = formatHotfixDocument({
|
|
3526
3545
|
id: hotfixId,
|
|
3527
3546
|
description: answers.description,
|
|
@@ -3596,7 +3615,7 @@ async function findRelatedSpec(description) {
|
|
|
3596
3615
|
}
|
|
3597
3616
|
const keywords = extractKeywords(description);
|
|
3598
3617
|
for (const file of specs) {
|
|
3599
|
-
const filePath =
|
|
3618
|
+
const filePath = path11.join(specDir, file);
|
|
3600
3619
|
const content = await FileUtils.read(filePath);
|
|
3601
3620
|
for (const keyword of keywords) {
|
|
3602
3621
|
if (content.toLowerCase().includes(keyword.toLowerCase())) {
|
|
@@ -3814,7 +3833,7 @@ init_esm_shims();
|
|
|
3814
3833
|
init_utils();
|
|
3815
3834
|
init_logger();
|
|
3816
3835
|
import { Command as Command8 } from "commander";
|
|
3817
|
-
import
|
|
3836
|
+
import path12 from "path";
|
|
3818
3837
|
var statusCommand = new Command8("status").description("\u67E5\u770B\u9879\u76EE\u72B6\u6001").action(async () => {
|
|
3819
3838
|
try {
|
|
3820
3839
|
logger.header("\u9879\u76EE\u72B6\u6001");
|
|
@@ -3872,7 +3891,7 @@ async function displayFeatureInventory() {
|
|
|
3872
3891
|
}
|
|
3873
3892
|
const inventory = [];
|
|
3874
3893
|
for (const file of specs) {
|
|
3875
|
-
const filePath =
|
|
3894
|
+
const filePath = path12.join(specDir, file);
|
|
3876
3895
|
const content = await FileUtils.read(filePath);
|
|
3877
3896
|
const status = parseSpecStatus2(content);
|
|
3878
3897
|
inventory.push({
|
|
@@ -3931,7 +3950,7 @@ async function displayRecentActivity() {
|
|
|
3931
3950
|
}
|
|
3932
3951
|
const sorted = files.sort().reverse().slice(0, 5);
|
|
3933
3952
|
for (const file of sorted) {
|
|
3934
|
-
const filePath =
|
|
3953
|
+
const filePath = path12.join(sessionDir, file);
|
|
3935
3954
|
const stat = await FileUtils.read(filePath);
|
|
3936
3955
|
const specMatch = stat.match(/\*\*Spec\*\*:\s*(.+)/);
|
|
3937
3956
|
const spec = specMatch ? specMatch[1].trim() : "\u672A\u77E5";
|
|
@@ -3973,7 +3992,7 @@ init_esm_shims();
|
|
|
3973
3992
|
init_utils();
|
|
3974
3993
|
init_logger();
|
|
3975
3994
|
import { Command as Command9 } from "commander";
|
|
3976
|
-
import
|
|
3995
|
+
import path13 from "path";
|
|
3977
3996
|
import inquirer6 from "inquirer";
|
|
3978
3997
|
var detectDepsCommand = new Command9("detect-deps").argument("[spec-file]", "Spec \u6587\u4EF6\u8DEF\u5F84").description("\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB").action(async (specFile) => {
|
|
3979
3998
|
try {
|
|
@@ -4001,7 +4020,7 @@ var detectDepsCommand = new Command9("detect-deps").argument("[spec-file]", "Spe
|
|
|
4001
4020
|
process.exit(1);
|
|
4002
4021
|
}
|
|
4003
4022
|
for (const spec of specs) {
|
|
4004
|
-
const specPath =
|
|
4023
|
+
const specPath = path13.join(specsDir, spec);
|
|
4005
4024
|
logger.step(`\u5904\u7406: ${spec}`);
|
|
4006
4025
|
await detectDependencies(specPath);
|
|
4007
4026
|
logger.newLine();
|
|
@@ -4027,7 +4046,7 @@ async function detectDependencies(specFile) {
|
|
|
4027
4046
|
logger.step("\u81EA\u52A8\u68C0\u6D4B\u4F9D\u8D56\u5173\u7CFB...");
|
|
4028
4047
|
const projectDir = ".";
|
|
4029
4048
|
const allDeps = /* @__PURE__ */ new Set();
|
|
4030
|
-
const backendDir =
|
|
4049
|
+
const backendDir = path13.join(projectDir, "backend");
|
|
4031
4050
|
const backendExists = await FileUtils.exists(backendDir);
|
|
4032
4051
|
if (backendExists) {
|
|
4033
4052
|
const apiDeps = await scanBackendApiCalls(backendDir);
|
|
@@ -4037,7 +4056,7 @@ async function detectDependencies(specFile) {
|
|
|
4037
4056
|
const serviceDeps = await scanBackendServiceRefs(backendDir);
|
|
4038
4057
|
serviceDeps.forEach((d) => allDeps.add(d));
|
|
4039
4058
|
}
|
|
4040
|
-
const frontendDir =
|
|
4059
|
+
const frontendDir = path13.join(projectDir, "frontend");
|
|
4041
4060
|
const frontendExists = await FileUtils.exists(frontendDir);
|
|
4042
4061
|
if (frontendExists) {
|
|
4043
4062
|
const frontendDeps = await scanFrontendApiCalls(frontendDir);
|
|
@@ -4078,11 +4097,11 @@ async function detectDependencies(specFile) {
|
|
|
4078
4097
|
}
|
|
4079
4098
|
async function scanBackendApiCalls(backendDir) {
|
|
4080
4099
|
const deps = [];
|
|
4081
|
-
const srcDir =
|
|
4100
|
+
const srcDir = path13.join(backendDir, "src");
|
|
4082
4101
|
try {
|
|
4083
4102
|
const javaFiles = await FileUtils.findFiles("*.java", srcDir);
|
|
4084
4103
|
for (const file of javaFiles) {
|
|
4085
|
-
const filePath =
|
|
4104
|
+
const filePath = path13.join(srcDir, file);
|
|
4086
4105
|
const content = await FileUtils.read(filePath);
|
|
4087
4106
|
const pathRegex = /"(\/api\/[^"]+)"/g;
|
|
4088
4107
|
let match;
|
|
@@ -4100,11 +4119,11 @@ async function scanBackendApiCalls(backendDir) {
|
|
|
4100
4119
|
}
|
|
4101
4120
|
async function scanBackendEntityRelations(backendDir) {
|
|
4102
4121
|
const deps = [];
|
|
4103
|
-
const srcDir =
|
|
4122
|
+
const srcDir = path13.join(backendDir, "src");
|
|
4104
4123
|
try {
|
|
4105
4124
|
const javaFiles = await FileUtils.findFiles("*.java", srcDir);
|
|
4106
4125
|
for (const file of javaFiles) {
|
|
4107
|
-
const filePath =
|
|
4126
|
+
const filePath = path13.join(srcDir, file);
|
|
4108
4127
|
const content = await FileUtils.read(filePath);
|
|
4109
4128
|
if (content.includes("@JoinColumn") || content.includes("@ManyToOne") || content.includes("@OneToMany")) {
|
|
4110
4129
|
const typeRegex = /type\s*=\s*(\w+)/g;
|
|
@@ -4120,11 +4139,11 @@ async function scanBackendEntityRelations(backendDir) {
|
|
|
4120
4139
|
}
|
|
4121
4140
|
async function scanBackendServiceRefs(backendDir) {
|
|
4122
4141
|
const deps = [];
|
|
4123
|
-
const srcDir =
|
|
4142
|
+
const srcDir = path13.join(backendDir, "src");
|
|
4124
4143
|
try {
|
|
4125
4144
|
const javaFiles = await FileUtils.findFiles("*.java", srcDir);
|
|
4126
4145
|
for (const file of javaFiles) {
|
|
4127
|
-
const filePath =
|
|
4146
|
+
const filePath = path13.join(srcDir, file);
|
|
4128
4147
|
const content = await FileUtils.read(filePath);
|
|
4129
4148
|
const serviceRegex = /private\s+(\w+)Service/g;
|
|
4130
4149
|
let match;
|
|
@@ -4140,11 +4159,11 @@ async function scanBackendServiceRefs(backendDir) {
|
|
|
4140
4159
|
}
|
|
4141
4160
|
async function scanFrontendApiCalls(frontendDir) {
|
|
4142
4161
|
const deps = [];
|
|
4143
|
-
const srcDir =
|
|
4162
|
+
const srcDir = path13.join(frontendDir, "src");
|
|
4144
4163
|
try {
|
|
4145
4164
|
const tsFiles = await FileUtils.findFiles("*.{ts,tsx,js,jsx}", srcDir);
|
|
4146
4165
|
for (const file of tsFiles) {
|
|
4147
|
-
const filePath =
|
|
4166
|
+
const filePath = path13.join(srcDir, file);
|
|
4148
4167
|
const content = await FileUtils.read(filePath);
|
|
4149
4168
|
const pathRegex = /"(\/api\/[^"]+)"/g;
|
|
4150
4169
|
let match;
|
|
@@ -4234,7 +4253,7 @@ init_esm_shims();
|
|
|
4234
4253
|
init_utils();
|
|
4235
4254
|
init_logger();
|
|
4236
4255
|
import { Command as Command10 } from "commander";
|
|
4237
|
-
import
|
|
4256
|
+
import path14 from "path";
|
|
4238
4257
|
var syncMemoryCommand = new Command10("sync-memory").description("\u540C\u6B65 AI_MEMORY.md").action(async () => {
|
|
4239
4258
|
try {
|
|
4240
4259
|
logger.header("\u540C\u6B65 AI_MEMORY.md");
|
|
@@ -4267,7 +4286,7 @@ var syncMemoryCommand = new Command10("sync-memory").description("\u540C\u6B65 A
|
|
|
4267
4286
|
});
|
|
4268
4287
|
async function syncFeatureInventory(aiMemoryFile, projectDir) {
|
|
4269
4288
|
logger.step("\u540C\u6B65\u529F\u80FD\u6E05\u5355...");
|
|
4270
|
-
const specsDir =
|
|
4289
|
+
const specsDir = path14.join(projectDir, "docs/specs");
|
|
4271
4290
|
const exists = await FileUtils.exists(specsDir);
|
|
4272
4291
|
if (!exists) {
|
|
4273
4292
|
return;
|
|
@@ -4282,7 +4301,7 @@ async function syncFeatureInventory(aiMemoryFile, projectDir) {
|
|
|
4282
4301
|
for (const specFile of specs) {
|
|
4283
4302
|
const name = specFile.replace(".md", "");
|
|
4284
4303
|
const displayName = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
4285
|
-
const specPath =
|
|
4304
|
+
const specPath = path14.join(specsDir, specFile);
|
|
4286
4305
|
const content = await FileUtils.read(specPath);
|
|
4287
4306
|
const status = parseSpecStatus3(content);
|
|
4288
4307
|
const progress = getSpecProgress(content);
|
|
@@ -4300,7 +4319,7 @@ async function syncFeatureInventory(aiMemoryFile, projectDir) {
|
|
|
4300
4319
|
}
|
|
4301
4320
|
async function syncApiInventory(aiMemoryFile, projectDir) {
|
|
4302
4321
|
logger.step("\u540C\u6B65 API \u5217\u8868...");
|
|
4303
|
-
const backendDir =
|
|
4322
|
+
const backendDir = path14.join(projectDir, "backend");
|
|
4304
4323
|
const exists = await FileUtils.exists(backendDir);
|
|
4305
4324
|
if (!exists) {
|
|
4306
4325
|
return;
|
|
@@ -4310,13 +4329,13 @@ async function syncApiInventory(aiMemoryFile, projectDir) {
|
|
|
4310
4329
|
lines.push("");
|
|
4311
4330
|
lines.push("> \u672C\u90E8\u5206\u7531 team-cli \u81EA\u52A8\u626B\u63CF\u540E\u7AEF Controller \u751F\u6210");
|
|
4312
4331
|
lines.push("");
|
|
4313
|
-
const srcDir =
|
|
4332
|
+
const srcDir = path14.join(backendDir, "src");
|
|
4314
4333
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4315
4334
|
if (controllers.length === 0) {
|
|
4316
4335
|
lines.push("\u6682\u65E0 API");
|
|
4317
4336
|
} else {
|
|
4318
4337
|
for (const controllerFile of controllers) {
|
|
4319
|
-
const controllerPath =
|
|
4338
|
+
const controllerPath = path14.join(srcDir, controllerFile);
|
|
4320
4339
|
const controllerName = controllerFile.replace(".java", "");
|
|
4321
4340
|
const module = controllerName.replace(/Controller$/, "").toLowerCase();
|
|
4322
4341
|
lines.push(`### ${module} \u6A21\u5757`);
|
|
@@ -4393,7 +4412,7 @@ function extractMethodComment(content, methodName) {
|
|
|
4393
4412
|
}
|
|
4394
4413
|
async function syncDataModels(aiMemoryFile, projectDir) {
|
|
4395
4414
|
logger.step("\u540C\u6B65\u6570\u636E\u6A21\u578B...");
|
|
4396
|
-
const backendDir =
|
|
4415
|
+
const backendDir = path14.join(projectDir, "backend");
|
|
4397
4416
|
const exists = await FileUtils.exists(backendDir);
|
|
4398
4417
|
if (!exists) {
|
|
4399
4418
|
return;
|
|
@@ -4403,7 +4422,7 @@ async function syncDataModels(aiMemoryFile, projectDir) {
|
|
|
4403
4422
|
lines.push("");
|
|
4404
4423
|
lines.push("> \u672C\u90E8\u5206\u7531 team-cli \u81EA\u52A8\u626B\u63CF\u540E\u7AEF Entity \u751F\u6210");
|
|
4405
4424
|
lines.push("");
|
|
4406
|
-
const srcDir =
|
|
4425
|
+
const srcDir = path14.join(backendDir, "src");
|
|
4407
4426
|
const entities = await FileUtils.findFiles("*Entity.java", srcDir);
|
|
4408
4427
|
if (entities.length === 0) {
|
|
4409
4428
|
lines.push("\u6682\u65E0\u6570\u636E\u6A21\u578B");
|
|
@@ -4411,7 +4430,7 @@ async function syncDataModels(aiMemoryFile, projectDir) {
|
|
|
4411
4430
|
lines.push("| \u6A21\u578B | \u8BF4\u660E | \u5B57\u6BB5 | \u5173\u8054 |");
|
|
4412
4431
|
lines.push("|------|------|------|------|");
|
|
4413
4432
|
for (const entityFile of entities) {
|
|
4414
|
-
const entityPath =
|
|
4433
|
+
const entityPath = path14.join(srcDir, entityFile);
|
|
4415
4434
|
const entityName = entityFile.replace(".java", "").replace(/Entity$/, "");
|
|
4416
4435
|
const displayName = entityName.split(/(?=[A-Z])/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
4417
4436
|
const content = await FileUtils.read(entityPath);
|
|
@@ -4533,15 +4552,15 @@ async function syncTemplateVersions(aiMemoryFile, projectDir) {
|
|
|
4533
4552
|
await replaceOrInsertSection(aiMemoryFile, "## \u6A21\u677F\u7248\u672C\u4FE1\u606F", newContent);
|
|
4534
4553
|
}
|
|
4535
4554
|
function extractRepoName(repository) {
|
|
4536
|
-
let
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
const parts =
|
|
4555
|
+
let path18 = repository;
|
|
4556
|
+
path18 = path18.replace(/^https?:\/\//, "");
|
|
4557
|
+
path18 = path18.replace(/^git@/, "");
|
|
4558
|
+
const parts = path18.split("/");
|
|
4540
4559
|
if (parts.length > 1) {
|
|
4541
|
-
|
|
4560
|
+
path18 = parts.slice(1).join("/");
|
|
4542
4561
|
}
|
|
4543
|
-
|
|
4544
|
-
return
|
|
4562
|
+
path18 = path18.replace(/\.git$/, "");
|
|
4563
|
+
return path18;
|
|
4545
4564
|
}
|
|
4546
4565
|
|
|
4547
4566
|
// src/commands/check-api.ts
|
|
@@ -4549,7 +4568,7 @@ init_esm_shims();
|
|
|
4549
4568
|
init_utils();
|
|
4550
4569
|
init_logger();
|
|
4551
4570
|
import { Command as Command11 } from "commander";
|
|
4552
|
-
import
|
|
4571
|
+
import path15 from "path";
|
|
4553
4572
|
import inquirer7 from "inquirer";
|
|
4554
4573
|
import { Listr as Listr6 } from "listr2";
|
|
4555
4574
|
var checkApiCommand = new Command11("check-api").description("API \u68C0\u67E5\uFF08\u51B2\u7A81/\u53D8\u66F4/Registry\uFF09").action(async () => {
|
|
@@ -4613,7 +4632,7 @@ var checkApiCommand = new Command11("check-api").description("API \u68C0\u67E5\u
|
|
|
4613
4632
|
}
|
|
4614
4633
|
});
|
|
4615
4634
|
async function checkApiConflicts(projectDir) {
|
|
4616
|
-
const backendDir =
|
|
4635
|
+
const backendDir = path15.join(projectDir, "backend");
|
|
4617
4636
|
const exists = await FileUtils.exists(backendDir);
|
|
4618
4637
|
if (!exists) {
|
|
4619
4638
|
logger.info("\u672A\u627E\u5230\u540E\u7AEF\u9879\u76EE");
|
|
@@ -4622,10 +4641,10 @@ async function checkApiConflicts(projectDir) {
|
|
|
4622
4641
|
logger.step("\u626B\u63CF\u540E\u7AEF API...");
|
|
4623
4642
|
logger.newLine();
|
|
4624
4643
|
const apiMap = /* @__PURE__ */ new Map();
|
|
4625
|
-
const srcDir =
|
|
4644
|
+
const srcDir = path15.join(backendDir, "src");
|
|
4626
4645
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4627
4646
|
for (const controllerFile of controllers) {
|
|
4628
|
-
const controllerPath =
|
|
4647
|
+
const controllerPath = path15.join(srcDir, controllerFile);
|
|
4629
4648
|
const apis = await extractApisFromController(controllerPath);
|
|
4630
4649
|
for (const api of apis) {
|
|
4631
4650
|
const key = `${api.method}:${api.path}`;
|
|
@@ -4656,8 +4675,8 @@ async function checkApiConflicts(projectDir) {
|
|
|
4656
4675
|
}
|
|
4657
4676
|
}
|
|
4658
4677
|
async function detectApiChanges(projectDir) {
|
|
4659
|
-
const backendDir =
|
|
4660
|
-
const registryFile =
|
|
4678
|
+
const backendDir = path15.join(projectDir, "backend");
|
|
4679
|
+
const registryFile = path15.join(projectDir, "docs/api-registry.md");
|
|
4661
4680
|
const registryExists = await FileUtils.exists(registryFile);
|
|
4662
4681
|
if (!registryExists) {
|
|
4663
4682
|
logger.info("API Registry \u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u53D8\u66F4\u68C0\u6D4B");
|
|
@@ -4669,10 +4688,10 @@ async function detectApiChanges(projectDir) {
|
|
|
4669
4688
|
const registryContent = await FileUtils.read(registryFile);
|
|
4670
4689
|
const existingApis = extractApisFromRegistry(registryContent);
|
|
4671
4690
|
const currentApis = /* @__PURE__ */ new Map();
|
|
4672
|
-
const srcDir =
|
|
4691
|
+
const srcDir = path15.join(backendDir, "src");
|
|
4673
4692
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4674
4693
|
for (const controllerFile of controllers) {
|
|
4675
|
-
const controllerPath =
|
|
4694
|
+
const controllerPath = path15.join(srcDir, controllerFile);
|
|
4676
4695
|
const apis = await extractApisFromController(controllerPath);
|
|
4677
4696
|
for (const api of apis) {
|
|
4678
4697
|
const key = `${api.method}:${api.path}`;
|
|
@@ -4734,9 +4753,9 @@ async function detectApiChanges(projectDir) {
|
|
|
4734
4753
|
}
|
|
4735
4754
|
}
|
|
4736
4755
|
async function generateApiRegistry(projectDir) {
|
|
4737
|
-
const registryFile =
|
|
4756
|
+
const registryFile = path15.join(projectDir, "docs/api-registry.md");
|
|
4738
4757
|
logger.step("\u626B\u63CF\u5E76\u751F\u6210 API Registry...");
|
|
4739
|
-
await FileUtils.ensureDir(
|
|
4758
|
+
await FileUtils.ensureDir(path15.dirname(registryFile));
|
|
4740
4759
|
const header = `# API Registry
|
|
4741
4760
|
|
|
4742
4761
|
> \u672C\u6587\u4EF6\u8BB0\u5F55\u6240\u6709 API \u7684\u5B9A\u4E49\u3001\u7248\u672C\u548C\u53D8\u66F4\u5386\u53F2
|
|
@@ -4765,14 +4784,14 @@ async function generateApiRegistry(projectDir) {
|
|
|
4765
4784
|
*\u6700\u540E\u66F4\u65B0: ${DateUtils.format(/* @__PURE__ */ new Date(), "YYYY-MM-DD HH:mm:ss")}*
|
|
4766
4785
|
`;
|
|
4767
4786
|
let content = header;
|
|
4768
|
-
const backendDir =
|
|
4787
|
+
const backendDir = path15.join(projectDir, "backend");
|
|
4769
4788
|
const exists = await FileUtils.exists(backendDir);
|
|
4770
4789
|
if (exists) {
|
|
4771
|
-
const srcDir =
|
|
4790
|
+
const srcDir = path15.join(backendDir, "src");
|
|
4772
4791
|
const controllers = await FileUtils.findFiles("*Controller.java", srcDir);
|
|
4773
4792
|
const moduleMap = /* @__PURE__ */ new Map();
|
|
4774
4793
|
for (const controllerFile of controllers) {
|
|
4775
|
-
const controllerPath =
|
|
4794
|
+
const controllerPath = path15.join(srcDir, controllerFile);
|
|
4776
4795
|
const controllerName = controllerFile.replace(".java", "");
|
|
4777
4796
|
const module = controllerName.replace(/Controller$/, "").toLowerCase();
|
|
4778
4797
|
if (!moduleMap.has(module)) {
|
|
@@ -4856,10 +4875,10 @@ function extractApisFromRegistry(registryContent) {
|
|
|
4856
4875
|
let match;
|
|
4857
4876
|
while ((match = apiRegex.exec(registryContent)) !== null) {
|
|
4858
4877
|
const method = match[1];
|
|
4859
|
-
const
|
|
4878
|
+
const path18 = match[2].trim();
|
|
4860
4879
|
const description = match[3].trim();
|
|
4861
|
-
const key = `${method}:${
|
|
4862
|
-
apis.set(key, { method, path:
|
|
4880
|
+
const key = `${method}:${path18}`;
|
|
4881
|
+
apis.set(key, { method, path: path18, description });
|
|
4863
4882
|
}
|
|
4864
4883
|
return apis;
|
|
4865
4884
|
}
|
|
@@ -4881,7 +4900,7 @@ init_esm_shims();
|
|
|
4881
4900
|
init_utils();
|
|
4882
4901
|
init_logger();
|
|
4883
4902
|
import { Command as Command12 } from "commander";
|
|
4884
|
-
import
|
|
4903
|
+
import path16 from "path";
|
|
4885
4904
|
import inquirer8 from "inquirer";
|
|
4886
4905
|
var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668 (today, --all, \u6216\u65E5\u671F YYYY-MM-DD)").description("\u67E5\u770B\u4F1A\u8BDD\u65E5\u5FD7").action(async (filter = "today") => {
|
|
4887
4906
|
try {
|
|
@@ -4906,7 +4925,7 @@ var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668
|
|
|
4906
4925
|
case "":
|
|
4907
4926
|
case "today": {
|
|
4908
4927
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
4909
|
-
targetDir =
|
|
4928
|
+
targetDir = path16.join(sessionsDir, today);
|
|
4910
4929
|
const todayExists = await FileUtils.exists(targetDir);
|
|
4911
4930
|
if (!todayExists) {
|
|
4912
4931
|
logger.info("\u4ECA\u65E5\u6682\u65E0\u4F1A\u8BDD\u65E5\u5FD7");
|
|
@@ -4922,7 +4941,7 @@ var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668
|
|
|
4922
4941
|
break;
|
|
4923
4942
|
}
|
|
4924
4943
|
default: {
|
|
4925
|
-
targetDir =
|
|
4944
|
+
targetDir = path16.join(sessionsDir, filter);
|
|
4926
4945
|
const dateExists = await FileUtils.exists(targetDir);
|
|
4927
4946
|
if (!dateExists) {
|
|
4928
4947
|
logger.error(`\u672A\u627E\u5230\u65E5\u671F '${filter}' \u7684\u65E5\u5FD7`);
|
|
@@ -4946,7 +4965,7 @@ var logsCommand = new Command12("logs").argument("[filter]", "\u8FC7\u6EE4\u5668
|
|
|
4946
4965
|
process.exit(0);
|
|
4947
4966
|
}
|
|
4948
4967
|
for (let i = 0; i < logs.length; i++) {
|
|
4949
|
-
const relPath =
|
|
4968
|
+
const relPath = path16.relative(sessionsDir, logs[i]);
|
|
4950
4969
|
logger.step(`${i + 1}) ${relPath}`);
|
|
4951
4970
|
}
|
|
4952
4971
|
logger.newLine();
|
|
@@ -4987,7 +5006,7 @@ async function collectLogFiles(targetDir) {
|
|
|
4987
5006
|
const allFiles = await FileUtils.findFiles("*.md", targetDir);
|
|
4988
5007
|
const filtered = allFiles.filter((f) => f !== "index.md");
|
|
4989
5008
|
for (const file of filtered) {
|
|
4990
|
-
const filePath =
|
|
5009
|
+
const filePath = path16.join(targetDir, file);
|
|
4991
5010
|
const stat = await FileUtils.exists(filePath);
|
|
4992
5011
|
if (stat) {
|
|
4993
5012
|
logs.push(filePath);
|
|
@@ -5001,7 +5020,7 @@ async function collectLogFiles(targetDir) {
|
|
|
5001
5020
|
// src/commands/update.ts
|
|
5002
5021
|
init_esm_shims();
|
|
5003
5022
|
import { Command as Command13 } from "commander";
|
|
5004
|
-
import
|
|
5023
|
+
import path17 from "path";
|
|
5005
5024
|
init_logger();
|
|
5006
5025
|
init_utils();
|
|
5007
5026
|
import { execa as execa4 } from "execa";
|
|
@@ -5106,7 +5125,7 @@ async function performUpdate(projectPath, updates) {
|
|
|
5106
5125
|
for (const update of updates) {
|
|
5107
5126
|
const { type, info, updateOptions } = update;
|
|
5108
5127
|
const targetDir = type === "frontend" ? "frontend" : "backend";
|
|
5109
|
-
const targetPath =
|
|
5128
|
+
const targetPath = path17.join(projectPath, targetDir);
|
|
5110
5129
|
logger.newLine();
|
|
5111
5130
|
logger.step(`\u66F4\u65B0 ${type === "frontend" ? "\u524D\u7AEF" : "\u540E\u7AEF"}\u6A21\u677F...`);
|
|
5112
5131
|
if (updateOptions?.tag || updateOptions?.branch) {
|
|
@@ -5137,8 +5156,8 @@ async function performUpdate(projectPath, updates) {
|
|
|
5137
5156
|
}
|
|
5138
5157
|
}
|
|
5139
5158
|
const ref = updateOptions?.tag || updateOptions?.branch || "HEAD";
|
|
5140
|
-
const backupDir =
|
|
5141
|
-
await fs3.copy(targetPath,
|
|
5159
|
+
const backupDir = path17.join(projectPath, `.backup-${Date.now()}`);
|
|
5160
|
+
await fs3.copy(targetPath, path17.join(backupDir, targetDir));
|
|
5142
5161
|
logger.info(`\u5DF2\u521B\u5EFA\u5907\u4EFD: ${backupDir}`);
|
|
5143
5162
|
if (updateOptions?.dryRun) {
|
|
5144
5163
|
logger.info("[Dry Run] \u5C06\u4F1A\u66F4\u65B0\u5230\u4EE5\u4E0B\u7248\u672C:");
|
|
@@ -5148,7 +5167,7 @@ async function performUpdate(projectPath, updates) {
|
|
|
5148
5167
|
continue;
|
|
5149
5168
|
}
|
|
5150
5169
|
try {
|
|
5151
|
-
const tempDir =
|
|
5170
|
+
const tempDir = path17.join(projectPath, `.template-update-${Date.now()}`);
|
|
5152
5171
|
await execa4("git", ["clone", "--depth=1", "--branch", ref, info.repository, tempDir], {
|
|
5153
5172
|
stdio: "pipe"
|
|
5154
5173
|
});
|
|
@@ -5165,7 +5184,7 @@ async function performUpdate(projectPath, updates) {
|
|
|
5165
5184
|
const currentFiles = await FileUtils.findFiles("*", targetPath);
|
|
5166
5185
|
for (const file of currentFiles) {
|
|
5167
5186
|
if (!keepFiles.includes(file)) {
|
|
5168
|
-
const filePath =
|
|
5187
|
+
const filePath = path17.join(targetPath, file);
|
|
5169
5188
|
try {
|
|
5170
5189
|
await fs3.remove(filePath);
|
|
5171
5190
|
} catch {
|
|
@@ -5187,7 +5206,7 @@ async function performUpdate(projectPath, updates) {
|
|
|
5187
5206
|
logger.error(`\u66F4\u65B0\u5931\u8D25: ${error.message}`);
|
|
5188
5207
|
logger.info("\u6B63\u5728\u6062\u590D\u5907\u4EFD...");
|
|
5189
5208
|
await fs3.remove(targetPath);
|
|
5190
|
-
await fs3.copy(
|
|
5209
|
+
await fs3.copy(path17.join(backupDir, targetDir), targetPath);
|
|
5191
5210
|
await fs3.remove(backupDir);
|
|
5192
5211
|
logger.info("\u5DF2\u6062\u590D\u5230\u66F4\u65B0\u524D\u7684\u72B6\u6001");
|
|
5193
5212
|
}
|
|
@@ -5674,7 +5693,7 @@ var Table = class {
|
|
|
5674
5693
|
|
|
5675
5694
|
// src/index.ts
|
|
5676
5695
|
var program = new Command16();
|
|
5677
|
-
program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version("2.1.
|
|
5696
|
+
program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version("2.1.2");
|
|
5678
5697
|
program.option("-v, --verbose", "\u8BE6\u7EC6\u8F93\u51FA\u6A21\u5F0F").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F");
|
|
5679
5698
|
program.addCommand(initCommand);
|
|
5680
5699
|
program.addCommand(splitPrdCommand);
|