ai-project-manage-cli 3.0.17 → 3.0.19

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 (2) hide show
  1. package/dist/index.js +262 -257
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { readFileSync as readFileSync10 } from "fs";
5
- import { dirname as dirname2, join as join8 } from "path";
5
+ import { dirname as dirname2, join as join9 } from "path";
6
6
  import { fileURLToPath as fileURLToPath2 } from "url";
7
7
  import { Command } from "commander";
8
8
 
@@ -158,8 +158,8 @@ import { fileURLToPath } from "url";
158
158
  var __dirname = dirname(fileURLToPath(import.meta.url));
159
159
  var CLI_TEMPLATE_DIR = resolve(__dirname, "../template");
160
160
  var WORKSPACE_APM_DIR = resolve(process.cwd(), ".apm");
161
- function requirementWorkitemsDir(requirementId) {
162
- return join2(WORKSPACE_APM_DIR, "workitems", requirementId);
161
+ function requirementWorkitemsDir(requirementId, workspaceDir = WORKSPACE_APM_DIR) {
162
+ return join2(workspaceDir, "workitems", requirementId);
163
163
  }
164
164
  async function ensureLoggedConfig() {
165
165
  const cfg = await ensureApmConfig();
@@ -227,10 +227,10 @@ async function runComment(requirementId, file, model) {
227
227
  }
228
228
 
229
229
  // src/commands/connect.ts
230
- import { execSync } from "child_process";
231
230
  import { randomUUID } from "crypto";
232
231
  import WebSocket from "ws";
233
232
  import { Agent } from "@cursor/sdk";
233
+ import { join as join5 } from "path";
234
234
 
235
235
  // src/session-utils.ts
236
236
  import { appendFileSync } from "fs";
@@ -278,17 +278,20 @@ var EventSession = class {
278
278
  }
279
279
  return;
280
280
  }
281
- this.events.push(event);
281
+ this.events.push(formatedEvent);
282
282
  }
283
283
  formatEvent(event) {
284
284
  switch (event.type) {
285
285
  case "assistant":
286
286
  return {
287
287
  type: "assistant",
288
- content: event.message.content[0].text || ""
288
+ content: event.message.content[0].text || event.content || ""
289
289
  };
290
290
  case "thinking":
291
- return { type: "thinking", content: event.text || "" };
291
+ return {
292
+ type: "thinking",
293
+ content: event.text || event.content || ""
294
+ };
292
295
  case "tool_call":
293
296
  return {
294
297
  type: "tool_call",
@@ -329,6 +332,228 @@ var EventSession = class {
329
332
  }
330
333
  };
331
334
 
335
+ // src/commands/upload-artifact.ts
336
+ import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
337
+ import { join as join3, relative, sep } from "path";
338
+ var EXCLUDED_RELATIVE_PATHS = /* @__PURE__ */ new Set([
339
+ "defect.xml",
340
+ "prd.md",
341
+ "requirement-status.yaml",
342
+ "reviews.xml",
343
+ "testcase.xml"
344
+ ]);
345
+ function toPosixRelative(root, absoluteFile) {
346
+ return relative(root, absoluteFile).split(sep).join("/");
347
+ }
348
+ function artifactTagFromRelPath(relPosix) {
349
+ const parts = relPosix.split("/");
350
+ const fileName = parts[parts.length - 1] ?? relPosix;
351
+ if (parts.length > 1) {
352
+ return parts[0] ?? fileName;
353
+ }
354
+ const dot = fileName.lastIndexOf(".");
355
+ return dot > 0 ? fileName.slice(0, dot) : fileName;
356
+ }
357
+ function* walkMarkdownFiles(dir) {
358
+ const names = readdirSync2(dir);
359
+ for (const name of names) {
360
+ if (name.startsWith(".")) continue;
361
+ const full = join3(dir, name);
362
+ const st = statSync2(full);
363
+ if (st.isDirectory()) {
364
+ yield* walkMarkdownFiles(full);
365
+ continue;
366
+ }
367
+ if (!st.isFile()) continue;
368
+ if (!name.toLowerCase().endsWith(".md")) continue;
369
+ yield full;
370
+ }
371
+ }
372
+ async function deleteAllArtifactsForRequirement(api, requirementId) {
373
+ const pageSize = 100;
374
+ let page = 1;
375
+ const rows = [];
376
+ while (true) {
377
+ const batch = await api.requirementArtifact.list({
378
+ requirementId,
379
+ page,
380
+ pageSize
381
+ });
382
+ rows.push(...batch.items);
383
+ if (batch.total === 0 || rows.length >= batch.total) break;
384
+ page += 1;
385
+ }
386
+ for (const row of rows) {
387
+ await api.requirementArtifact.delete({ artifactId: row.id });
388
+ }
389
+ return rows.length;
390
+ }
391
+ async function runUploadArtifact(requirementId, workspaceDir) {
392
+ const cfg = await ensureLoggedConfig();
393
+ const api = createApmApiClient(cfg);
394
+ const root = requirementWorkitemsDir(requirementId, workspaceDir);
395
+ if (!existsSync2(root)) {
396
+ console.error(
397
+ `[apm] \u76EE\u5F55\u4E0D\u5B58\u5728: ${root}
398
+ \u8BF7\u5148\u6267\u884C: apm pull ${requirementId}`
399
+ );
400
+ process.exit(1);
401
+ }
402
+ const deleted = await deleteAllArtifactsForRequirement(api, requirementId);
403
+ console.log(`[apm] \u5DF2\u6E05\u7A7A\u9700\u6C42\u4EA7\u7269\u6587\u6863 ${deleted} \u6761`);
404
+ const paths = [...walkMarkdownFiles(root)];
405
+ let created = 0;
406
+ let skipped = 0;
407
+ for (const abs of paths) {
408
+ const relPosix = toPosixRelative(root, abs);
409
+ if (EXCLUDED_RELATIVE_PATHS.has(relPosix)) {
410
+ skipped += 1;
411
+ console.log(`[apm] \u8DF3\u8FC7\uFF08\u6392\u9664\u5217\u8868\uFF09: ${relPosix}`);
412
+ continue;
413
+ }
414
+ const content = readFileSync3(abs, "utf8");
415
+ const tag = artifactTagFromRelPath(relPosix);
416
+ await api.requirementArtifact.create({
417
+ requirementId,
418
+ tag,
419
+ fileName: relPosix,
420
+ content
421
+ });
422
+ created += 1;
423
+ console.log(`[apm] \u5DF2\u4E0A\u4F20\u4EA7\u7269: ${relPosix} (tag=${tag})`);
424
+ }
425
+ console.log(
426
+ `[apm] \u5B8C\u6210\uFF1A\u5220\u9664 ${deleted}\uFF0C\u65B0\u5EFA ${created}\uFF0C\u8DF3\u8FC7\uFF08\u6392\u9664\uFF09 ${skipped}\uFF0C\u5171\u626B\u63CF ${paths.length} \u4E2A Markdown \u6587\u4EF6`
427
+ );
428
+ }
429
+
430
+ // src/commands/pull.ts
431
+ import { writeFileSync as writeFileSync2 } from "fs";
432
+ import { join as join4 } from "path";
433
+ import { stringify as yamlStringify } from "yaml";
434
+ function valueToXmlContent(value) {
435
+ if (value === null || value === void 0) return "";
436
+ if (typeof value === "string") return xmlEscape(value);
437
+ if (typeof value === "number" || typeof value === "boolean") {
438
+ return xmlEscape(String(value));
439
+ }
440
+ return `<![CDATA[${JSON.stringify(value)}]]>`;
441
+ }
442
+ function recordToXmlLines(record, indent) {
443
+ const lines = [];
444
+ for (const [rawKey, val] of Object.entries(record)) {
445
+ const key = /^[a-zA-Z_][\w.-]*$/.test(rawKey) ? rawKey : "field";
446
+ lines.push(`${indent}<${key}>${valueToXmlContent(val)}</${key}>`);
447
+ }
448
+ return lines;
449
+ }
450
+ function unknownArrayToXml(rootName, itemName, items) {
451
+ const lines = [`<${rootName}>`];
452
+ items.forEach((item, index) => {
453
+ if (item !== null && typeof item === "object" && !Array.isArray(item)) {
454
+ lines.push(` <${itemName} index="${index}">`);
455
+ lines.push(...recordToXmlLines(item, " "));
456
+ lines.push(` </${itemName}>`);
457
+ } else {
458
+ lines.push(
459
+ ` <${itemName} index="${index}">${valueToXmlContent(
460
+ item
461
+ )}</${itemName}>`
462
+ );
463
+ }
464
+ });
465
+ lines.push(`</${rootName}>`, "");
466
+ return lines.join("\n");
467
+ }
468
+ function tasksForStatusYaml(tasks) {
469
+ return tasks.map((t) => ({
470
+ id: t.id,
471
+ title: t.title,
472
+ status: t.status,
473
+ executor: t.executorType
474
+ }));
475
+ }
476
+ function escapeForCdata(text) {
477
+ return text.replace(/\]\]>/g, "]]]]><![CDATA[>");
478
+ }
479
+ function defectsToXml(defects) {
480
+ const sorted = [...defects].sort(
481
+ (a, b) => new Date(a.createdAt ?? 0).getTime() - new Date(b.createdAt ?? 0).getTime()
482
+ );
483
+ const lines = ["<defects>"];
484
+ for (const d of sorted) {
485
+ lines.push(` <defect id="${xmlEscape(d.id)}">`);
486
+ lines.push(` <status>${xmlEscape(d.status)}</status>`);
487
+ lines.push(
488
+ ` <current><![CDATA[${escapeForCdata(
489
+ d.currentState ?? ""
490
+ )}]]></current>`
491
+ );
492
+ lines.push(
493
+ ` <expected><![CDATA[${escapeForCdata(
494
+ d.expectedEffect ?? ""
495
+ )}]]></expected>`
496
+ );
497
+ lines.push(` </defect>`);
498
+ }
499
+ lines.push("</defects>", "");
500
+ return lines.join("\n");
501
+ }
502
+ async function runPull(requirementId, workspaceDir) {
503
+ const cfg = await ensureLoggedConfig();
504
+ const api = createApmApiClient(cfg);
505
+ const data = await api.cliRequirements.pull({ requirementId });
506
+ const WORKITEMS_DIR = requirementWorkitemsDir(requirementId, workspaceDir);
507
+ await ensureDirExists(WORKITEMS_DIR);
508
+ const req2 = data.requirement;
509
+ const statusYaml = yamlStringify(
510
+ {
511
+ id: req2.id,
512
+ status: req2.status,
513
+ title: req2.title,
514
+ env: req2.envName || "",
515
+ tasks: tasksForStatusYaml(data.tasks ?? [])
516
+ },
517
+ { lineWidth: 0 }
518
+ );
519
+ writeFileSync2(
520
+ join4(WORKITEMS_DIR, "requirement-status.yaml"),
521
+ statusYaml.endsWith("\n") ? statusYaml : `${statusYaml}
522
+ `,
523
+ "utf8"
524
+ );
525
+ writeFileSync2(join4(WORKITEMS_DIR, "prd.md"), req2.content || "", "utf8");
526
+ const reviews = data.reviews ?? [];
527
+ const reviewsXml = [
528
+ "<reviews>",
529
+ ...reviews.map((r) => {
530
+ return [
531
+ ` <review id="${xmlEscape(r.id)}">`,
532
+ ` <model>${xmlEscape(r.model ?? "")}</model>`,
533
+ ` <content>`,
534
+ `${xmlEscape(r.content ?? "")}`,
535
+ ` </content>`,
536
+ ` <reply>`,
537
+ `${xmlEscape(r.reply ?? "")}`,
538
+ ` </reply>`,
539
+ " </review>"
540
+ ].join("\n");
541
+ }),
542
+ "</reviews>",
543
+ ""
544
+ ].join("\n");
545
+ writeFileSync2(join4(WORKITEMS_DIR, "reviews.xml"), reviewsXml, "utf8");
546
+ const defectsXml = defectsToXml(data.defects ?? []);
547
+ writeFileSync2(join4(WORKITEMS_DIR, "defect.xml"), defectsXml, "utf8");
548
+ const testCasesXml = unknownArrayToXml(
549
+ "testcases",
550
+ "case",
551
+ data.testCases ?? []
552
+ );
553
+ writeFileSync2(join4(WORKITEMS_DIR, "testcase.xml"), testCasesXml, "utf8");
554
+ return WORKITEMS_DIR;
555
+ }
556
+
332
557
  // src/commands/connect.ts
333
558
  function runConnect(opts) {
334
559
  void (async () => {
@@ -372,11 +597,10 @@ function runConnect(opts) {
372
597
  return;
373
598
  }
374
599
  const payload = msg.payload;
600
+ const apmRoot = join5(payload.cwd, ".apm");
601
+ console.log("[apm] ROOT:", apmRoot);
375
602
  try {
376
- execSync(`apm pull ${payload.requirementId}`, {
377
- cwd: payload.cwd,
378
- encoding: "utf8"
379
- });
603
+ await runPull(payload.requirementId, apmRoot);
380
604
  } catch (pullErr) {
381
605
  console.error("[apm] apm pull \u5931\u8D25:", pullErr);
382
606
  throw pullErr;
@@ -455,10 +679,7 @@ function runConnect(opts) {
455
679
  console.log("[Done]");
456
680
  session.writeToFile(payload.cwd, payload.requirementId, run.agentId);
457
681
  try {
458
- execSync(`apm upload-artifact ${payload.requirementId}`, {
459
- cwd: payload.cwd,
460
- encoding: "utf8"
461
- });
682
+ await runUploadArtifact(payload.requirementId, apmRoot);
462
683
  } catch (pullErr) {
463
684
  console.error("[apm] apm upload-artifact \u5931\u8D25:", pullErr);
464
685
  throw pullErr;
@@ -478,17 +699,17 @@ function runConnect(opts) {
478
699
  }
479
700
 
480
701
  // src/commands/init.ts
481
- import { join as join3 } from "path";
482
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
702
+ import { join as join6 } from "path";
703
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
483
704
  async function runInit(name) {
484
705
  await ensureWorkspaceApmDirForInit();
485
706
  await copyTemplateFiles(WORKSPACE_APM_DIR);
486
707
  if (name) {
487
- const apmConfigPath = join3(WORKSPACE_APM_DIR, "apm.config.json");
488
- const config = readFileSync3(apmConfigPath, "utf8");
708
+ const apmConfigPath = join6(WORKSPACE_APM_DIR, "apm.config.json");
709
+ const config = readFileSync4(apmConfigPath, "utf8");
489
710
  const configJson = JSON.parse(config);
490
711
  configJson.name = name;
491
- writeFileSync2(apmConfigPath, JSON.stringify(configJson, null, 2), "utf8");
712
+ writeFileSync3(apmConfigPath, JSON.stringify(configJson, null, 2), "utf8");
492
713
  }
493
714
  }
494
715
 
@@ -539,13 +760,13 @@ async function runLogin(opts) {
539
760
 
540
761
  // src/commands/branch.ts
541
762
  import { execFile } from "child_process";
542
- import { resolve as resolve3 } from "path";
763
+ import { resolve as resolve4 } from "path";
543
764
  import { promisify } from "util";
544
765
  var execFileAsync = promisify(execFile);
545
766
  async function fetchBaselineBranchFromApi(requirementId, cwd) {
546
767
  const cfg = await ensureLoggedConfig();
547
768
  const api = createApmApiClient(cfg);
548
- const workdirPath = resolve3(cwd);
769
+ const workdirPath = resolve4(cwd);
549
770
  const { baselineBranch } = await api.cliRequirements.branchBaseline({
550
771
  requirementId,
551
772
  workdirPath
@@ -675,134 +896,13 @@ async function runBranch(requirementId, options = {}) {
675
896
  return branch;
676
897
  }
677
898
 
678
- // src/commands/pull.ts
679
- import { writeFileSync as writeFileSync3 } from "fs";
680
- import { join as join4 } from "path";
681
- import { stringify as yamlStringify } from "yaml";
682
- function valueToXmlContent(value) {
683
- if (value === null || value === void 0) return "";
684
- if (typeof value === "string") return xmlEscape(value);
685
- if (typeof value === "number" || typeof value === "boolean") {
686
- return xmlEscape(String(value));
687
- }
688
- return `<![CDATA[${JSON.stringify(value)}]]>`;
689
- }
690
- function recordToXmlLines(record, indent) {
691
- const lines = [];
692
- for (const [rawKey, val] of Object.entries(record)) {
693
- const key = /^[a-zA-Z_][\w.-]*$/.test(rawKey) ? rawKey : "field";
694
- lines.push(`${indent}<${key}>${valueToXmlContent(val)}</${key}>`);
695
- }
696
- return lines;
697
- }
698
- function unknownArrayToXml(rootName, itemName, items) {
699
- const lines = [`<${rootName}>`];
700
- items.forEach((item, index) => {
701
- if (item !== null && typeof item === "object" && !Array.isArray(item)) {
702
- lines.push(` <${itemName} index="${index}">`);
703
- lines.push(...recordToXmlLines(item, " "));
704
- lines.push(` </${itemName}>`);
705
- } else {
706
- lines.push(
707
- ` <${itemName} index="${index}">${valueToXmlContent(
708
- item
709
- )}</${itemName}>`
710
- );
711
- }
712
- });
713
- lines.push(`</${rootName}>`, "");
714
- return lines.join("\n");
715
- }
716
- function tasksForStatusYaml(tasks) {
717
- return tasks.map((t) => ({
718
- id: t.id,
719
- title: t.title,
720
- status: t.status,
721
- executor: t.executorType
722
- }));
723
- }
724
- function escapeForCdata(text) {
725
- return text.replace(/\]\]>/g, "]]]]><![CDATA[>");
726
- }
727
- function defectsToXml(defects) {
728
- const sorted = [...defects].sort(
729
- (a, b) => new Date(a.createdAt ?? 0).getTime() - new Date(b.createdAt ?? 0).getTime()
730
- );
731
- const lines = ["<defects>"];
732
- for (const d of sorted) {
733
- lines.push(` <defect id="${xmlEscape(d.id)}">`);
734
- lines.push(` <status>${xmlEscape(d.status)}</status>`);
735
- lines.push(` <current><![CDATA[${escapeForCdata(d.currentState ?? "")}]]></current>`);
736
- lines.push(
737
- ` <expected><![CDATA[${escapeForCdata(d.expectedEffect ?? "")}]]></expected>`
738
- );
739
- lines.push(` </defect>`);
740
- }
741
- lines.push("</defects>", "");
742
- return lines.join("\n");
743
- }
744
- async function runPull(requirementId) {
745
- const cfg = await ensureLoggedConfig();
746
- const api = createApmApiClient(cfg);
747
- const data = await api.cliRequirements.pull({ requirementId });
748
- const WORKITEMS_DIR = requirementWorkitemsDir(requirementId);
749
- await ensureDirExists(WORKITEMS_DIR);
750
- const req2 = data.requirement;
751
- const statusYaml = yamlStringify(
752
- {
753
- id: req2.id,
754
- status: req2.status,
755
- title: req2.title,
756
- env: req2.envName || "",
757
- tasks: tasksForStatusYaml(data.tasks ?? [])
758
- },
759
- { lineWidth: 0 }
760
- );
761
- writeFileSync3(
762
- join4(WORKITEMS_DIR, "requirement-status.yaml"),
763
- statusYaml.endsWith("\n") ? statusYaml : `${statusYaml}
764
- `,
765
- "utf8"
766
- );
767
- writeFileSync3(join4(WORKITEMS_DIR, "prd.md"), req2.content || "", "utf8");
768
- const reviews = data.reviews ?? [];
769
- const reviewsXml = [
770
- "<reviews>",
771
- ...reviews.map((r) => {
772
- return [
773
- ` <review id="${xmlEscape(r.id)}">`,
774
- ` <model>${xmlEscape(r.model ?? "")}</model>`,
775
- ` <content>`,
776
- `${xmlEscape(r.content ?? "")}`,
777
- ` </content>`,
778
- ` <reply>`,
779
- `${xmlEscape(r.reply ?? "")}`,
780
- ` </reply>`,
781
- " </review>"
782
- ].join("\n");
783
- }),
784
- "</reviews>",
785
- ""
786
- ].join("\n");
787
- writeFileSync3(join4(WORKITEMS_DIR, "reviews.xml"), reviewsXml, "utf8");
788
- const defectsXml = defectsToXml(data.defects ?? []);
789
- writeFileSync3(join4(WORKITEMS_DIR, "defect.xml"), defectsXml, "utf8");
790
- const testCasesXml = unknownArrayToXml(
791
- "testcases",
792
- "case",
793
- data.testCases ?? []
794
- );
795
- writeFileSync3(join4(WORKITEMS_DIR, "testcase.xml"), testCasesXml, "utf8");
796
- return WORKITEMS_DIR;
797
- }
798
-
799
899
  // src/commands/refine.ts
800
- import { readFileSync as readFileSync4 } from "fs";
801
- import { join as join5 } from "path";
900
+ import { readFileSync as readFileSync5 } from "fs";
901
+ import { join as join7 } from "path";
802
902
  async function runRefine(requirementId) {
803
903
  const cfg = await ensureLoggedConfig();
804
- const filePath = join5(WORKSPACE_APM_DIR, "workitems", requirementId, "prd.md");
805
- const content = readFileSync4(filePath, "utf8");
904
+ const filePath = join7(WORKSPACE_APM_DIR, "workitems", requirementId, "prd.md");
905
+ const content = readFileSync5(filePath, "utf8");
806
906
  const api = createApmApiClient(cfg);
807
907
  const data = await api.cliRequirements.refine({ requirementId, content });
808
908
  console.log(JSON.stringify(data, null, 2));
@@ -830,111 +930,16 @@ async function runUpdateStatus(requirementId, status) {
830
930
  console.log(JSON.stringify(data, null, 2));
831
931
  }
832
932
 
833
- // src/commands/upload-artifact.ts
834
- import { existsSync as existsSync2, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
835
- import { join as join6, relative, sep } from "path";
836
- var EXCLUDED_RELATIVE_PATHS = /* @__PURE__ */ new Set([
837
- "defect.xml",
838
- "prd.md",
839
- "requirement-status.yaml",
840
- "reviews.xml",
841
- "testcase.xml"
842
- ]);
843
- function toPosixRelative(root, absoluteFile) {
844
- return relative(root, absoluteFile).split(sep).join("/");
845
- }
846
- function artifactTagFromRelPath(relPosix) {
847
- const parts = relPosix.split("/");
848
- const fileName = parts[parts.length - 1] ?? relPosix;
849
- if (parts.length > 1) {
850
- return parts[0] ?? fileName;
851
- }
852
- const dot = fileName.lastIndexOf(".");
853
- return dot > 0 ? fileName.slice(0, dot) : fileName;
854
- }
855
- function* walkMarkdownFiles(dir) {
856
- const names = readdirSync2(dir);
857
- for (const name of names) {
858
- if (name.startsWith(".")) continue;
859
- const full = join6(dir, name);
860
- const st = statSync2(full);
861
- if (st.isDirectory()) {
862
- yield* walkMarkdownFiles(full);
863
- continue;
864
- }
865
- if (!st.isFile()) continue;
866
- if (!name.toLowerCase().endsWith(".md")) continue;
867
- yield full;
868
- }
869
- }
870
- async function deleteAllArtifactsForRequirement(api, requirementId) {
871
- const pageSize = 100;
872
- let page = 1;
873
- const rows = [];
874
- while (true) {
875
- const batch = await api.requirementArtifact.list({
876
- requirementId,
877
- page,
878
- pageSize
879
- });
880
- rows.push(...batch.items);
881
- if (batch.total === 0 || rows.length >= batch.total) break;
882
- page += 1;
883
- }
884
- for (const row of rows) {
885
- await api.requirementArtifact.delete({ artifactId: row.id });
886
- }
887
- return rows.length;
888
- }
889
- async function runUploadArtifact(requirementId) {
890
- const cfg = await ensureLoggedConfig();
891
- const api = createApmApiClient(cfg);
892
- const root = requirementWorkitemsDir(requirementId);
893
- if (!existsSync2(root)) {
894
- console.error(
895
- `[apm] \u76EE\u5F55\u4E0D\u5B58\u5728: ${root}
896
- \u8BF7\u5148\u6267\u884C: apm pull ${requirementId}`
897
- );
898
- process.exit(1);
899
- }
900
- const deleted = await deleteAllArtifactsForRequirement(api, requirementId);
901
- console.log(`[apm] \u5DF2\u6E05\u7A7A\u9700\u6C42\u4EA7\u7269\u6587\u6863 ${deleted} \u6761`);
902
- const paths = [...walkMarkdownFiles(root)];
903
- let created = 0;
904
- let skipped = 0;
905
- for (const abs of paths) {
906
- const relPosix = toPosixRelative(root, abs);
907
- if (EXCLUDED_RELATIVE_PATHS.has(relPosix)) {
908
- skipped += 1;
909
- console.log(`[apm] \u8DF3\u8FC7\uFF08\u6392\u9664\u5217\u8868\uFF09: ${relPosix}`);
910
- continue;
911
- }
912
- const content = readFileSync5(abs, "utf8");
913
- const tag = artifactTagFromRelPath(relPosix);
914
- await api.requirementArtifact.create({
915
- requirementId,
916
- tag,
917
- fileName: relPosix,
918
- content
919
- });
920
- created += 1;
921
- console.log(`[apm] \u5DF2\u4E0A\u4F20\u4EA7\u7269: ${relPosix} (tag=${tag})`);
922
- }
923
- console.log(
924
- `[apm] \u5B8C\u6210\uFF1A\u5220\u9664 ${deleted}\uFF0C\u65B0\u5EFA ${created}\uFF0C\u8DF3\u8FC7\uFF08\u6392\u9664\uFF09 ${skipped}\uFF0C\u5171\u626B\u63CF ${paths.length} \u4E2A Markdown \u6587\u4EF6`
925
- );
926
- }
927
-
928
933
  // src/commands/deploy/backend.ts
929
934
  import path5 from "node:path";
930
935
 
931
936
  // src/commands/deploy/lib/apm-config.ts
932
937
  import { existsSync as existsSync3, readFileSync as readFileSync6 } from "node:fs";
933
- import { resolve as resolve4 } from "node:path";
938
+ import { resolve as resolve5 } from "node:path";
934
939
  function loadApmConfig(options) {
935
- const p = resolve4(
940
+ const p = resolve5(
936
941
  process.cwd(),
937
- options?.configPath ?? resolve4(WORKSPACE_APM_DIR, "apm.config.json")
942
+ options?.configPath ?? resolve5(WORKSPACE_APM_DIR, "apm.config.json")
938
943
  );
939
944
  if (!existsSync3(p)) {
940
945
  console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
@@ -1178,17 +1183,17 @@ var DockerodeClient = class {
1178
1183
  await this.client.getImage(image).remove({ force: true });
1179
1184
  }
1180
1185
  async pullImage(image, auth) {
1181
- const stream = await new Promise((resolve5, reject) => {
1186
+ const stream = await new Promise((resolve6, reject) => {
1182
1187
  const pullOptions = auth ? { authconfig: auth } : void 0;
1183
1188
  this.client.pull(image, pullOptions, (err, output) => {
1184
1189
  if (err || !output) {
1185
1190
  reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
1186
1191
  return;
1187
1192
  }
1188
- resolve5(output);
1193
+ resolve6(output);
1189
1194
  });
1190
1195
  });
1191
- await new Promise((resolve5, reject) => {
1196
+ await new Promise((resolve6, reject) => {
1192
1197
  this.client.modem.followProgress(
1193
1198
  stream,
1194
1199
  (err) => {
@@ -1196,7 +1201,7 @@ var DockerodeClient = class {
1196
1201
  reject(err);
1197
1202
  return;
1198
1203
  }
1199
- resolve5();
1204
+ resolve6();
1200
1205
  },
1201
1206
  () => void 0
1202
1207
  );
@@ -1341,7 +1346,7 @@ function assertDeployImageTag(tag) {
1341
1346
  import { platform } from "node:os";
1342
1347
 
1343
1348
  // src/commands/deploy/lib/backend-deploy/command-runner.ts
1344
- import { execSync as execSync2 } from "child_process";
1349
+ import { execSync } from "child_process";
1345
1350
 
1346
1351
  // src/commands/deploy/lib/backend-deploy/logger.ts
1347
1352
  var Logger = class {
@@ -1367,7 +1372,7 @@ var CommandRunner = class {
1367
1372
  static exec(command, cwd) {
1368
1373
  try {
1369
1374
  Logger.info(`\u6267\u884C\u547D\u4EE4: ${command}`);
1370
- const result = execSync2(command, {
1375
+ const result = execSync(command, {
1371
1376
  cwd,
1372
1377
  encoding: "utf8",
1373
1378
  stdio: "pipe"
@@ -1385,7 +1390,7 @@ var CommandRunner = class {
1385
1390
  static execWithOutput(command, cwd) {
1386
1391
  try {
1387
1392
  Logger.info(`\u6267\u884C\u547D\u4EE4: ${command}`);
1388
- execSync2(command, {
1393
+ execSync(command, {
1389
1394
  cwd,
1390
1395
  stdio: "inherit"
1391
1396
  });
@@ -1579,9 +1584,9 @@ import path7 from "node:path";
1579
1584
 
1580
1585
  // src/commands/deploy/lib/load-apm-dotenv.ts
1581
1586
  import { existsSync as existsSync7, readFileSync as readFileSync9 } from "node:fs";
1582
- import { join as join7 } from "node:path";
1587
+ import { join as join8 } from "node:path";
1583
1588
  function loadApmDotEnvIfPresent() {
1584
- const p = join7(WORKSPACE_APM_DIR, ".env");
1589
+ const p = join8(WORKSPACE_APM_DIR, ".env");
1585
1590
  if (!existsSync7(p)) {
1586
1591
  return;
1587
1592
  }
@@ -1712,14 +1717,14 @@ var MinioClient = class {
1712
1717
  async deleteObjectsByPrefix(bucket, prefix) {
1713
1718
  const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
1714
1719
  const keys = [];
1715
- await new Promise((resolve5, reject) => {
1720
+ await new Promise((resolve6, reject) => {
1716
1721
  objectsStream.on("data", (obj) => {
1717
1722
  if (obj.name) {
1718
1723
  keys.push(obj.name);
1719
1724
  }
1720
1725
  });
1721
1726
  objectsStream.on("error", reject);
1722
- objectsStream.on("end", resolve5);
1727
+ objectsStream.on("end", resolve6);
1723
1728
  });
1724
1729
  const chunkSize = 500;
1725
1730
  for (let i = 0; i < keys.length; i += chunkSize) {
@@ -1946,7 +1951,7 @@ function registerDeployCommands(program) {
1946
1951
  function readCliVersion() {
1947
1952
  try {
1948
1953
  const dir = dirname2(fileURLToPath2(import.meta.url));
1949
- const pkgPath = join8(dir, "..", "package.json");
1954
+ const pkgPath = join9(dir, "..", "package.json");
1950
1955
  const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
1951
1956
  return pkg.version ?? "0.0.0";
1952
1957
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "3.0.17",
3
+ "version": "3.0.19",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,