ai-project-manage-cli 6.0.68 → 6.0.70

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 +192 -45
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2227,7 +2227,7 @@ function validateAgentWsMessage(value, kind) {
2227
2227
  // src/commands/connect/deploy-run.ts
2228
2228
  import { spawn } from "node:child_process";
2229
2229
  import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
2230
- import { join as join13 } from "node:path";
2230
+ import { join as join14 } from "node:path";
2231
2231
 
2232
2232
  // src/commands/deploy/internal/wisdom-auto-deploy.ts
2233
2233
  import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
@@ -2236,7 +2236,8 @@ import { spawnSync as spawnSync3 } from "node:child_process";
2236
2236
 
2237
2237
  // src/commands/deploy/internal/apm-config.ts
2238
2238
  import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
2239
- import { resolve as resolve3 } from "node:path";
2239
+ import { homedir as homedir2 } from "node:os";
2240
+ import { join as join13, resolve as resolve3 } from "node:path";
2240
2241
  function loadApmConfig(options) {
2241
2242
  const p = resolve3(
2242
2243
  process.cwd(),
@@ -2375,6 +2376,70 @@ function reqWb(v, field) {
2375
2376
  }
2376
2377
  return v;
2377
2378
  }
2379
+ function expandWindowsEnvVars(pathStr, env = process.env) {
2380
+ return pathStr.replace(/%([^%]+)%/g, (_, name) => {
2381
+ const value = env[name];
2382
+ return value ?? `%${name}%`;
2383
+ });
2384
+ }
2385
+ function expandUserPath(pathStr, env = process.env) {
2386
+ const home = env.HOME ?? env.USERPROFILE ?? homedir2();
2387
+ const withEnv = expandWindowsEnvVars(pathStr, env);
2388
+ const expanded = withEnv.replace(/^~(?=\/|\\|$)/, home);
2389
+ if (/^[a-zA-Z]:[/\\]/.test(expanded)) {
2390
+ return expanded;
2391
+ }
2392
+ return resolve3(expanded);
2393
+ }
2394
+ var MAVEN_REPO_ENV_KEYS = [
2395
+ "MAVEN_LOCAL_REPO",
2396
+ "M2_REPO",
2397
+ "MAVEN_REPOSITORY"
2398
+ ];
2399
+ function readMavenLocalRepoFromMavenOpts(mavenOpts, env = process.env) {
2400
+ const match = mavenOpts.match(/-Dmaven\.repo\.local=(?:"([^"]+)"|(\S+))/);
2401
+ const raw = match?.[1]?.trim() || match?.[2]?.trim();
2402
+ return raw ? expandUserPath(raw, env) : null;
2403
+ }
2404
+ function readMavenLocalRepoFromEnv(env = process.env) {
2405
+ for (const key of MAVEN_REPO_ENV_KEYS) {
2406
+ const raw = env[key]?.trim();
2407
+ if (raw) {
2408
+ return expandUserPath(raw, env);
2409
+ }
2410
+ }
2411
+ const mavenOpts = env.MAVEN_OPTS?.trim();
2412
+ if (mavenOpts) {
2413
+ return readMavenLocalRepoFromMavenOpts(mavenOpts, env);
2414
+ }
2415
+ return null;
2416
+ }
2417
+ function readMavenLocalRepoFromSettings() {
2418
+ const settingsPath = join13(homedir2(), ".m2", "settings.xml");
2419
+ if (!existsSync11(settingsPath)) {
2420
+ return null;
2421
+ }
2422
+ try {
2423
+ const xml = readFileSync9(settingsPath, "utf8");
2424
+ const match = xml.match(
2425
+ /<localRepository>\s*([^<]+?)\s*<\/localRepository>/
2426
+ );
2427
+ const raw = match?.[1]?.trim();
2428
+ if (!raw) {
2429
+ return null;
2430
+ }
2431
+ return expandUserPath(raw);
2432
+ } catch {
2433
+ return null;
2434
+ }
2435
+ }
2436
+ function resolveMavenLocalRepo(configured) {
2437
+ const trimmed = configured?.trim();
2438
+ if (trimmed) {
2439
+ return expandUserPath(trimmed);
2440
+ }
2441
+ return readMavenLocalRepoFromEnv() ?? readMavenLocalRepoFromSettings() ?? join13(homedir2(), ".m2", "repository");
2442
+ }
2378
2443
  function resolveWisdomBackendDeployFromApmConfig(cfg) {
2379
2444
  const projectName = reqTopLevelName(cfg);
2380
2445
  const w = cfg.wisdomDeploy ?? {};
@@ -2402,7 +2467,7 @@ function resolveWisdomBackendDeployFromApmConfig(cfg) {
2402
2467
  remoteLibDir: `${remoteAppDir}/lib`,
2403
2468
  startupJar: posixBasename(jarPath),
2404
2469
  packageName: `${projectName}.jar.zip`,
2405
- mavenLocalRepo: reqWb(w.mavenLocalRepo, "mavenLocalRepo").trim(),
2470
+ mavenLocalRepo: resolveMavenLocalRepo(w.mavenLocalRepo),
2406
2471
  healthCheckPort: healthPort,
2407
2472
  healthCheckContext: reqHc(h.context, "context").trim(),
2408
2473
  healthCheckTimeout: healthTimeout
@@ -2588,7 +2653,7 @@ async function runWisdomSftpDeploy(params) {
2588
2653
  }
2589
2654
 
2590
2655
  // src/commands/deploy/internal/wisdom-backend-deploy.ts
2591
- var SPRINGBOOT_SCRIPT = "springboot.sh";
2656
+ var SPRINGBOOT_JAVA_OPTS = "-XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -Xms512M -Xmx1G";
2592
2657
  var MAVEN_MODULE = "jeecg-module-system/jeecg-system-start";
2593
2658
  var MAVEN_PROFILE = "dev";
2594
2659
  function log(message) {
@@ -2924,22 +2989,106 @@ function springbootOutputIndicatesSuccess(action, combined) {
2924
2989
  }
2925
2990
  return true;
2926
2991
  }
2927
- async function runSpringbootAction(client, config, action, ...args) {
2928
- if (action === "start" || action === "restart") {
2929
- if (args.length === 0) {
2930
- fail(`\u8FDC\u7A0B ${action} \u7F3A\u5C11 jar \u53C2\u6570`);
2931
- }
2932
- const jar = args[0].trim().split(/\r?\n/)[0].trim();
2933
- if (!jar) {
2934
- fail(`\u65E0\u6548\u7684 jar \u540D\u79F0: ${JSON.stringify(args[0])}`);
2935
- }
2992
+ function buildRemoteStatusScript(remoteAppDir, appName) {
2993
+ const dir = shellSingleQuote(remoteAppDir);
2994
+ const jar = shellSingleQuote(appName);
2995
+ return `
2996
+ set -e
2997
+ cd ${dir}
2998
+ appName=${jar}
2999
+ appIds=$(ps -ef | grep java | grep "$appName" | awk '{print $2}')
3000
+ if [ -z "$appIds" ]; then
3001
+ echo -e "\\033[31m Not running \\033[0m"
3002
+ else
3003
+ echo -e "\\033[32m Running [$appIds] \\033[0m"
3004
+ fi
3005
+ `.trim();
3006
+ }
3007
+ function buildRemoteRestartScript(remoteAppDir) {
3008
+ const dir = shellSingleQuote(remoteAppDir);
3009
+ const javaOpts = shellSingleQuote(SPRINGBOOT_JAVA_OPTS);
3010
+ return `
3011
+ set -e
3012
+ cd ${dir}
3013
+ releaseApp=$(ls -t | grep '.jar$' | head -n1)
3014
+ lastVersionApp=$(ls -t | grep '.jar$' | head -n2 | tail -n1)
3015
+ appName=$lastVersionApp
3016
+ appIds=$(ps -ef | grep java | grep "$appName" | awk '{print $2}')
3017
+ if [ -z "$appIds" ]; then
3018
+ echo "Maybe $appName not running, please check it..."
3019
+ else
3020
+ echo "The $appName is stopping..."
3021
+ echo "$appIds" | xargs kill
3022
+ fi
3023
+ for i in $(seq 15 -1 1); do
3024
+ echo -n "$i "
3025
+ sleep 1
3026
+ done
3027
+ echo 0
3028
+ if [ ! -d "backup" ]; then
3029
+ mkdir backup
3030
+ fi
3031
+ for i in $(ls | grep '.jar$' | grep -vFx "$releaseApp"); do
3032
+ echo "backup $i"
3033
+ mv "$i" backup/
3034
+ done
3035
+ appName=$releaseApp
3036
+ count=$(ps -ef | grep java | grep "$appName" | wc -l)
3037
+ if [ "$count" != "0" ]; then
3038
+ echo "Maybe $appName is running, please check it..."
3039
+ else
3040
+ echo "The $appName is starting..."
3041
+ nohup java -jar "./$appName" ${javaOpts} > nohup.out 2>&1 &
3042
+ fi
3043
+ `.trim();
3044
+ }
3045
+ function normalizeHealthContext(context) {
3046
+ let normalized = context.trim() || "/";
3047
+ if (!normalized.startsWith("/")) {
3048
+ normalized = `/${normalized}`;
2936
3049
  }
2937
- const quotedArgs = [action, ...args].map((arg) => shellSingleQuote(arg));
2938
- const command = [
2939
- `cd ${shellSingleQuote(config.remoteAppDir)}`,
2940
- `./${SPRINGBOOT_SCRIPT} ${quotedArgs.join(" ")}`
2941
- ].join(" && ");
2942
- const { exitCode, out, err } = await runRemoteCommand(client, command, {
3050
+ if (!normalized.endsWith("/")) {
3051
+ normalized = `${normalized}/`;
3052
+ }
3053
+ return normalized;
3054
+ }
3055
+ function buildRemoteHealthScript(port, context, timeoutSecs) {
3056
+ const normalizedContext = normalizeHealthContext(context);
3057
+ const portStr = String(port);
3058
+ const timeoutStr = String(timeoutSecs);
3059
+ return `
3060
+ set -e
3061
+ port=${shellSingleQuote(portStr)}
3062
+ context=${shellSingleQuote(normalizedContext)}
3063
+ timeout=${shellSingleQuote(timeoutStr)}
3064
+ check_url="http://127.0.0.1:${portStr}${normalizedContext}"
3065
+ echo "\u5065\u5EB7\u68C0\u67E5: \${check_url} (\u8D85\u65F6 \${timeout}s)"
3066
+ deadline=$(($(date +%s) + timeout))
3067
+ attempt=0
3068
+ while [ $(date +%s) -lt $deadline ]; do
3069
+ attempt=$((attempt + 1))
3070
+ code=$(curl -s -o /dev/null -w "%{http_code}" "$check_url" 2>/dev/null || echo "000")
3071
+ code=$(echo "$code" | tail -n1 | tr -d '[:space:]')
3072
+ if [ \${#code} -ge 3 ]; then
3073
+ status=\${code:0:3}
3074
+ if echo "$status" | grep -qE '^[0-9]+$' && [ "$status" -ge 200 ] && [ "$status" -lt 500 ]; then
3075
+ echo -e "\\033[32m\u5065\u5EB7\u68C0\u67E5\u901A\u8FC7 (HTTP \${status})\\033[0m"
3076
+ exit 0
3077
+ fi
3078
+ fi
3079
+ remaining=$((deadline - $(date +%s)))
3080
+ if [ $remaining -lt 0 ]; then
3081
+ remaining=0
3082
+ fi
3083
+ echo "\u7B49\u5F85\u670D\u52A1\u542F\u52A8... \u7B2C \${attempt} \u6B21\uFF0C\u5269\u4F59 \${remaining}s"
3084
+ sleep 5
3085
+ done
3086
+ echo -e "\\033[31m\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6 (\${timeout}s): \${check_url}\\033[0m"
3087
+ exit 1
3088
+ `.trim();
3089
+ }
3090
+ async function runRemoteServiceScript(client, script, action) {
3091
+ const { exitCode, out, err } = await runRemoteCommand(client, script, {
2943
3092
  check: false
2944
3093
  });
2945
3094
  const combined = `${out}
@@ -2948,21 +3097,17 @@ ${err}`.trim();
2948
3097
  if (action === "health") {
2949
3098
  if (exitCode !== 0 || !outputOk) {
2950
3099
  fail(`\u5065\u5EB7\u68C0\u67E5\u5931\u8D25
2951
- \u547D\u4EE4: ${command}
2952
3100
  \u8F93\u51FA: ${combined || "(\u7A7A)"}`);
2953
3101
  }
2954
3102
  return combined;
2955
3103
  }
2956
3104
  if (exitCode !== 0 && !outputOk) {
2957
- fail(`\u8FDC\u7A0B ${action} \u5931\u8D25: ${args.join(" ")}
3105
+ fail(`\u8FDC\u7A0B ${action} \u5931\u8D25
2958
3106
  ${combined}`);
2959
3107
  }
2960
- if ((action === "start" || action === "restart") && !outputOk) {
2961
- fail(
2962
- `\u8FDC\u7A0B ${action} \u672A\u6210\u529F: ${args.join(" ")}
2963
- \u547D\u4EE4: ${command}
2964
- \u8F93\u51FA: ${combined || "(\u7A7A)"}`
2965
- );
3108
+ if (action === "restart" && !outputOk) {
3109
+ fail(`\u8FDC\u7A0B restart \u672A\u6210\u529F
3110
+ \u8F93\u51FA: ${combined || "(\u7A7A)"}`);
2966
3111
  }
2967
3112
  return combined;
2968
3113
  }
@@ -2970,12 +3115,11 @@ function stripAnsi(text) {
2970
3115
  return text.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
2971
3116
  }
2972
3117
  async function getRunningJar(client, config) {
2973
- const combined = await runSpringbootAction(
2974
- client,
2975
- config,
2976
- "status",
3118
+ const script = buildRemoteStatusScript(
3119
+ config.remoteAppDir,
2977
3120
  config.startupJar
2978
3121
  );
3122
+ const combined = await runRemoteServiceScript(client, script, "status");
2979
3123
  const text = stripAnsi(combined).trim().toLowerCase();
2980
3124
  if (text.includes("not running")) {
2981
3125
  return null;
@@ -2986,11 +3130,19 @@ async function getRunningJar(client, config) {
2986
3130
  return null;
2987
3131
  }
2988
3132
  async function healthCheckService(client, config) {
2989
- const port = String(config.healthCheckPort);
2990
- const context = config.healthCheckContext;
2991
- const timeout = String(config.healthCheckTimeout);
2992
- log(`\u5065\u5EB7\u68C0\u67E5: springboot.sh health ${port} ${context} ${timeout}`);
2993
- await runSpringbootAction(client, config, "health", port, context, timeout);
3133
+ log(
3134
+ `\u5065\u5EB7\u68C0\u67E5: http://127.0.0.1:${config.healthCheckPort}${normalizeHealthContext(config.healthCheckContext)} (\u8D85\u65F6 ${config.healthCheckTimeout}s)`
3135
+ );
3136
+ const script = buildRemoteHealthScript(
3137
+ config.healthCheckPort,
3138
+ config.healthCheckContext,
3139
+ config.healthCheckTimeout
3140
+ );
3141
+ await runRemoteServiceScript(client, script, "health");
3142
+ }
3143
+ async function restartRemoteService(client, config) {
3144
+ const script = buildRemoteRestartScript(config.remoteAppDir);
3145
+ await runRemoteServiceScript(client, script, "restart");
2994
3146
  }
2995
3147
  async function runWisdomBackendDeploy(options) {
2996
3148
  const projectRoot = path2.resolve(options.projectRoot ?? process.cwd());
@@ -3044,12 +3196,7 @@ async function runWisdomBackendDeploy(options) {
3044
3196
  }
3045
3197
  if (needRestart) {
3046
3198
  log("\u91CD\u542F\u670D\u52A1...");
3047
- await runSpringbootAction(
3048
- conn.client,
3049
- config,
3050
- "restart",
3051
- config.startupJar
3052
- );
3199
+ await restartRemoteService(conn.client, config);
3053
3200
  }
3054
3201
  await healthCheckService(conn.client, config);
3055
3202
  if (libUploadEntries.length > 0) {
@@ -3141,7 +3288,7 @@ async function runWisdomAutoDeploy(options) {
3141
3288
  // src/commands/connect/deploy-run.ts
3142
3289
  var DEPLOY_LOG_SYNC_INTERVAL_MS = 3e4;
3143
3290
  function readApmConfig(workdir) {
3144
- const configPath = join13(workspaceApmDir(workdir), "apm.config.json");
3291
+ const configPath = join14(workspaceApmDir(workdir), "apm.config.json");
3145
3292
  if (!existsSync14(configPath)) {
3146
3293
  return void 0;
3147
3294
  }
@@ -4051,10 +4198,10 @@ async function runCursorAgent(cfg, ctx, options) {
4051
4198
 
4052
4199
  // src/commands/connect/cli-version-sync.ts
4053
4200
  import { existsSync as existsSync16, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
4054
- import { join as join14 } from "path";
4201
+ import { join as join15 } from "path";
4055
4202
  var CLI_VERSION_FILE = ".cli-version.json";
4056
4203
  function manifestPath(apmDir) {
4057
- return join14(apmDir, CLI_VERSION_FILE);
4204
+ return join15(apmDir, CLI_VERSION_FILE);
4058
4205
  }
4059
4206
  function loadManifest4(apmDir) {
4060
4207
  const path12 = toFsPath(manifestPath(apmDir));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.68",
3
+ "version": "6.0.70",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,