yg-team-cli 2.1.8 → 2.2.0

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/README.md CHANGED
@@ -32,7 +32,32 @@
32
32
 
33
33
  以下记录了 team-cli 的开发进展,按时间倒序排列。
34
34
 
35
- ### 2026-01-27 - 迭代开发与自动化
35
+ ### 2026-01-27 - GitLab 版本管理与 Dev 模式增强
36
+
37
+ **Phase 4: GitLab 版本管理**
38
+ - **提交**: `npm_feature` 分支
39
+ - **新增命令**: `config`, `diff`
40
+ - **功能**:
41
+ - GitLab Access Token 管理(加密存储)
42
+ - 模板版本检查和更新
43
+ - 版本对比功能(支持 tag/branch)
44
+ - 模板版本信息记录到 AI_MEMORY.md
45
+ - **新增文件**:
46
+ - `src/lib/user-config.ts` - 用户配置管理
47
+ - `src/lib/gitlab-api.ts` - GitLab API 客户端
48
+ - `src/commands/config.ts` - 配置管理命令
49
+ - `src/commands/diff.ts` - 版本对比命令
50
+ - **npm 发布**: `yg-team-cli@2.1.9`
51
+
52
+ **Phase 3: Dev 模式增强**
53
+ - **功能**:
54
+ - 任务完成后自动更新 spec 文件状态
55
+ - 支持单个 todo 或整个 milestone 批量更新
56
+ - **交互优化**:
57
+ - 添加用户指引提示
58
+ - 移除超时限制,允许长时间开发
59
+
60
+ **Phase 2: 迭代开发与自动化**
36
61
 
37
62
  **Phase 3: API 管理功能**
38
63
  - **提交**: `6a69bc5`
@@ -117,32 +142,31 @@
117
142
 
118
143
  ## 安装
119
144
 
120
- ### 方式一:Git 仓库分发(推荐)
145
+ ### 通过 npm 安装(推荐)
121
146
 
122
147
  ```bash
123
- # 克隆仓库
124
- git clone https://github.com/your-org/team-cli.git
125
- cd team-cli
126
-
127
- # 添加到 PATH
128
- echo 'export PATH=$PATH:'$(pwd)'' >> ~/.zshrc
129
- source ~/.zshrc
148
+ # 全局安装
149
+ npm install -g yg-team-cli
130
150
 
131
- # 赋予执行权限
132
- chmod +x team-cli
151
+ # 验证安装
152
+ team-cli --version
133
153
  ```
134
154
 
135
- ### 方式二:直接下载
155
+ ### 方式一:Git 仓库分发
136
156
 
137
157
  ```bash
138
- # 下载脚本
139
- curl -O https://raw.githubusercontent.com/your-org/team-cli/main/team-cli
158
+ # 克隆仓库
159
+ git clone https://gitlab.yungu-inc.org/yungu-app/claude-dev-cli.git
160
+ cd claude-dev-cli
161
+
162
+ # 安装依赖
163
+ npm install
140
164
 
141
- # 赋予执行权限
142
- chmod +x team-cli
165
+ # 构建项目
166
+ npm run build
143
167
 
144
- # 添加到 PATH
145
- sudo mv team-cli /usr/local/bin/
168
+ # 全局链接
169
+ npm link
146
170
  ```
147
171
 
148
172
  ## 使用指南
@@ -155,12 +179,26 @@ sudo mv team-cli /usr/local/bin/
155
179
  team-cli init my-project
156
180
  ```
157
181
 
182
+ **指定版本初始化:**
183
+
184
+ ```bash
185
+ # 使用指定 tag 初始化
186
+ team-cli init my-project --backend-tag v1.2.0
187
+
188
+ # 使用指定分支初始化
189
+ team-cli init my-project --frontend-branch develop
190
+
191
+ # 前后端指定不同版本
192
+ team-cli init my-project --backend-tag v1.2.0 --frontend-branch develop
193
+ ```
194
+
158
195
  **执行内容:**
159
196
  - 环境检查(Claude Code CLI)
160
197
  - 交互式输入项目名称
161
198
  - 创建标准目录结构
162
199
  - 生成"宪法"文件(TECH_STACK.md, CONVENTIONS.md, AI_MEMORY.md)
163
200
  - 从模板仓库克隆前后端代码
201
+ - 记录模板版本信息到 `.team-cli/template.json` 和 AI_MEMORY.md
164
202
  - 初始化 Git 仓库
165
203
  - 配置 pre-commit hook
166
204
 
@@ -584,7 +622,7 @@ team-cli detect-deps
584
622
  - 服务引用(Service 注入)
585
623
  - 前端 API 调用(fetch, axios)
586
624
 
587
- ### 12. 同步 AI_MEMORY
625
+ ### 15. 同步 AI_MEMORY
588
626
 
589
627
  自动同步 AI_MEMORY.md,保持项目状态最新:
590
628
 
@@ -603,6 +641,7 @@ team-cli sync-memory
603
641
  - 扫描 specs 更新功能清单...
604
642
  - 扫描 Controller 更新 API 列表...
605
643
  - 扫描 Entity 更新数据模型...
644
+ - 同步模板版本信息...
606
645
  - 更新最后同步时间...
607
646
 
608
647
  ✓ AI_MEMORY.md 已同步
@@ -612,6 +651,37 @@ team-cli sync-memory
612
651
  - 功能清单(状态、进度、完成日期)
613
652
  - API 列表(扫描 Controller 生成)
614
653
  - 数据模型(表名、字段数、关联关系)
654
+ - 模板版本信息(前后端模板版本、commit、更新时间)
655
+
656
+ ### 16. Dev 模式增强
657
+
658
+ **开发任务完成后自动更新 Spec 文件状态:**
659
+
660
+ ```bash
661
+ team-cli dev
662
+ # → 选择 spec → milestone → todo
663
+ # → 在 Claude 中完成开发
664
+ # → 退出 Claude 后自动询问是否更新 spec 文件
665
+ ```
666
+
667
+ **交互流程:**
668
+
669
+ ```
670
+ 开发任务完成!
671
+ ✓ 会话日志已保存
672
+
673
+ ? 任务是否已完成?是否更新 spec 文件中的 todo 状态? (Y/n)
674
+ ```
675
+
676
+ 选择 `Y` 后自动:
677
+ - 找到对应的 todo 项
678
+ - 将 `- [ ]` 改为 `- [x]`
679
+ - 更新 spec 文件
680
+ - 下次运行 `team-cli dev` 时会显示为已完成
681
+
682
+ ---
683
+
684
+ ## 环境变量配置
615
685
 
616
686
  ### 13. API 检查
617
687
 
@@ -686,28 +756,73 @@ team-cli check-api
686
756
  | 2026-01-27 | v1.0 | 新增 | 初始版本 | team-cli |
687
757
  ```
688
758
 
689
- ---
759
+ ### 14. GitLab 版本管理
690
760
 
691
- ## 环境变量配置
761
+ 管理 GitLab 模板版本配置和更新:
692
762
 
693
763
  ```bash
694
- # 后端模板仓库
695
- export TEMPLATE_REPO=git@gitlab.yungu-inc.org:yungu-app/java-scaffold-template.git
764
+ # 配置 GitLab Token(首次使用必须)
765
+ team-cli config set-token
766
+
767
+ # 显示当前配置
768
+ team-cli config show
696
769
 
697
- # 本地后端模板(降级使用)
698
- export LOCAL_BACKEND_TEMPLATE=/path/to/local/backend/template
770
+ # 验证 Token
771
+ team-cli config validate
772
+ ```
699
773
 
700
- # 前端模板仓库
701
- export FRONTEND_TEMPLATE_REPO=https://gitlab.yungu-inc.org/static/fe-tpl-ai
774
+ **更新模板到最新版本:**
702
775
 
703
- # 本地前端模板(降级使用)
704
- export LOCAL_FRONTEND_TEMPLATE=/path/to/local/frontend/template
776
+ ```bash
777
+ # 检查并更新到最新版本
778
+ team-cli update
705
779
 
706
- # Git 网络超时时间(秒)
707
- export GIT_TIMEOUT=5
780
+ # 只更新后端模板
781
+ team-cli update --backend
782
+
783
+ # 更新到指定 tag
784
+ team-cli update --backend --tag v1.3.0
785
+
786
+ # 预览更新(不实际执行)
787
+ team-cli update --backend --tag v1.3.0 --dry-run
708
788
  ```
709
789
 
710
- ## 开发规范
790
+ **版本对比:**
791
+
792
+ ```bash
793
+ # 对比所有模板
794
+ team-cli diff
795
+
796
+ # 只对比后端模板
797
+ team-cli diff --backend
798
+
799
+ # 对比指定版本
800
+ team-cli diff --backend --tag v1.3.0
801
+
802
+ # 以 diff 格式输出
803
+ team-cli diff --backend --output diff
804
+ ```
805
+
806
+ **输出示例:**
807
+
808
+ ```
809
+ ═══════════════════════════════════════════════════════
810
+ 模板版本对比
811
+ ═══════════════════════════════════════════════════════
812
+
813
+ ▸ 后端模板:
814
+ 本地版本: v1.2.0 (abc123)
815
+ 远程版本: v1.3.0 (def456)
816
+ 状态: ⚠️ 有更新
817
+
818
+ 新增提交 (2):
819
+ ✓ abc123 添加用户导出功能
820
+ ✓ def456 修复分页查询 bug
821
+ ```
822
+
823
+ ---
824
+
825
+ ## 环境变量配置
711
826
 
712
827
  ### 后端规范
713
828
 
package/dist/cli.js CHANGED
@@ -177,6 +177,14 @@ var init_logger = __esm({
177
177
  const coloredLabel = chalk[labelColor](`[${label}]`);
178
178
  console.log(`${coloredLabel} ${text}`);
179
179
  }
180
+ /**
181
+ * 打印调试信息(灰色,仅在 DEBUG 模式下显示)
182
+ */
183
+ debug(text) {
184
+ if (process.env.DEBUG) {
185
+ console.debug(chalk.gray(`[DEBUG] ${text}`));
186
+ }
187
+ }
180
188
  };
181
189
  logger = new Logger();
182
190
  }
@@ -924,7 +932,7 @@ var init_user_config = __esm({
924
932
  try {
925
933
  const configDir = path5.dirname(this.configPath);
926
934
  await FileUtils.ensureDir(configDir);
927
- const configToSave = { ...config };
935
+ const configToSave = JSON.parse(JSON.stringify(config));
928
936
  if (configToSave.gitlab?.accessToken) {
929
937
  configToSave.gitlab.accessToken = this.encrypt(configToSave.gitlab.accessToken);
930
938
  }
@@ -1244,11 +1252,18 @@ var init_gitlab_api = __esm({
1244
1252
  */
1245
1253
  static parseProjectPath(repository) {
1246
1254
  let path18 = repository;
1247
- path18 = path18.replace(/^https?:\/\//, "");
1248
- path18 = path18.replace(/^git@/, "");
1249
- const parts = path18.split("/");
1250
- if (parts.length > 1) {
1251
- path18 = parts.slice(1).join("/");
1255
+ if (path18.startsWith("git@")) {
1256
+ path18 = path18.replace(/^git@/, "");
1257
+ const colonIndex = path18.indexOf(":");
1258
+ if (colonIndex !== -1) {
1259
+ path18 = path18.substring(colonIndex + 1);
1260
+ }
1261
+ } else {
1262
+ path18 = path18.replace(/^https?:\/\//, "");
1263
+ const parts = path18.split("/");
1264
+ if (parts.length > 1) {
1265
+ path18 = parts.slice(1).join("/");
1266
+ }
1252
1267
  }
1253
1268
  path18 = path18.replace(/\.git$/, "");
1254
1269
  return path18;
@@ -2458,6 +2473,7 @@ async function executeDevelopment(specFile, milestone, todo) {
2458
2473
  logger.separator("\u2500", 60);
2459
2474
  logger.newLine();
2460
2475
  await generateSessionLog(specFile, milestone, todo, taskDescription, result);
2476
+ await askAndUpdateSpecStatus(specFile, milestone, todo);
2461
2477
  logger.header("\u5F00\u53D1\u4EFB\u52A1\u5B8C\u6210!");
2462
2478
  logger.success("\u4F1A\u8BDD\u65E5\u5FD7\u5DF2\u4FDD\u5B58");
2463
2479
  logger.newLine();
@@ -2651,6 +2667,72 @@ ${result}
2651
2667
  `;
2652
2668
  await FileUtils.write(logFile, content);
2653
2669
  }
2670
+ async function askAndUpdateSpecStatus(specFile, milestone, todo) {
2671
+ try {
2672
+ const { shouldUpdate } = await inquirer3.prompt([
2673
+ {
2674
+ type: "confirm",
2675
+ name: "shouldUpdate",
2676
+ message: "\u4EFB\u52A1\u662F\u5426\u5DF2\u5B8C\u6210\uFF1F\u662F\u5426\u66F4\u65B0 spec \u6587\u4EF6\u4E2D\u7684 todo \u72B6\u6001\uFF1F",
2677
+ default: true
2678
+ }
2679
+ ]);
2680
+ if (!shouldUpdate) {
2681
+ logger.info("\u8DF3\u8FC7\u66F4\u65B0 spec \u6587\u4EF6");
2682
+ return;
2683
+ }
2684
+ const content = await FileUtils.read(specFile);
2685
+ const lines = content.split("\n");
2686
+ let inTargetMilestone = false;
2687
+ let targetTodoIndex = -1;
2688
+ let milestoneIndex = -1;
2689
+ for (let i = 0; i < lines.length; i++) {
2690
+ const line = lines[i];
2691
+ if (milestone !== "\u6574\u4E2A spec" && line.includes(milestone)) {
2692
+ inTargetMilestone = true;
2693
+ milestoneIndex = i;
2694
+ continue;
2695
+ }
2696
+ if (inTargetMilestone) {
2697
+ if (line.match(/^###\s+Milestone/)) {
2698
+ break;
2699
+ }
2700
+ if (todo !== "\u5168\u90E8\u529F\u80FD" && todo !== "\u5168\u90E8\u4EFB\u52A1") {
2701
+ const todoMatch = line.match(/^-\s+\[[ x ]\]\s*(.+)/);
2702
+ if (todoMatch && todoMatch[1].trim() === todo) {
2703
+ targetTodoIndex = i;
2704
+ break;
2705
+ }
2706
+ }
2707
+ }
2708
+ }
2709
+ if (targetTodoIndex !== -1) {
2710
+ const line = lines[targetTodoIndex];
2711
+ lines[targetTodoIndex] = line.replace(/^-\s+\[ \]/, "- [x]");
2712
+ logger.success(`\u5DF2\u6807\u8BB0 todo \u4E3A\u5B8C\u6210: ${todo}`);
2713
+ } else if (todo === "\u5168\u90E8\u529F\u80FD" || todo === "\u5168\u90E8\u4EFB\u52A1") {
2714
+ let updatedCount = 0;
2715
+ for (let i = milestoneIndex + 1; i < lines.length; i++) {
2716
+ const line = lines[i];
2717
+ if (line.match(/^###\s+Milestone/)) {
2718
+ break;
2719
+ }
2720
+ if (line.match(/^-\s+\[ \]/)) {
2721
+ lines[i] = line.replace(/^-\s+\[ \]/, "- [x]");
2722
+ updatedCount++;
2723
+ }
2724
+ }
2725
+ logger.success(`\u5DF2\u6807\u8BB0 ${updatedCount} \u4E2A todos \u4E3A\u5B8C\u6210`);
2726
+ } else {
2727
+ logger.warn("\u672A\u627E\u5230\u5BF9\u5E94\u7684 todo \u9879");
2728
+ return;
2729
+ }
2730
+ await FileUtils.write(specFile, lines.join("\n"));
2731
+ logger.success("Spec \u6587\u4EF6\u5DF2\u66F4\u65B0");
2732
+ } catch (error) {
2733
+ logger.warn(`\u66F4\u65B0 spec \u6587\u4EF6\u5931\u8D25: ${error}`);
2734
+ }
2735
+ }
2654
2736
  var devCommand;
2655
2737
  var init_dev = __esm({
2656
2738
  "src/commands/dev.ts"() {
@@ -5866,7 +5948,7 @@ var init_index = __esm({
5866
5948
  init_config();
5867
5949
  init_diff();
5868
5950
  program = new Command16();
5869
- program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version("2.1.8");
5951
+ program.name("team-cli").description("AI-Native \u56E2\u961F\u7814\u53D1\u811A\u624B\u67B6").version("2.1.9");
5870
5952
  program.option("-v, --verbose", "\u8BE6\u7EC6\u8F93\u51FA\u6A21\u5F0F").option("--debug", "\u8C03\u8BD5\u6A21\u5F0F");
5871
5953
  program.addCommand(initCommand);
5872
5954
  program.addCommand(splitPrdCommand);