ai-project-manage-cli 6.0.42 → 6.0.43

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 +63 -62
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -127,6 +127,13 @@ function resolveWorkdirPath(cwd = process.cwd()) {
127
127
  return normalizeWorkdirPath(absolute);
128
128
  }
129
129
  }
130
+ function requireRemoteWorkdir(workdir) {
131
+ const trimmed = typeof workdir === "string" ? workdir.trim() : "";
132
+ if (!trimmed) {
133
+ throw new Error("[apm] \u8FDC\u7A0B\u6D88\u606F\u7F3A\u5C11\u5DE5\u4F5C\u76EE\u5F55 workdir");
134
+ }
135
+ return resolveWorkdirPath(trimmed);
136
+ }
130
137
 
131
138
  // src/command-utils.ts
132
139
  var __dirname = dirname(fileURLToPath(import.meta.url));
@@ -611,7 +618,7 @@ async function runBranch(sessionId, options = {}) {
611
618
 
612
619
  // src/commands/pull.ts
613
620
  import { writeFileSync as writeFileSync6 } from "fs";
614
- import { dirname as dirname2, join as join7 } from "path";
621
+ import { join as join7 } from "path";
615
622
  import { stringify as yamlStringify } from "yaml";
616
623
 
617
624
  // src/session-messages-xml.ts
@@ -908,13 +915,7 @@ async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
908
915
  }
909
916
 
910
917
  // src/commands/pull.ts
911
- function resolvePullWorkdir(apmRoot) {
912
- if (apmRoot) {
913
- return resolveWorkdirPath(dirname2(apmRoot));
914
- }
915
- return resolveWorkdirPath();
916
- }
917
- async function runPull(sessionId, apmRoot) {
918
+ async function runPull(sessionId, remoteWorkdir) {
918
919
  const trimmedId = sessionId.trim();
919
920
  if (!trimmedId) {
920
921
  console.error("[apm] sessionId \u4E0D\u80FD\u4E3A\u7A7A");
@@ -922,6 +923,8 @@ async function runPull(sessionId, apmRoot) {
922
923
  }
923
924
  const cfg = await ensureLoggedConfig();
924
925
  const api = createApmApiClient(cfg);
926
+ const workdir = remoteWorkdir === void 0 ? resolveWorkdirPath() : requireRemoteWorkdir(remoteWorkdir);
927
+ const apmRoot = workspaceApmDir(workdir);
925
928
  const [detail, members, documents, attachments, messages] = await Promise.all(
926
929
  [
927
930
  api.cli.sessionDetail({ sessionId: trimmedId }),
@@ -976,8 +979,7 @@ async function runPull(sessionId, apmRoot) {
976
979
  "utf8"
977
980
  );
978
981
  await syncSessionAttachments(cfg, trimmedId, attachments, apmRoot);
979
- const workdirPath = resolvePullWorkdir(apmRoot);
980
- await syncPlatformRules(cfg, trimmedId, workdirPath, apmRoot);
982
+ await syncPlatformRules(cfg, trimmedId, workdir, apmRoot);
981
983
  console.log(`[apm] \u5DF2\u540C\u6B65\u4F1A\u8BDD\u5DE5\u4F5C\u533A: ${dir}`);
982
984
  return dir;
983
985
  }
@@ -987,12 +989,12 @@ import { spawnSync } from "child_process";
987
989
 
988
990
  // src/version.ts
989
991
  import { readFileSync as readFileSync5 } from "fs";
990
- import { dirname as dirname3, join as join8 } from "path";
992
+ import { dirname as dirname2, join as join8 } from "path";
991
993
  import { fileURLToPath as fileURLToPath2 } from "url";
992
994
  var CLI_PACKAGE_NAME = "ai-project-manage-cli";
993
995
  function readCliVersion() {
994
996
  try {
995
- const dir = dirname3(fileURLToPath2(import.meta.url));
997
+ const dir = dirname2(fileURLToPath2(import.meta.url));
996
998
  const pkgPath = join8(dir, "..", "package.json");
997
999
  const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
998
1000
  return pkg.version ?? "0.0.0";
@@ -1430,7 +1432,6 @@ import {
1430
1432
  CursorAgentError
1431
1433
  } from "@cursor/sdk";
1432
1434
  import { setMaxListeners as setMaxListeners2 } from "node:events";
1433
- import { resolve as resolve4 } from "path";
1434
1435
 
1435
1436
  // src/session-utils.ts
1436
1437
  var EventSession = class {
@@ -1592,7 +1593,7 @@ ${JSON.stringify(event, null, 2)}
1592
1593
 
1593
1594
  // src/commands/connect/agent-session-registry.ts
1594
1595
  import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
1595
- import { dirname as dirname4, resolve as resolve3 } from "node:path";
1596
+ import { dirname as dirname3, resolve as resolve3 } from "node:path";
1596
1597
  function registryPath(workdir, sessionId) {
1597
1598
  return resolve3(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
1598
1599
  }
@@ -1618,7 +1619,7 @@ function readRegistry(path10) {
1618
1619
  return {};
1619
1620
  }
1620
1621
  function writeRegistry(path10, registry) {
1621
- mkdirSync5(dirname4(path10), { recursive: true });
1622
+ mkdirSync5(dirname3(path10), { recursive: true });
1622
1623
  writeFileSync7(path10, `${JSON.stringify(registry, null, 2)}
1623
1624
  `, "utf8");
1624
1625
  }
@@ -1816,16 +1817,16 @@ async function runCursorAgent(cfg, ctx, options) {
1816
1817
  if (!apiKey) {
1817
1818
  throw new Error("\u7F3A\u5C11 apiKey\uFF0C\u65E0\u6CD5\u8C03\u7528 Cursor SDK");
1818
1819
  }
1819
- const cwd = resolve4(ctx.workdir);
1820
+ const workdir = resolveWorkdirPath(ctx.workdir);
1820
1821
  const prompt = ctx.prompt;
1821
1822
  console.log(
1822
- `[apm] Cursor Agent \u5F00\u59CB messageId=${ctx.messageId} sessionId=${ctx.sessionId} cwd=${cwd}`
1823
+ `[apm] Cursor Agent \u5F00\u59CB messageId=${ctx.messageId} sessionId=${ctx.sessionId} cwd=${workdir}`
1823
1824
  );
1824
1825
  const { agent, resumed } = await obtainAgent({
1825
1826
  apiKey,
1826
1827
  model: ctx.model,
1827
- cwd,
1828
- workdir: ctx.workdir,
1828
+ cwd: workdir,
1829
+ workdir,
1829
1830
  sessionId: ctx.sessionId,
1830
1831
  user: ctx.user
1831
1832
  });
@@ -1884,7 +1885,7 @@ async function runCursorAgent(cfg, ctx, options) {
1884
1885
  });
1885
1886
  console.error(`[apm] ${failureMessage}`);
1886
1887
  if (resumed) {
1887
- clearSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user);
1888
+ clearSessionAgentId(workdir, ctx.sessionId, ctx.user);
1888
1889
  }
1889
1890
  throw new Error(failureMessage);
1890
1891
  }
@@ -1895,7 +1896,7 @@ async function runCursorAgent(cfg, ctx, options) {
1895
1896
  } catch (err) {
1896
1897
  if (err instanceof CursorAgentError) {
1897
1898
  if (resumed) {
1898
- clearSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user);
1899
+ clearSessionAgentId(workdir, ctx.sessionId, ctx.user);
1899
1900
  }
1900
1901
  throw new Error(
1901
1902
  `Cursor \u542F\u52A8\u5931\u8D25: ${err.message}${err.isRetryable ? "\uFF08\u53EF\u91CD\u8BD5\uFF09" : ""}`
@@ -1912,23 +1913,27 @@ async function runCursorAgent(cfg, ctx, options) {
1912
1913
 
1913
1914
  // src/commands/connect/pre-step-cache.ts
1914
1915
  var PULL_TTL_MS = 3e4;
1915
- var lastBranchSessionId = null;
1916
- var lastPullAtBySession = /* @__PURE__ */ new Map();
1917
- function shouldRunBranch(sessionId) {
1918
- return lastBranchSessionId !== sessionId;
1916
+ function sessionWorkdirKey(sessionId, workdir) {
1917
+ return `${sessionId}\0${workdir}`;
1919
1918
  }
1920
- function markBranchDone(sessionId) {
1921
- lastBranchSessionId = sessionId;
1919
+ var lastBranchKey = null;
1920
+ var lastPullAtByKey = /* @__PURE__ */ new Map();
1921
+ function shouldRunBranch(sessionId, workdir) {
1922
+ return lastBranchKey !== sessionWorkdirKey(sessionId, workdir);
1922
1923
  }
1923
- function shouldRunPull(sessionId) {
1924
- const last = lastPullAtBySession.get(sessionId);
1924
+ function markBranchDone(sessionId, workdir) {
1925
+ lastBranchKey = sessionWorkdirKey(sessionId, workdir);
1926
+ }
1927
+ function shouldRunPull(sessionId, workdir) {
1928
+ const key = sessionWorkdirKey(sessionId, workdir);
1929
+ const last = lastPullAtByKey.get(key);
1925
1930
  if (last == null) {
1926
1931
  return true;
1927
1932
  }
1928
1933
  return Date.now() - last >= PULL_TTL_MS;
1929
1934
  }
1930
- function markPullDone(sessionId) {
1931
- lastPullAtBySession.set(sessionId, Date.now());
1935
+ function markPullDone(sessionId, workdir) {
1936
+ lastPullAtByKey.set(sessionWorkdirKey(sessionId, workdir), Date.now());
1932
1937
  }
1933
1938
 
1934
1939
  // src/commands/connect/run-slot-pool.ts
@@ -1941,10 +1946,10 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT) {
1941
1946
  active += 1;
1942
1947
  return Promise.resolve();
1943
1948
  }
1944
- return new Promise((resolve6) => {
1949
+ return new Promise((resolve5) => {
1945
1950
  waiters.push(() => {
1946
1951
  active += 1;
1947
- resolve6();
1952
+ resolve5();
1948
1953
  });
1949
1954
  });
1950
1955
  };
@@ -1978,6 +1983,8 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
1978
1983
  if (isUserCancelled(ctx)) return;
1979
1984
  if (signal.aborted) return;
1980
1985
  const messageId = msg.messageId;
1986
+ const workdir = requireRemoteWorkdir(msg.workdir);
1987
+ const apmRoot = workspaceApmDir(workdir);
1981
1988
  const runStep = async (step, fn) => {
1982
1989
  const startedAt = Date.now();
1983
1990
  try {
@@ -1995,24 +2002,18 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
1995
2002
  "status-typing",
1996
2003
  () => updateMessageStatus(cfg, messageId, "TYPING")
1997
2004
  );
1998
- if (shouldRunBranch(msg.sessionId)) {
2005
+ if (shouldRunBranch(msg.sessionId, workdir)) {
1999
2006
  if (signal.aborted) return;
2000
- await runStep(
2001
- "branch",
2002
- () => runBranch(msg.sessionId, { cwd: msg.workdir })
2003
- );
2004
- markBranchDone(msg.sessionId);
2007
+ await runStep("branch", () => runBranch(msg.sessionId, { cwd: workdir }));
2008
+ markBranchDone(msg.sessionId, workdir);
2005
2009
  } else {
2006
2010
  console.log(`[apm] step=branch skipped sessionId=${msg.sessionId}`);
2007
2011
  }
2008
2012
  let pullRan = false;
2009
- if (shouldRunPull(msg.sessionId)) {
2013
+ if (shouldRunPull(msg.sessionId, workdir)) {
2010
2014
  if (signal.aborted) return;
2011
- await runStep(
2012
- "pull",
2013
- () => runPull(msg.sessionId, workspaceApmDir(msg.workdir))
2014
- );
2015
- markPullDone(msg.sessionId);
2015
+ await runStep("pull", () => runPull(msg.sessionId, workdir));
2016
+ markPullDone(msg.sessionId, workdir);
2016
2017
  pullRan = true;
2017
2018
  } else {
2018
2019
  console.log(`[apm] step=pull skipped sessionId=${msg.sessionId}`);
@@ -2021,7 +2022,7 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
2021
2022
  if (signal.aborted) return;
2022
2023
  await runStep(
2023
2024
  "commit-pull",
2024
- () => commitWorkingTreeIfDirty(msg.workdir, "fix: apm pull")
2025
+ () => commitWorkingTreeIfDirty(workdir, "fix: apm pull")
2025
2026
  );
2026
2027
  } else {
2027
2028
  console.log(`[apm] step=commit-pull skipped sessionId=${msg.sessionId}`);
@@ -2037,7 +2038,7 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
2037
2038
  prompt: msg.content,
2038
2039
  model: msg.model,
2039
2040
  apiKey: msg.apiKey,
2040
- workdir: msg.workdir,
2041
+ workdir,
2041
2042
  user: msg.user
2042
2043
  },
2043
2044
  { signal }
@@ -2045,11 +2046,11 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
2045
2046
  );
2046
2047
  await runStep(
2047
2048
  "sync-documents",
2048
- () => syncSessionDocuments(cfg, msg.sessionId, workspaceApmDir(msg.workdir))
2049
+ () => syncSessionDocuments(cfg, msg.sessionId, apmRoot)
2049
2050
  );
2050
2051
  await runStep(
2051
2052
  "commit-files",
2052
- () => commitWorkingTreeIfDirty(msg.workdir, "chore(apm): commit working tree")
2053
+ () => commitWorkingTreeIfDirty(workdir, "chore(apm): commit working tree")
2053
2054
  );
2054
2055
  await runStep(
2055
2056
  "status-success",
@@ -2109,7 +2110,7 @@ async function runConnect(options) {
2109
2110
  }
2110
2111
  const url = buildAgentWsUrl(cfg.baseUrl, resolveApiKey(cfg));
2111
2112
  console.log(`[apm] \u8FDE\u63A5 ${cfg.baseUrl} \u2026`);
2112
- await new Promise((resolve6, reject) => {
2113
+ await new Promise((resolve5, reject) => {
2113
2114
  const ws = new WebSocket(url);
2114
2115
  let stopHeartbeat;
2115
2116
  let shuttingDown = false;
@@ -2138,7 +2139,7 @@ async function runConnect(options) {
2138
2139
  ]);
2139
2140
  } catch {
2140
2141
  }
2141
- resolve6();
2142
+ resolve5();
2142
2143
  process.exit(code);
2143
2144
  };
2144
2145
  ws.on("open", () => {
@@ -2226,11 +2227,11 @@ import path5 from "node:path";
2226
2227
 
2227
2228
  // src/commands/deploy/internal/apm-config.ts
2228
2229
  import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
2229
- import { resolve as resolve5 } from "node:path";
2230
+ import { resolve as resolve4 } from "node:path";
2230
2231
  function loadApmConfig(options) {
2231
- const p = resolve5(
2232
+ const p = resolve4(
2232
2233
  process.cwd(),
2233
- options?.configPath ?? resolve5(workspaceApmDir(), "apm.config.json")
2234
+ options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
2234
2235
  );
2235
2236
  if (!existsSync9(p)) {
2236
2237
  console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
@@ -2497,17 +2498,17 @@ var DockerodeClient = class {
2497
2498
  await this.client.getImage(image).remove({ force: true });
2498
2499
  }
2499
2500
  async pullImage(image, auth) {
2500
- const stream = await new Promise((resolve6, reject) => {
2501
+ const stream = await new Promise((resolve5, reject) => {
2501
2502
  const pullOptions = auth ? { authconfig: auth } : void 0;
2502
2503
  this.client.pull(image, pullOptions, (err, output) => {
2503
2504
  if (err || !output) {
2504
2505
  reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
2505
2506
  return;
2506
2507
  }
2507
- resolve6(output);
2508
+ resolve5(output);
2508
2509
  });
2509
2510
  });
2510
- await new Promise((resolve6, reject) => {
2511
+ await new Promise((resolve5, reject) => {
2511
2512
  this.client.modem.followProgress(
2512
2513
  stream,
2513
2514
  (err) => {
@@ -2515,7 +2516,7 @@ var DockerodeClient = class {
2515
2516
  reject(err);
2516
2517
  return;
2517
2518
  }
2518
- resolve6();
2519
+ resolve5();
2519
2520
  },
2520
2521
  () => void 0
2521
2522
  );
@@ -3006,14 +3007,14 @@ var MinioClient = class {
3006
3007
  async deleteObjectsByPrefix(bucket, prefix) {
3007
3008
  const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
3008
3009
  const keys = [];
3009
- await new Promise((resolve6, reject) => {
3010
+ await new Promise((resolve5, reject) => {
3010
3011
  objectsStream.on("data", (obj) => {
3011
3012
  if (obj.name) {
3012
3013
  keys.push(obj.name);
3013
3014
  }
3014
3015
  });
3015
3016
  objectsStream.on("error", reject);
3016
- objectsStream.on("end", resolve6);
3017
+ objectsStream.on("end", resolve5);
3017
3018
  });
3018
3019
  const chunkSize = 500;
3019
3020
  for (let i = 0; i < keys.length; i += chunkSize) {
@@ -3251,7 +3252,7 @@ async function ensureRemoteDir(sftp, dir) {
3251
3252
  }
3252
3253
  }
3253
3254
  function execCommand(client, command) {
3254
- return new Promise((resolve6, reject) => {
3255
+ return new Promise((resolve5, reject) => {
3255
3256
  client.exec(command, (err, stream) => {
3256
3257
  if (err) return reject(err);
3257
3258
  let stdout = "";
@@ -3261,7 +3262,7 @@ function execCommand(client, command) {
3261
3262
  reject(new Error(`\u8FDC\u7A0B\u547D\u4EE4\u5931\u8D25 (${code}): ${stderr || stdout}`));
3262
3263
  return;
3263
3264
  }
3264
- resolve6(stdout);
3265
+ resolve5(stdout);
3265
3266
  }).on("data", (data) => {
3266
3267
  stdout += data.toString();
3267
3268
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.42",
3
+ "version": "6.0.43",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,