zero-ai 1.0.70 → 1.0.71

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zero-ai",
3
- "version": "1.0.70",
3
+ "version": "1.0.71",
4
4
  "description": "Zero Ecotope AI",
5
5
  "main": "src/ai.js",
6
6
  "bin": {
@@ -3,17 +3,8 @@
3
3
  "description": "同步 Zero Ui 的最新框架",
4
4
  "command": "sync",
5
5
  "options": [
6
- {
7
- "name": "path",
8
- "alias": "p",
9
- "description": "本地配置文件路径,默认 .zero",
10
- "default": ".zero"
11
- },
12
- {
13
- "name": "mode",
14
- "alias": "m",
15
- "description": "指定同步模块的模式,是否本地同步",
16
- "default": false
17
- }
6
+ {"name": "path", "alias": "p", "description": "本地配置文件路径,默认 .zero", "default": ".zero"},
7
+ {"name": "mode", "alias": "m", "description": "指定同步模块的模式,是否本地同步", "default": false},
8
+ {"name": "reverse", "alias": "r", "type": "boolean", "description": "逆向拷贝:从当前项目拷贝到 Z_ZERO_UI 指定目录", "default": false}
18
9
  ]
19
- }
10
+ }
@@ -181,6 +181,51 @@ module.exports = async (options) => {
181
181
  Ec.info(`安装位置:${targetLabels.join("、")}`);
182
182
  Ec.info(`已安装 ${selectedFiles.length} 个规则文件`);
183
183
 
184
+ // work-claude/:提取标题形成菜单,用户选择后拷贝 CLAUDE-*.md 为项目根目录 CLAUDE.md
185
+ const workClaudeDir = path.join(repoCache, "work-claude");
186
+ if (fs.existsSync(workClaudeDir)) {
187
+ const workClaudeFiles = fs.readdirSync(workClaudeDir).filter((file) => {
188
+ const p = path.join(workClaudeDir, file);
189
+ return fs.statSync(p).isFile() && file.startsWith("CLAUDE-") && file.endsWith(".md");
190
+ });
191
+ if (workClaudeFiles.length > 0) {
192
+ const choicesWithTitle = workClaudeFiles.map((file) => {
193
+ const fullPath = path.join(workClaudeDir, file);
194
+ const content = fs.readFileSync(fullPath, "utf-8");
195
+ const match = content.match(/^#\s+(.+)$/m);
196
+ const title = match ? match[1].trim() : path.basename(file, ".md");
197
+ return { name: title, value: file };
198
+ });
199
+ const { selectedClaude } = await inquirer.prompt([
200
+ {
201
+ type: "list",
202
+ name: "selectedClaude",
203
+ message: "请选择要安装的 Claude 工作说明(将拷贝为项目根目录 CLAUDE.md):",
204
+ choices: choicesWithTitle
205
+ }
206
+ ]);
207
+ const sourceClaude = path.join(workClaudeDir, selectedClaude);
208
+ const targetClaude = path.resolve(outputPath, "CLAUDE.md");
209
+ fs.copyFileSync(sourceClaude, targetClaude);
210
+ Ec.info(`已安装:${selectedClaude} → CLAUDE.md`);
211
+ // 将 CLAUDE.md 追加到 .gitignore
212
+ const gitignorePathClaude = path.resolve(outputPath, ".gitignore");
213
+ const claudeIgnoreEntry = "CLAUDE.md";
214
+ if (fs.existsSync(gitignorePathClaude)) {
215
+ const content = fs.readFileSync(gitignorePathClaude, "utf-8");
216
+ const hasClaude = content.split("\n").some((line) => line.trim() === claudeIgnoreEntry);
217
+ if (!hasClaude) {
218
+ const newContent = content.endsWith("\n") ? `${content}${claudeIgnoreEntry}\n` : `${content}\n${claudeIgnoreEntry}\n`;
219
+ fs.writeFileSync(gitignorePathClaude, newContent, "utf-8");
220
+ Ec.info(`已将 ${claudeIgnoreEntry} 添加到 .gitignore`);
221
+ }
222
+ } else {
223
+ fs.writeFileSync(gitignorePathClaude, `${claudeIgnoreEntry}\n`, "utf-8");
224
+ Ec.info(`已创建 .gitignore 并添加 ${claudeIgnoreEntry}`);
225
+ }
226
+ }
227
+ }
228
+
184
229
  // 添加 AI 工具目录到 .git/info/exclude
185
230
  const excludeEntries = [".cursor/", ".claude/", ".gemini/", ".trae/", ".lingma/"];
186
231
  const gitPath = path.resolve(outputPath, ".git");
@@ -91,6 +91,35 @@ const executeLocal = (actual = {}, options = {}) => {
91
91
  return pathEnv;
92
92
  }
93
93
 
94
+ /**
95
+ * 逆向拷贝:从当前项目将 COMMANDS 所列内容拷贝到 Z_ZERO_UI 指定目录
96
+ */
97
+ const executeReverse = (targetBase, options = {}) => {
98
+ Ec.info(`逆向拷贝目标:${targetBase}`);
99
+ Ec.info(`开始逆向拷贝主框架(与正向 sync 相同内容):......`.yellow);
100
+ COMMANDS.forEach((command) => {
101
+ Ec.info(`处理:${command.green}`);
102
+ const src = `./${command}`;
103
+ const dest = path.resolve(targetBase, command);
104
+ if (command.endsWith("/")) {
105
+ if (!Ec.isExist(src)) return;
106
+ const destDir = path.resolve(targetBase, command);
107
+ if (!fs.existsSync(destDir)) {
108
+ fs.mkdirSync(destDir, { recursive: true });
109
+ }
110
+ child.execSync(`cp -rf ${src}* "${destDir}"`, options);
111
+ } else {
112
+ if (!Ec.isExist(src)) return;
113
+ const destDir = path.dirname(dest);
114
+ if (!fs.existsSync(destDir)) {
115
+ fs.mkdirSync(destDir, { recursive: true });
116
+ }
117
+ child.execSync(`cp -rf ${src} "${dest}"`, options);
118
+ }
119
+ });
120
+ Ec.info(`逆向拷贝完成:${targetBase}!`.help);
121
+ };
122
+
94
123
  module.exports = (options) => {
95
124
 
96
125
  // 获取当前操作系统
@@ -107,6 +136,14 @@ module.exports = (options) => {
107
136
  optionsWait = {stdio: 'inherit'};
108
137
  }
109
138
 
139
+ // -r / --reverse 无值时补 "true",否则 parseArgument 会报缺值
140
+ const argvRest = process.argv.slice(3);
141
+ const rIdx = argvRest.indexOf("-r");
142
+ const revIdx = argvRest.indexOf("--reverse");
143
+ const flagIdx = rIdx >= 0 ? rIdx : revIdx;
144
+ if (flagIdx >= 0 && (flagIdx + 1 >= argvRest.length || (argvRest[flagIdx + 1] && argvRest[flagIdx + 1].startsWith("-")))) {
145
+ process.argv.splice(3 + flagIdx + 1, 0, "true");
146
+ }
110
147
  const parsed = Ut.parseArgument(options);
111
148
  // 1. 环境检查
112
149
  if (!Ec.isExist(".git")) {
@@ -114,6 +151,18 @@ module.exports = (options) => {
114
151
  return;
115
152
  }
116
153
 
154
+ // 逆向拷贝:-r 时从当前项目拷贝到 Z_ZERO_UI
155
+ if (parsed.reverse) {
156
+ const targetBase = process.env.Z_ZERO_UI;
157
+ if (!targetBase || !targetBase.trim()) {
158
+ Ec.error("逆向拷贝需要设置环境变量 Z_ZERO_UI(拷贝目标地址),未设置则退出。");
159
+ process.exit(1);
160
+ }
161
+ const resolved = path.resolve(targetBase.trim());
162
+ executeReverse(resolved, optionsWait);
163
+ return;
164
+ }
165
+
117
166
  let pathSource;
118
167
  if (parsed.mode) {
119
168
  // 本地模式