ai-project-manage-cli 6.0.85 → 6.0.87

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,6 +32,7 @@ apm sync-project-documents --push
32
32
  apm update-skills
33
33
  apm branch <sessionId>
34
34
  apm branch prune [--dry-run] [-A|--all]
35
+ apm create-pr --session <sessionId> --title "<标题>" [--content "<正文>"]
35
36
  ```
36
37
 
37
38
  ## 常驻连接(后台守护)
package/dist/index.js CHANGED
@@ -2483,7 +2483,7 @@ async function fetchDeployArtifactStorage(api) {
2483
2483
  }
2484
2484
  async function uploadDeployArtifactZip(options) {
2485
2485
  const deploymentRunId = options.deploymentRunId ?? resolveDeploymentRunIdFromEnv();
2486
- if (!deploymentRunId) {
2486
+ if (!deploymentRunId && !options.uploadWithoutRunId) {
2487
2487
  return null;
2488
2488
  }
2489
2489
  const cfg = await tryReadApmConfig();
@@ -2527,26 +2527,30 @@ async function uploadDeployArtifactZip(options) {
2527
2527
  "Content-Type": "application/zip"
2528
2528
  });
2529
2529
  console.error(
2530
- `[apm] \u5DF2\u5F52\u6863\u90E8\u7F72\u4EA7\u7269: ${storage.bucket}/${objectKey} (${(body.length / 1024 / 1024).toFixed(2)} MB)`
2530
+ `[apm] \u672C\u5730\u76F4\u4F20 MinIO\uFF08\u4E0D\u7ECF\u5E73\u53F0\u670D\u52A1\u5668\uFF09: ${storage.endpoint}:${storage.port}/${storage.bucket}/${objectKey} (${(body.length / 1024 / 1024).toFixed(
2531
+ 2
2532
+ )} MB)`
2531
2533
  );
2532
2534
  } catch (error) {
2533
2535
  const detail = error instanceof Error ? error.message : String(error);
2534
2536
  console.warn(`[apm] MinIO \u90E8\u7F72\u4EA7\u7269\u5F52\u6863\u5931\u8D25: ${detail}`);
2535
2537
  return null;
2536
2538
  }
2537
- try {
2538
- await api.cli.attachTaskDeploymentArtifact({
2539
- id: deploymentRunId,
2540
- artifactObjectKey: objectKey,
2541
- artifactFileName: fileName
2542
- });
2543
- console.error(
2544
- `[apm] \u5DF2\u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55 id=${deploymentRunId} file=${fileName}`
2545
- );
2546
- } catch (error) {
2547
- const detail = error instanceof Error ? error.message : String(error);
2548
- console.warn(`[apm] \u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55\u5931\u8D25: ${detail}`);
2549
- return null;
2539
+ if (deploymentRunId) {
2540
+ try {
2541
+ await api.cli.attachTaskDeploymentArtifact({
2542
+ id: deploymentRunId,
2543
+ artifactObjectKey: objectKey,
2544
+ artifactFileName: fileName
2545
+ });
2546
+ console.error(
2547
+ `[apm] \u5DF2\u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55 id=${deploymentRunId} file=${fileName}`
2548
+ );
2549
+ } catch (error) {
2550
+ const detail = error instanceof Error ? error.message : String(error);
2551
+ console.warn(`[apm] \u7ED1\u5B9A\u90E8\u7F72\u4EA7\u7269\u5230\u8BB0\u5F55\u5931\u8D25: ${detail}`);
2552
+ return null;
2553
+ }
2550
2554
  }
2551
2555
  return {
2552
2556
  objectKey,
@@ -4691,7 +4695,7 @@ var DeployExecutionError = class extends Error {
4691
4695
  };
4692
4696
 
4693
4697
  // src/commands/deploy/internal/wisdom-auto-deploy.ts
4694
- import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
4698
+ import { existsSync as existsSync17, readFileSync as readFileSync14, statSync as statSync7 } from "node:fs";
4695
4699
  import path4 from "node:path";
4696
4700
  import { spawnSync as spawnSync4 } from "node:child_process";
4697
4701
 
@@ -4835,19 +4839,30 @@ async function uploadAndMaybeExtract(settings, localZip, extract) {
4835
4839
  async function runWisdomSftpDeploy(params) {
4836
4840
  const zipPath = path2.join(params.localDir, "..", ".deploy-sftp-dist.zip");
4837
4841
  const resolvedZipPath = path2.resolve(zipPath);
4842
+ const packOnly = Boolean(params.packOnly);
4838
4843
  let zipSizeBytes = 0;
4844
+ let artifactUploaded = false;
4839
4845
  try {
4840
4846
  zipSizeBytes = await zipDirectory(params.localDir, resolvedZipPath);
4841
- await uploadAndMaybeExtract(
4842
- params.settings,
4843
- resolvedZipPath,
4844
- params.extract
4845
- );
4846
- await uploadDeployArtifactZip({
4847
+ if (!packOnly) {
4848
+ await uploadAndMaybeExtract(
4849
+ params.settings,
4850
+ resolvedZipPath,
4851
+ params.extract
4852
+ );
4853
+ } else {
4854
+ console.error("[apm] \u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u8DF3\u8FC7 SFTP \u8FDC\u7A0B\u4E0A\u4F20");
4855
+ }
4856
+ const artifact = await uploadDeployArtifactZip({
4847
4857
  zipPath: resolvedZipPath,
4848
4858
  projectName: params.projectName,
4849
- kind: "frontend"
4859
+ kind: "frontend",
4860
+ uploadWithoutRunId: packOnly
4850
4861
  });
4862
+ artifactUploaded = artifact !== null;
4863
+ if (packOnly && artifactUploaded) {
4864
+ console.error("\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09");
4865
+ }
4851
4866
  } finally {
4852
4867
  try {
4853
4868
  await unlink(resolvedZipPath);
@@ -4861,7 +4876,9 @@ async function runWisdomSftpDeploy(params) {
4861
4876
  host: params.settings.host,
4862
4877
  remotePath: params.settings.remotePath,
4863
4878
  zipSizeBytes,
4864
- extracted: params.extract
4879
+ extracted: packOnly ? false : params.extract,
4880
+ packOnly,
4881
+ artifactUploaded
4865
4882
  };
4866
4883
  }
4867
4884
 
@@ -5385,19 +5402,63 @@ async function restartRemoteService(client, config) {
5385
5402
  const script = buildRemoteRestartScript(config.remoteAppDir);
5386
5403
  await runRemoteServiceScript(client, script, "restart");
5387
5404
  }
5405
+ function listAllLibFilesForArchive(libDir) {
5406
+ return readdirSync5(libDir).filter((name) => name.endsWith(".jar")).sort().map((jarName) => ({
5407
+ path: path3.join(libDir, jarName),
5408
+ arcname: jarName,
5409
+ reason: "\u4EC5\u6253\u5305\u5F52\u6863"
5410
+ }));
5411
+ }
5388
5412
  async function runWisdomBackendDeploy(options) {
5389
5413
  const projectRoot = path3.resolve(options.projectRoot ?? process.cwd());
5390
5414
  const config = options.config;
5415
+ const packOnly = Boolean(options.packOnly);
5391
5416
  log(`=== \u81EA\u52A8\u90E8\u7F72: ${config.projectName} ===`);
5392
5417
  log(`\u914D\u7F6E\u6587\u4EF6: ${path3.join(workspaceApmDir(), "apm.config.json")}`);
5393
5418
  log(`\u9879\u76EE\u6839\u76EE\u5F55: ${projectRoot}`);
5394
5419
  log(
5395
- `\u90E8\u7F72\u6A21\u5F0F: ${config.mode}${config.mode === "full" ? "\uFF08\u5168\u91CF JAR\uFF0C\u8DF3\u8FC7 lib \u68C0\u67E5\uFF09" : "\uFF08\u589E\u91CF lib \u66F4\u65B0\uFF09"}`
5420
+ `\u90E8\u7F72\u6A21\u5F0F: ${config.mode}${config.mode === "full" ? "\uFF08\u5168\u91CF JAR\uFF0C\u8DF3\u8FC7 lib \u68C0\u67E5\uFF09" : "\uFF08\u589E\u91CF lib \u66F4\u65B0\uFF09"}${packOnly ? "\uFF1B\u4EC5\u6253\u5305\uFF08\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\uFF09" : ""}`
5396
5421
  );
5397
5422
  runMavenBuild(projectRoot, config.mavenLocalRepo, {
5398
5423
  source: config.mavenLocalRepoSource,
5399
5424
  sourceDetail: config.mavenLocalRepoSourceDetail
5400
5425
  });
5426
+ if (packOnly) {
5427
+ if (config.mode === "full") {
5428
+ const mainJar = locateMainJar(projectRoot);
5429
+ const archiveZipPath = await createUpdatePackage(
5430
+ [
5431
+ {
5432
+ path: mainJar,
5433
+ arcname: path3.basename(mainJar),
5434
+ reason: "\u5168\u91CF JAR \u5F52\u6863"
5435
+ }
5436
+ ],
5437
+ `.deploy-archive-${config.projectName}.jar.zip`
5438
+ );
5439
+ await uploadDeployArtifactZip({
5440
+ zipPath: archiveZipPath,
5441
+ projectName: config.projectName,
5442
+ kind: "backend",
5443
+ uploadWithoutRunId: true
5444
+ });
5445
+ } else {
5446
+ const libDir = locateLibDir(projectRoot);
5447
+ const entries = listAllLibFilesForArchive(libDir);
5448
+ if (entries.length === 0) {
5449
+ fail("lib \u76EE\u5F55\u4E0B\u6CA1\u6709\u53EF\u5F52\u6863\u7684 JAR");
5450
+ }
5451
+ const zipPath = await createUpdatePackage(entries, config.packageName);
5452
+ await uploadDeployArtifactZip({
5453
+ zipPath,
5454
+ projectName: config.projectName,
5455
+ kind: "backend",
5456
+ uploadWithoutRunId: true
5457
+ });
5458
+ }
5459
+ log("\u4EC5\u6253\u5305\u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09");
5460
+ return;
5461
+ }
5401
5462
  const conn = await connectSsh(config);
5402
5463
  try {
5403
5464
  if (config.mode === "full") {
@@ -5543,14 +5604,48 @@ function runShellCommand2(command, cwd, captureOutput) {
5543
5604
  }
5544
5605
  return output;
5545
5606
  }
5607
+ function resolveFrontendDistDir(cwd) {
5608
+ const candidates = ["dist", "apps/web/dist"];
5609
+ for (const rel of candidates) {
5610
+ const full = path4.join(cwd, rel);
5611
+ try {
5612
+ if (existsSync17(full) && statSync7(full).isDirectory()) {
5613
+ return full;
5614
+ }
5615
+ } catch {
5616
+ }
5617
+ }
5618
+ return path4.join(cwd, "dist");
5619
+ }
5546
5620
  async function runWisdomAutoDeploy(options) {
5547
5621
  const cwd = path4.resolve(options.cwd ?? process.cwd());
5548
5622
  const captureOutput = options.captureOutput ?? false;
5623
+ const packOnly = Boolean(options.packOnly);
5549
5624
  const projectType = detectWisdomProjectType(cwd);
5625
+ const configPath = options.configPath ?? path4.join(workspaceApmDir(cwd), "apm.config.json");
5626
+ const cfg = loadApmConfig({ configPath });
5550
5627
  console.error(
5551
- `[apm] \u533B\u52A1\u5B58\u91CF\u9879\u76EE\u81EA\u52A8\u8BC6\u522B: ${projectType === "frontend" ? "\u524D\u7AEF Vue" : "\u540E\u7AEF Java"}`
5628
+ `[apm] \u533B\u52A1\u5B58\u91CF\u9879\u76EE\u81EA\u52A8\u8BC6\u522B: ${projectType === "frontend" ? "\u524D\u7AEF Vue" : "\u540E\u7AEF Java"}${packOnly ? "\uFF08\u4EC5\u6253\u5305\u6A21\u5F0F\uFF09" : ""}`
5552
5629
  );
5553
5630
  if (projectType === "frontend") {
5631
+ if (packOnly) {
5632
+ const projectName = (cfg.name ?? "").trim();
5633
+ if (!projectName) {
5634
+ throw new DeployExecutionError(
5635
+ "\u8BF7\u5728 .apm/apm.config.json \u9876\u5C42\u914D\u7F6E name\uFF08\u4F5C\u4E3A\u90E8\u7F72\u4EA7\u7269\u9879\u76EE\u540D\uFF09",
5636
+ 1
5637
+ );
5638
+ }
5639
+ const settings2 = resolveWisdomDeployFromApmConfig(cfg);
5640
+ await runWisdomSftpDeploy({
5641
+ localDir: resolveFrontendDistDir(cwd),
5642
+ settings: settings2,
5643
+ extract: false,
5644
+ projectName,
5645
+ packOnly: true
5646
+ });
5647
+ return { projectType };
5648
+ }
5554
5649
  const deployCmd = resolveFrontendDeployCommand(options.env, cwd);
5555
5650
  if (!deployCmd) {
5556
5651
  const lines = formatWisdomFrontendDeployNotConfiguredLines(
@@ -5562,15 +5657,18 @@ async function runWisdomAutoDeploy(options) {
5562
5657
  runShellCommand2(deployCmd, cwd, captureOutput);
5563
5658
  return { projectType };
5564
5659
  }
5565
- const configPath = options.configPath ?? path4.join(workspaceApmDir(cwd), "apm.config.json");
5566
- const cfg = loadApmConfig({ configPath });
5567
5660
  const settings = resolveWisdomBackendDeployFromApmConfig(cfg);
5568
- console.error(
5569
- `[apm] \u540E\u7AEF\u90E8\u7F72\u4E0D\u533A\u5206 test/online\uFF0C\u5FFD\u7565\u73AF\u5883\u53C2\u6570: ${options.env}`
5570
- );
5661
+ if (packOnly) {
5662
+ console.error(`[apm] \u540E\u7AEF\u4EC5\u6253\u5305\u6A21\u5F0F\uFF0C\u5FFD\u7565\u73AF\u5883\u53C2\u6570: ${options.env}`);
5663
+ } else {
5664
+ console.error(
5665
+ `[apm] \u540E\u7AEF\u90E8\u7F72\u4E0D\u533A\u5206 test/online\uFF0C\u5FFD\u7565\u73AF\u5883\u53C2\u6570: ${options.env}`
5666
+ );
5667
+ }
5571
5668
  await runWisdomBackendDeploy({
5572
5669
  config: settings,
5573
- projectRoot: cwd
5670
+ projectRoot: cwd,
5671
+ packOnly
5574
5672
  });
5575
5673
  return { projectType };
5576
5674
  }
@@ -5749,6 +5847,15 @@ async function executeDeploy(options) {
5749
5847
  const captureOutput = options.captureOutput ?? false;
5750
5848
  const outputParts = [];
5751
5849
  try {
5850
+ const configSyncResult = await syncRemoteDeploymentConfig(
5851
+ cwd,
5852
+ workspaceApmDir(cwd)
5853
+ );
5854
+ if (configSyncResult.synced && configSyncResult.configName) {
5855
+ outputParts.push(
5856
+ `[apm] \u90E8\u7F72\u524D\u5DF2\u540C\u6B65\u5E73\u53F0\u90E8\u7F72\u914D\u7F6E: ${configSyncResult.configName}`
5857
+ );
5858
+ }
5752
5859
  const syncResult = await syncDeployBaselineBeforeDeploy(cwd);
5753
5860
  if (syncResult.log.trim()) {
5754
5861
  outputParts.push(syncResult.log);
@@ -5768,7 +5875,8 @@ async function executeDeploy(options) {
5768
5875
  env: options.env,
5769
5876
  cwd,
5770
5877
  configPath: options.configPath,
5771
- captureOutput
5878
+ captureOutput,
5879
+ packOnly: options.packOnly
5772
5880
  });
5773
5881
  return outputParts.join("\n");
5774
5882
  } catch (error) {
@@ -5916,28 +6024,33 @@ async function runDeployWithBackendTracking(options) {
5916
6024
  // src/commands/deploy/deploy.ts
5917
6025
  function registerDeployMainCommand(program) {
5918
6026
  program.command("deploy").description(
5919
- "\u7EDF\u4E00\u90E8\u7F72\uFF1A\u533B\u52A1\u5B58\u91CF\u81EA\u52A8\u8BC6\u522B\u524D\u540E\u7AEF\uFF08\u524D\u7AEF\u6309 deploy:<env> \u811A\u672C\uFF1B\u540E\u7AEF test/online \u540C\u4E00\u5957\uFF09\uFF1B\u5176\u4ED6\u9879\u76EE\u6309 deploy.<\u73AF\u5883> \u6267\u884C shell \u547D\u4EE4"
6027
+ "\u7EDF\u4E00\u90E8\u7F72\uFF08\u6267\u884C\u524D\u81EA\u52A8\u540C\u6B65\u90E8\u7F72\u914D\u7F6E\u5E76\u5408\u5E76\u57FA\u7EBF\u5206\u652F\uFF09\uFF1A\u533B\u52A1\u5B58\u91CF\u81EA\u52A8\u8BC6\u522B\u524D\u540E\u7AEF\uFF1B\u5176\u4ED6\u9879\u76EE\u6309 deploy.<\u73AF\u5883> \u6267\u884C shell \u547D\u4EE4"
5920
6028
  ).argument("<env>", "\u90E8\u7F72\u73AF\u5883\u540D\uFF08\u5982 test\u3001online\uFF09").option(
5921
6029
  "--config <path>",
5922
6030
  "apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
5923
6031
  ).option(
5924
6032
  "--session <sessionId>",
5925
6033
  "\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7"
6034
+ ).option(
6035
+ "--pack-only",
6036
+ "\u4EC5\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u533B\u52A1\u5B58\u91CF SFTP / Java \u90E8\u7F72\uFF09"
5926
6037
  ).action(
5927
6038
  async (env, opts) => {
5928
6039
  const cwd = process.cwd();
5929
6040
  const sessionId = opts.session?.trim();
6041
+ const packOnly = Boolean(opts.packOnly);
5930
6042
  try {
5931
6043
  if (sessionId) {
5932
6044
  await runDeployWithBackendTracking({
5933
6045
  env,
5934
6046
  cwd,
5935
6047
  configPath: opts.config,
5936
- sessionId
6048
+ sessionId,
6049
+ packOnly
5937
6050
  });
5938
6051
  return;
5939
6052
  }
5940
- await executeDeploy({ env, cwd, configPath: opts.config });
6053
+ await executeDeploy({ env, cwd, configPath: opts.config, packOnly });
5941
6054
  } catch (error) {
5942
6055
  if (error instanceof DeployExecutionError) {
5943
6056
  printDeployExecutionError(error);
@@ -6182,7 +6295,7 @@ var DockerodeClient = class {
6182
6295
  var createDockerodeClient = (config) => new DockerodeClient(config);
6183
6296
 
6184
6297
  // src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
6185
- import { existsSync as existsSync19, readFileSync as readFileSync16, statSync as statSync7 } from "node:fs";
6298
+ import { existsSync as existsSync19, readFileSync as readFileSync16, statSync as statSync8 } from "node:fs";
6186
6299
  import path7 from "node:path";
6187
6300
  function stripSurroundingQuotes(value) {
6188
6301
  const t = value.trim();
@@ -6199,7 +6312,7 @@ function loadEnvFromFile(envFilePath) {
6199
6312
  return {};
6200
6313
  }
6201
6314
  const targetPath = path7.resolve(envFilePath);
6202
- if (!existsSync19(targetPath) || !statSync7(targetPath).isFile()) {
6315
+ if (!existsSync19(targetPath) || !statSync8(targetPath).isFile()) {
6203
6316
  return {};
6204
6317
  }
6205
6318
  const raw = readFileSync16(targetPath, "utf-8");
@@ -6503,7 +6616,7 @@ function registerDeployBackendCommands(program) {
6503
6616
  }
6504
6617
 
6505
6618
  // src/commands/deploy/frontend.ts
6506
- import { copyFile, readdir as readdir3, stat } from "node:fs/promises";
6619
+ import { copyFile, readdir as readdir3, stat, unlink as unlink2 } from "node:fs/promises";
6507
6620
  import path11 from "node:path";
6508
6621
  function resolveArtifactNamePrefix(cfg) {
6509
6622
  const nameRaw = (cfg.name ?? "").trim();
@@ -6567,6 +6680,44 @@ async function ensureArtifactRootIndexHtml(root) {
6567
6680
  );
6568
6681
  process.exit(1);
6569
6682
  }
6683
+ async function runFrontendPackOnlyDeploy(root, namePrefix) {
6684
+ const zipPath = path11.resolve(root, "..", ".deploy-frontend-dist.zip");
6685
+ let zipSizeBytes = 0;
6686
+ let artifactUploaded = false;
6687
+ try {
6688
+ zipSizeBytes = await zipDirectory(root, zipPath);
6689
+ console.error("[apm] \u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u8DF3\u8FC7\u524D\u7AEF\u8BBF\u95EE\u6876\u4E0A\u4F20");
6690
+ const artifact = await uploadDeployArtifactZip({
6691
+ zipPath,
6692
+ projectName: namePrefix,
6693
+ kind: "frontend",
6694
+ uploadWithoutRunId: true
6695
+ });
6696
+ artifactUploaded = artifact !== null;
6697
+ if (artifactUploaded) {
6698
+ console.error("\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u81F3\u524D\u7AEF\u8BBF\u95EE\u6876\uFF09");
6699
+ }
6700
+ console.log(
6701
+ JSON.stringify(
6702
+ {
6703
+ ok: true,
6704
+ packOnly: true,
6705
+ namePrefix,
6706
+ zipSizeBytes,
6707
+ artifactUploaded
6708
+ },
6709
+ null,
6710
+ 2
6711
+ )
6712
+ );
6713
+ } finally {
6714
+ try {
6715
+ await unlink2(zipPath);
6716
+ console.error(`\u5DF2\u6E05\u7406\u672C\u5730\u4E34\u65F6\u6587\u4EF6: ${zipPath}`);
6717
+ } catch {
6718
+ }
6719
+ }
6720
+ }
6570
6721
  function registerDeployFrontendCommands(program) {
6571
6722
  program.command("deploy-frontend").description(
6572
6723
  "\u9012\u5F52\u4E0A\u4F20\u524D\u7AEF\u4EA7\u7269\u76EE\u5F55\u5230 MinIO\uFF0C\u5E76\u5728\u6210\u529F\u540E\u4E3A\u8BE5\u6876\u8BBE\u7F6E\u533F\u540D\u53EF\u8BFB\u7B56\u7565\uFF08MinIO \u8FDE\u63A5\u4FE1\u606F\u4EC5\u6765\u81EA apm.config.json frontendDeploy\uFF09"
@@ -6581,10 +6732,23 @@ function registerDeployFrontendCommands(program) {
6581
6732
  "--max-file-size-mb <mb>",
6582
6733
  `\u5355\u6587\u4EF6\u5927\u5C0F\u4E0A\u9650\uFF0C\u9ED8\u8BA4 ${DEFAULT_MAX_FILE_SIZE_MB}`,
6583
6734
  (v) => Number.parseInt(String(v), 10)
6735
+ ).option(
6736
+ "--pack-only",
6737
+ "\u4EC5\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u81F3\u524D\u7AEF\u8BBF\u95EE\u6876\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09"
6584
6738
  ).action(
6585
6739
  async (name, opts) => {
6586
6740
  const cfg = loadApmConfig({ configPath: opts.config });
6587
6741
  const namePrefix = resolveArtifactNamePrefix(cfg);
6742
+ const root = path11.resolve(process.cwd(), opts.dir || "apps/web/dist");
6743
+ if (!await isDirectoryPath(root)) {
6744
+ console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
6745
+ process.exit(1);
6746
+ }
6747
+ await ensureArtifactRootIndexHtml(root);
6748
+ if (opts.packOnly) {
6749
+ await runFrontendPackOnlyDeploy(root, namePrefix);
6750
+ return;
6751
+ }
6588
6752
  const settings = resolveFrontendDeployFromApmConfig(cfg);
6589
6753
  const minio = new MinioClient({
6590
6754
  endPoint: settings.endpoint,
@@ -6594,12 +6758,6 @@ function registerDeployFrontendCommands(program) {
6594
6758
  secretKey: settings.secretKey
6595
6759
  });
6596
6760
  const bucket = settings.bucket;
6597
- const root = path11.resolve(process.cwd(), opts.dir || "apps/web/dist");
6598
- if (!await isDirectoryPath(root)) {
6599
- console.error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${root}`);
6600
- process.exit(1);
6601
- }
6602
- await ensureArtifactRootIndexHtml(root);
6603
6761
  const maxBytes = Math.max(
6604
6762
  1,
6605
6763
  Number.isFinite(opts.maxFileSizeMb) ? Math.floor(
@@ -6674,7 +6832,10 @@ function registerDeploySftpCommands(program) {
6674
6832
  ).option(
6675
6833
  "--config <path>",
6676
6834
  "apm.config.json \u8DEF\u5F84\uFF08\u9ED8\u8BA4 .apm/apm.config.json\uFF09"
6677
- ).option("--extract", "\u4E0A\u4F20\u540E\u5728\u8FDC\u7A0B\u670D\u52A1\u5668\u89E3\u538B zip \u5230 remotePath").action(
6835
+ ).option("--extract", "\u4E0A\u4F20\u540E\u5728\u8FDC\u7A0B\u670D\u52A1\u5668\u89E3\u538B zip \u5230 remotePath").option(
6836
+ "--pack-only",
6837
+ "\u4EC5\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u4E0E --extract \u4E92\u65A5\uFF09"
6838
+ ).action(
6678
6839
  async (opts) => {
6679
6840
  const cfg = loadApmConfig({ configPath: opts.config });
6680
6841
  const settings = resolveWisdomDeployFromApmConfig(cfg);
@@ -6691,16 +6852,23 @@ function registerDeploySftpCommands(program) {
6691
6852
  process.exit(1);
6692
6853
  }
6693
6854
  try {
6855
+ const packOnly = Boolean(opts.packOnly);
6856
+ if (packOnly && opts.extract) {
6857
+ console.error("--pack-only \u4E0E --extract \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
6858
+ process.exit(1);
6859
+ }
6694
6860
  const result = await runWisdomSftpDeploy({
6695
6861
  localDir: root,
6696
6862
  settings,
6697
6863
  extract: Boolean(opts.extract),
6698
- projectName
6864
+ projectName,
6865
+ packOnly
6699
6866
  });
6700
6867
  console.log(JSON.stringify(result, null, 2));
6701
6868
  } catch (err) {
6702
6869
  const message = err instanceof Error ? err.message : String(err);
6703
- console.error(`${opts.extract ? "\u90E8\u7F72" : "\u4E0A\u4F20"}\u5931\u8D25:`, message);
6870
+ const action = opts.packOnly ? "\u6253\u5305" : opts.extract ? "\u90E8\u7F72" : "\u4E0A\u4F20";
6871
+ console.error(`${action}\u5931\u8D25:`, message);
6704
6872
  process.exit(1);
6705
6873
  }
6706
6874
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.85",
3
+ "version": "6.0.87",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -6,6 +6,13 @@
6
6
 
7
7
  **sessionId**:从当前工作项目录 `.apm/sessions/<sessionId>/` 或 `session.yaml` 获取;必须传入 `--session`,平台才会记录部署。
8
8
 
9
+ 部署前会自动:
10
+
11
+ 1. 从平台同步最新部署配置(`.apm/apm.config.json`)
12
+ 2. 合并仓库基线分支最新代码到当前分支
13
+
14
+ 若平台刚更新过部署配置,也可先手动执行 `apm sync-deploy-config` 再部署。
15
+
9
16
  - **成功**:部署完成,在回信中说明测试环境地址或部署结果。
10
17
  - **失败且输出含「未配置自动化部署」或「可跳过部署」**:本项目不支持自动化部署,属正常情况;放弃部署,在回信说明已跳过即可,无需修复配置或重试。
11
18
  - **其他失败**:按输出排查并修复后重试。