ai-project-manage-cli 6.0.37 → 6.0.38

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/index.js CHANGED
@@ -84,13 +84,55 @@ import { join as join3 } from "path";
84
84
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
85
85
 
86
86
  // src/command-utils.ts
87
- import { cpSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
88
- import { basename, dirname, extname, join as join2, resolve } from "path";
87
+ import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
88
+ import { basename, dirname, extname, join as join2, resolve as resolve2 } from "path";
89
89
  import { fileURLToPath } from "url";
90
+
91
+ // src/workdir-path.ts
92
+ import { realpathSync } from "fs";
93
+ import { platform } from "os";
94
+ import { resolve } from "path";
95
+ function toFsPath(inputPath) {
96
+ const absolute = resolve(inputPath);
97
+ if (platform() !== "win32") return absolute;
98
+ if (absolute.startsWith("\\\\?\\")) return absolute;
99
+ const normalized = absolute.replace(/\//g, "\\");
100
+ if (normalized.startsWith("\\\\")) {
101
+ return `\\\\?\\UNC\\${normalized.slice(2)}`;
102
+ }
103
+ return `\\\\?\\${normalized}`;
104
+ }
105
+ function normalizeWorkdirPath(path10) {
106
+ let normalized = path10.trim().replace(/\\/g, "/").normalize("NFC");
107
+ if (normalized.startsWith("//?/")) {
108
+ normalized = normalized.slice(4);
109
+ }
110
+ const windowsDrive = /^([A-Za-z]:)\/*(.*)$/.exec(normalized);
111
+ if (windowsDrive) {
112
+ const drive = windowsDrive[1].toLowerCase();
113
+ const rest = windowsDrive[2].replace(/\/+/g, "/").replace(/\/$/, "");
114
+ return rest ? `${drive}/${rest}` : drive;
115
+ }
116
+ normalized = normalized.replace(/\/+/g, "/");
117
+ if (normalized.length > 1 && normalized.endsWith("/")) {
118
+ normalized = normalized.slice(0, -1);
119
+ }
120
+ return normalized;
121
+ }
122
+ function resolveWorkdirPath(cwd = process.cwd()) {
123
+ const absolute = resolve(cwd);
124
+ try {
125
+ return normalizeWorkdirPath(realpathSync.native(absolute));
126
+ } catch {
127
+ return normalizeWorkdirPath(absolute);
128
+ }
129
+ }
130
+
131
+ // src/command-utils.ts
90
132
  var __dirname = dirname(fileURLToPath(import.meta.url));
91
- var CLI_TEMPLATE_DIR = resolve(__dirname, "../template");
92
- function workspaceApmDir(cwd = process.cwd()) {
93
- return resolve(cwd, ".apm");
133
+ var CLI_TEMPLATE_DIR = resolve2(__dirname, "../template");
134
+ function workspaceApmDir(cwd = resolveWorkdirPath()) {
135
+ return resolve2(resolve2(cwd), ".apm");
94
136
  }
95
137
  var SESSIONS_SUBDIR = "sessions";
96
138
  var SESSION_DOCS_SUBDIR = "docs";
@@ -147,78 +189,106 @@ async function ensureLoggedConfig() {
147
189
  async function ensureDirExists(dir) {
148
190
  mkdirSync2(dir, { recursive: true });
149
191
  }
150
- async function ensureWorkspaceApmDirForInit() {
151
- const dir = workspaceApmDir();
152
- if (!existsSync(dir)) {
153
- mkdirSync2(dir, { recursive: true });
192
+ async function ensureWorkspaceApmDirForInit(cwd = resolveWorkdirPath()) {
193
+ const dir = workspaceApmDir(cwd);
194
+ const fsDir = toFsPath(dir);
195
+ if (!existsSync(fsDir)) {
196
+ mkdirSync2(fsDir, { recursive: true });
154
197
  return;
155
198
  }
156
- const st = statSync(dir);
199
+ const st = statSync(fsDir);
157
200
  if (!st.isDirectory()) {
158
201
  throw new Error(`[apm] \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${dir}`);
159
202
  }
160
- if (readdirSync(dir).length > 0) {
203
+ if (readdirSync(fsDir).length > 0) {
161
204
  throw new Error(
162
205
  "[apm] .apm \u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\uFF0C\u8BF7\u5148\u5907\u4EFD\u3001\u6E05\u7A7A\u6216\u5220\u9664\u540E\u518D\u6267\u884C init"
163
206
  );
164
207
  }
165
208
  }
166
- async function copyTemplateFiles(targetDir) {
167
- if (!existsSync(CLI_TEMPLATE_DIR)) {
168
- throw new Error(`[apm] \u672A\u627E\u5230 CLI \u6A21\u677F\u76EE\u5F55: ${CLI_TEMPLATE_DIR}`);
169
- }
170
- const dirStat = statSync(CLI_TEMPLATE_DIR);
171
- if (!dirStat.isDirectory()) {
172
- throw new Error(`[apm] CLI \u6A21\u677F\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${CLI_TEMPLATE_DIR}`);
209
+ var WORKSPACE_TEMPLATE_SUBDIRS = [
210
+ "sessions",
211
+ "skills",
212
+ "rules",
213
+ "deploy"
214
+ ];
215
+ function shouldSkipTemplateEntry(name) {
216
+ return name === ".DS_Store" || name === "Thumbs.db";
217
+ }
218
+ function copyTemplateEntry(src, dest) {
219
+ const fsSrc = toFsPath(src);
220
+ const fsDest = toFsPath(dest);
221
+ const st = statSync(fsSrc);
222
+ if (st.isDirectory()) {
223
+ mkdirSync2(fsDest, { recursive: true });
224
+ for (const name of readdirSync(fsSrc)) {
225
+ if (shouldSkipTemplateEntry(name)) continue;
226
+ copyTemplateEntry(join2(src, name), join2(dest, name));
227
+ }
228
+ return;
173
229
  }
174
- const entries = readdirSync(CLI_TEMPLATE_DIR);
175
- if (entries.length === 0) {
176
- throw new Error(`[apm] CLI \u6A21\u677F\u76EE\u5F55\u4E3A\u7A7A: ${CLI_TEMPLATE_DIR}`);
230
+ if (!st.isFile()) return;
231
+ mkdirSync2(toFsPath(dirname(dest)), { recursive: true });
232
+ copyFileSync(fsSrc, fsDest);
233
+ }
234
+ function assertTemplateCopiedToApm(apmDir, workdir) {
235
+ const required = [
236
+ "AGENTS.md",
237
+ "apm.config.json",
238
+ "rules",
239
+ "skills",
240
+ "sessions"
241
+ ];
242
+ for (const item of required) {
243
+ const path10 = join2(apmDir, item);
244
+ if (!existsSync(toFsPath(path10))) {
245
+ throw new Error(`[apm] \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path10}`);
246
+ }
177
247
  }
178
- for (const name of entries) {
179
- const src = join2(CLI_TEMPLATE_DIR, name);
180
- const dest = join2(targetDir, name);
181
- cpSync(src, dest, { recursive: true, force: false });
248
+ const leakedRules = join2(workdir, "rules");
249
+ const apmRules = join2(apmDir, "rules");
250
+ if (existsSync(toFsPath(leakedRules)) && !existsSync(toFsPath(join2(apmRules, "reply.md")))) {
251
+ throw new Error(
252
+ `[apm] \u6A21\u677F\u88AB\u590D\u5236\u5230\u9519\u8BEF\u4F4D\u7F6E: ${leakedRules}\uFF08\u5E94\u5728 ${apmRules}\uFF09`
253
+ );
182
254
  }
183
255
  }
184
-
185
- // src/workdir-path.ts
186
- import { realpathSync } from "fs";
187
- import { resolve as resolve2 } from "path";
188
- function normalizeWorkdirPath(path10) {
189
- let normalized = path10.trim().replace(/\\/g, "/").normalize("NFC");
190
- if (normalized.startsWith("//?/")) {
191
- normalized = normalized.slice(4);
256
+ async function copyTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
257
+ const resolvedTarget = resolve2(targetDir);
258
+ const templateDir = resolve2(CLI_TEMPLATE_DIR);
259
+ const fsTemplateDir = toFsPath(templateDir);
260
+ if (!existsSync(fsTemplateDir)) {
261
+ throw new Error(`[apm] \u672A\u627E\u5230 CLI \u6A21\u677F\u76EE\u5F55: ${templateDir}`);
192
262
  }
193
- const windowsDrive = /^([A-Za-z]:)\/*(.*)$/.exec(normalized);
194
- if (windowsDrive) {
195
- const drive = windowsDrive[1].toLowerCase();
196
- const rest = windowsDrive[2].replace(/\/+/g, "/").replace(/\/$/, "");
197
- return rest ? `${drive}/${rest}` : drive;
263
+ const dirStat = statSync(fsTemplateDir);
264
+ if (!dirStat.isDirectory()) {
265
+ throw new Error(`[apm] CLI \u6A21\u677F\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${templateDir}`);
198
266
  }
199
- normalized = normalized.replace(/\/+/g, "/");
200
- if (normalized.length > 1 && normalized.endsWith("/")) {
201
- normalized = normalized.slice(0, -1);
267
+ const entries = readdirSync(fsTemplateDir).filter(
268
+ (name) => !shouldSkipTemplateEntry(name)
269
+ );
270
+ if (entries.length === 0) {
271
+ throw new Error(`[apm] CLI \u6A21\u677F\u76EE\u5F55\u4E3A\u7A7A: ${templateDir}`);
202
272
  }
203
- return normalized;
204
- }
205
- function resolveWorkdirPath(cwd = process.cwd()) {
206
- const absolute = resolve2(cwd);
207
- try {
208
- return normalizeWorkdirPath(realpathSync.native(absolute));
209
- } catch {
210
- return normalizeWorkdirPath(absolute);
273
+ mkdirSync2(toFsPath(resolvedTarget), { recursive: true });
274
+ for (const name of entries) {
275
+ copyTemplateEntry(join2(templateDir, name), join2(resolvedTarget, name));
211
276
  }
277
+ for (const subdir of WORKSPACE_TEMPLATE_SUBDIRS) {
278
+ mkdirSync2(toFsPath(join2(resolvedTarget, subdir)), { recursive: true });
279
+ }
280
+ assertTemplateCopiedToApm(resolvedTarget, resolve2(workdir));
212
281
  }
213
282
 
214
283
  // src/commands/init.ts
215
284
  async function runInit(name) {
216
- await ensureWorkspaceApmDirForInit();
217
- const apmDir = workspaceApmDir();
218
- await copyTemplateFiles(apmDir);
285
+ const workdir = resolveWorkdirPath();
286
+ await ensureWorkspaceApmDirForInit(workdir);
287
+ const apmDir = workspaceApmDir(workdir);
288
+ await copyTemplateFiles(apmDir, workdir);
219
289
  const trimmedName = name?.trim();
220
290
  if (trimmedName) {
221
- const apmConfigPath = join3(apmDir, "apm.config.json");
291
+ const apmConfigPath = toFsPath(join3(apmDir, "apm.config.json"));
222
292
  const config = readFileSync2(apmConfigPath, "utf8");
223
293
  const configJson = JSON.parse(config);
224
294
  configJson.name = trimmedName;
@@ -229,7 +299,6 @@ async function runInit(name) {
229
299
  "utf8"
230
300
  );
231
301
  }
232
- const workdir = resolveWorkdirPath();
233
302
  console.log(`[apm] \u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
234
303
  console.log(`[apm] \u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84\uFF1A${workdir}`);
235
304
  console.log("[apm] \u8BF7\u5728\u5E73\u53F0\u300C\u5BA2\u6237\u673A\u7BA1\u7406 \u2192 \u5DE5\u4F5C\u7A7A\u95F4\u300D\u767B\u8BB0\u4E0A\u8FF0\u76EE\u5F55\u8DEF\u5F84");
@@ -795,8 +864,8 @@ import { join as join8 } from "path";
795
864
 
796
865
  // src/skills-sync.ts
797
866
  import {
798
- copyFileSync,
799
- cpSync as cpSync2,
867
+ copyFileSync as copyFileSync2,
868
+ cpSync,
800
869
  existsSync as existsSync3,
801
870
  mkdirSync as mkdirSync3,
802
871
  readdirSync as readdirSync2,
@@ -823,7 +892,7 @@ function listBaseSkillDirNames() {
823
892
  function syncAgentsGuide(apmDir) {
824
893
  if (!existsSync3(AGENTS_TEMPLATE_PATH)) return false;
825
894
  mkdirSync3(apmDir, { recursive: true });
826
- copyFileSync(AGENTS_TEMPLATE_PATH, join7(apmDir, "AGENTS.md"));
895
+ copyFileSync2(AGENTS_TEMPLATE_PATH, join7(apmDir, "AGENTS.md"));
827
896
  return true;
828
897
  }
829
898
  function listBaseRuleFileNames() {
@@ -839,7 +908,7 @@ function syncBaseRules(rulesDir) {
839
908
  for (const name of names) {
840
909
  const src = join7(BASE_RULES_TEMPLATE_DIR, name);
841
910
  const dest = join7(rulesDir, name);
842
- copyFileSync(src, dest);
911
+ copyFileSync2(src, dest);
843
912
  }
844
913
  return names;
845
914
  }
@@ -849,7 +918,7 @@ function syncBaseSkills(skillsDir) {
849
918
  for (const name of names) {
850
919
  const src = join7(BASE_SKILLS_TEMPLATE_DIR, name);
851
920
  const dest = join7(skillsDir, name);
852
- cpSync2(src, dest, { recursive: true, force: true });
921
+ cpSync(src, dest, { recursive: true, force: true });
853
922
  }
854
923
  return names;
855
924
  }
@@ -2346,7 +2415,7 @@ function assertDeployImageTag(tag) {
2346
2415
  }
2347
2416
 
2348
2417
  // src/commands/deploy/internal/backend-deploy/local-docker-build.ts
2349
- import { platform } from "node:os";
2418
+ import { platform as platform2 } from "node:os";
2350
2419
 
2351
2420
  // src/commands/deploy/internal/backend-deploy/command-runner.ts
2352
2421
  import { execSync } from "child_process";
@@ -2406,7 +2475,7 @@ var CommandRunner = class {
2406
2475
 
2407
2476
  // src/commands/deploy/internal/backend-deploy/local-docker-build.ts
2408
2477
  function dockerBuildPlatformFlags() {
2409
- return platform() === "darwin" ? ["--platform", "linux/amd64"] : [];
2478
+ return platform2() === "darwin" ? ["--platform", "linux/amd64"] : [];
2410
2479
  }
2411
2480
  function buildDockerImageLocally(params, cwd) {
2412
2481
  const platformFlags = dockerBuildPlatformFlags();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.37",
3
+ "version": "6.0.38",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -0,0 +1,15 @@
1
+ ## 前端部署
2
+
3
+ 部署测试环境: `npm run deploy:test`
4
+ 部署线上环境: `npm run deploy:online`
5
+
6
+ ## 后端部署(不区分正式环境和测试环境)
7
+ `python scripts/deploy.py`
8
+
9
+ ## 前端产物下载地址
10
+
11
+ http://<服务器地址>/dist.zip
12
+ http://<服务器地址>/backend_update_jar.zip
13
+
14
+ ## 测试地址
15
+ http://<测试环境>
File without changes