ai-project-manage-cli 5.0.14 → 5.0.15

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
@@ -10,6 +10,12 @@ import { join } from "path";
10
10
  var APM_CONFIG_DIR = join(homedir(), ".config", "apm");
11
11
  var APM_CONFIG_PATH = join(APM_CONFIG_DIR, "config.json");
12
12
  var DEFAULT_BASE_URL = "http://127.0.0.1:3000";
13
+ function resolveClientMachineId(cfg) {
14
+ return (cfg.clientMachineId ?? cfg.userId ?? "").trim();
15
+ }
16
+ function resolveAccount(cfg) {
17
+ return (cfg.account ?? cfg.email ?? "").trim();
18
+ }
13
19
  async function readApmConfig() {
14
20
  try {
15
21
  const raw = readFileSync(APM_CONFIG_PATH, "utf8");
@@ -18,14 +24,17 @@ async function readApmConfig() {
18
24
  return null;
19
25
  }
20
26
  const rawCfg = v;
21
- if (typeof rawCfg.baseUrl !== "string" || typeof rawCfg.userId !== "string" || typeof rawCfg.token !== "string") {
27
+ if (typeof rawCfg.baseUrl !== "string" || typeof rawCfg.token !== "string") {
22
28
  return null;
23
29
  }
24
30
  const cfg = v;
31
+ const clientMachineId = resolveClientMachineId(cfg);
32
+ const account = resolveAccount(cfg);
25
33
  return {
26
34
  baseUrl: cfg.baseUrl.trim().replace(/\/+$/, ""),
27
- userId: cfg.userId,
28
35
  token: cfg.token,
36
+ ...clientMachineId ? { clientMachineId } : {},
37
+ ...account ? { account } : {},
29
38
  ...typeof cfg.email === "string" ? { email: cfg.email } : {}
30
39
  };
31
40
  } catch {
@@ -35,8 +44,9 @@ async function readApmConfig() {
35
44
  function defaultApmConfig() {
36
45
  return {
37
46
  baseUrl: DEFAULT_BASE_URL,
38
- userId: "",
47
+ clientMachineId: "",
39
48
  token: "",
49
+ account: "",
40
50
  email: ""
41
51
  };
42
52
  }
@@ -54,11 +64,13 @@ async function ensureApmConfig() {
54
64
  return defaults;
55
65
  }
56
66
  async function writeApmConfig(cfg) {
67
+ const clientMachineId = resolveClientMachineId(cfg);
68
+ const account = resolveAccount(cfg);
57
69
  const normalized = {
58
70
  baseUrl: cfg.baseUrl.trim().replace(/\/+$/, ""),
59
- userId: cfg.userId,
60
71
  token: cfg.token,
61
- ...typeof cfg.email === "string" ? { email: cfg.email } : {}
72
+ ...clientMachineId ? { clientMachineId } : {},
73
+ ...account ? { account, email: account } : {}
62
74
  };
63
75
  mkdirSync(APM_CONFIG_DIR, { recursive: true });
64
76
  writeFileSync(APM_CONFIG_PATH, JSON.stringify(normalized, null, 2) + "\n", {
@@ -256,13 +268,13 @@ async function runLogin(opts) {
256
268
  const baseUrl = (opts.server?.trim() || process.env.AI_PM_SERVER?.trim() || DEFAULT_BASE_URL).replace(/\/+$/, "");
257
269
  const api = createApmApiClient({
258
270
  baseUrl,
259
- userId: "",
271
+ clientMachineId: "",
260
272
  token: ""
261
273
  });
262
274
  let data;
263
275
  try {
264
276
  data = await api.auth.login({
265
- email: opts.email,
277
+ account: opts.email,
266
278
  password: opts.password
267
279
  });
268
280
  } catch (raw) {
@@ -277,24 +289,29 @@ async function runLogin(opts) {
277
289
  console.error("[apm] \u8BF7\u6C42\u5931\u8D25:", raw instanceof Error ? raw.message : raw);
278
290
  process.exit(1);
279
291
  }
280
- const userId = data?.user?.id;
292
+ const clientMachineId = data?.clientMachine?.id;
281
293
  const token = data?.token;
282
- if (!userId || !token) {
294
+ if (!clientMachineId || !token) {
283
295
  console.error(
284
- "[apm] \u54CD\u5E94\u7F3A\u5C11 user.id / token\uFF08\u8BF7\u786E\u8BA4\u670D\u52A1\u7AEF\u4E3A /api/v1/auth/login\uFF09"
296
+ "[apm] \u54CD\u5E94\u7F3A\u5C11 clientMachine.id / token\uFF08\u8BF7\u786E\u8BA4\u670D\u52A1\u7AEF\u4E3A /api/v1/auth/login\uFF09"
285
297
  );
286
298
  process.exit(1);
287
299
  }
288
300
  const cfg = {
289
301
  baseUrl,
290
- userId,
302
+ clientMachineId,
291
303
  token,
304
+ account: opts.email,
292
305
  email: opts.email
293
306
  };
294
307
  await writeApmConfig(cfg);
295
308
  console.error(`[apm] \u5DF2\u4FDD\u5B58\u767B\u5F55\u4FE1\u606F: ${APM_CONFIG_PATH}`);
296
309
  console.log(
297
- JSON.stringify({ userId: cfg.userId, baseUrl: cfg.baseUrl }, null, 2)
310
+ JSON.stringify(
311
+ { clientMachineId: cfg.clientMachineId, baseUrl: cfg.baseUrl },
312
+ null,
313
+ 2
314
+ )
298
315
  );
299
316
  }
300
317
 
@@ -489,7 +506,7 @@ function formatSessionMessagesXml(sessionId, messages) {
489
506
  lines.push(
490
507
  ` <message id="${escapeXmlAttr(message.id)}" name="${escapeXmlAttr(
491
508
  message.name
492
- )}" position="${escapeXmlAttr(message.position)}"${roundAttr}>`,
509
+ )}" expert="${escapeXmlAttr(message.expert)}"${roundAttr}>`,
493
510
  ` <content>${wrapCdata(message.content)}</content>`,
494
511
  " </message>"
495
512
  );
@@ -613,7 +630,7 @@ async function runPull(sessionId, apmRoot) {
613
630
  description: "./RULE.md",
614
631
  members: members.map((m) => ({
615
632
  name: m.displayName,
616
- position: m.position,
633
+ expert: m.expert,
617
634
  system_persona: m.systemPersona,
618
635
  skills: []
619
636
  })),
@@ -1102,6 +1119,7 @@ async function handleInboundMessage(cfg, raw) {
1102
1119
  try {
1103
1120
  await runBranch(msg.sessionId, { cwd: msg.workdir });
1104
1121
  await runPull(msg.sessionId, workspaceApmDir(msg.workdir));
1122
+ await commitWorkingTreeIfDirty(msg.workdir, "fix: apm pull");
1105
1123
  await updateMessageStatus(cfg, messageId, "TYPING");
1106
1124
  await runCursorAgent(cfg, {
1107
1125
  messageId: msg.messageId,
@@ -1134,13 +1152,13 @@ async function handleInboundMessage(cfg, raw) {
1134
1152
  }
1135
1153
  }
1136
1154
  }
1137
- function startHeartbeat(ws, userId) {
1155
+ function startHeartbeat(ws, clientMachineId) {
1138
1156
  const send = () => {
1139
1157
  if (ws.readyState === WebSocket.OPEN) {
1140
1158
  ws.send(
1141
1159
  serializeAgentWsMessage({
1142
1160
  type: "heartbeat",
1143
- userId
1161
+ userId: clientMachineId
1144
1162
  })
1145
1163
  );
1146
1164
  }
@@ -1154,8 +1172,9 @@ async function runConnect(options) {
1154
1172
  if (options.server?.trim()) {
1155
1173
  cfg.baseUrl = options.server.trim().replace(/\/+$/, "");
1156
1174
  }
1157
- if (!cfg.userId?.trim()) {
1158
- console.error("[apm] config \u7F3A\u5C11 userId\uFF0C\u8BF7\u91CD\u65B0 apm login");
1175
+ const clientMachineId = resolveClientMachineId(cfg);
1176
+ if (!clientMachineId) {
1177
+ console.error("[apm] config \u7F3A\u5C11 clientMachineId\uFF0C\u8BF7\u91CD\u65B0 apm login");
1159
1178
  process.exit(1);
1160
1179
  }
1161
1180
  const url = buildAgentWsUrl(cfg.baseUrl, cfg.token);
@@ -1178,7 +1197,7 @@ async function runConnect(options) {
1178
1197
  };
1179
1198
  ws.on("open", () => {
1180
1199
  console.log("[apm] WebSocket \u5DF2\u8FDE\u63A5");
1181
- stopHeartbeat = startHeartbeat(ws, cfg.userId);
1200
+ stopHeartbeat = startHeartbeat(ws, clientMachineId);
1182
1201
  });
1183
1202
  ws.on("message", (data) => {
1184
1203
  const text = Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
@@ -1862,40 +1881,6 @@ function registerDeployBackendCommands(program) {
1862
1881
  import { copyFile, readdir as readdir2, stat } from "node:fs/promises";
1863
1882
  import path7 from "node:path";
1864
1883
 
1865
- // src/commands/deploy/internal/load-apm-dotenv.ts
1866
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "node:fs";
1867
- import { join as join9 } from "node:path";
1868
- function loadApmDotEnvIfPresent() {
1869
- const p = join9(workspaceApmDir(), ".env");
1870
- if (!existsSync10(p)) {
1871
- return;
1872
- }
1873
- let text;
1874
- try {
1875
- text = readFileSync9(p, "utf8");
1876
- } catch {
1877
- return;
1878
- }
1879
- for (const line of text.split("\n")) {
1880
- const t = line.trim();
1881
- if (!t || t.startsWith("#")) {
1882
- continue;
1883
- }
1884
- const eq = t.indexOf("=");
1885
- if (eq <= 0) {
1886
- continue;
1887
- }
1888
- const key = t.slice(0, eq).trim();
1889
- let val = t.slice(eq + 1).trim();
1890
- if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
1891
- val = val.slice(1, -1);
1892
- }
1893
- if (process.env[key] === void 0) {
1894
- process.env[key] = val;
1895
- }
1896
- }
1897
- }
1898
-
1899
1884
  // src/commands/deploy/internal/minio.ts
1900
1885
  import { statSync as statSync5 } from "node:fs";
1901
1886
  import { readdir, readFile } from "node:fs/promises";
@@ -2059,31 +2044,6 @@ function artifactObjectKey(namePrefix, branchSegment, relativePath) {
2059
2044
  const rel = sanitizeRelativePath(relativePath);
2060
2045
  return `${base}/${branchSegment}/dist/${rel}`;
2061
2046
  }
2062
- function mergeMinioFromEnv(settings) {
2063
- const ep = process.env.MINIO_ENDPOINT?.trim();
2064
- const portRaw = process.env.MINIO_PORT?.trim();
2065
- const sslRaw = process.env.MINIO_USE_SSL?.trim().toLowerCase();
2066
- const ak = process.env.MINIO_ACCESS_KEY?.trim();
2067
- const sk = process.env.MINIO_SECRET_KEY?.trim();
2068
- const bucket = process.env.MINIO_BUCKET?.trim();
2069
- const port = portRaw ? Number.parseInt(portRaw, 10) : void 0;
2070
- let useSsl = settings.useSsl;
2071
- if (sslRaw === "true" || sslRaw === "1") {
2072
- useSsl = true;
2073
- }
2074
- if (sslRaw === "false" || sslRaw === "0") {
2075
- useSsl = false;
2076
- }
2077
- return {
2078
- ...settings,
2079
- endpoint: ep || settings.endpoint,
2080
- port: port !== void 0 && Number.isFinite(port) && port > 0 ? port : settings.port,
2081
- useSsl,
2082
- accessKey: ak || settings.accessKey,
2083
- secretKey: sk || settings.secretKey,
2084
- bucket: bucket || settings.bucket
2085
- };
2086
- }
2087
2047
  async function ensureArtifactRootIndexHtml(root) {
2088
2048
  const indexHtmlPath = path7.join(root, "index.html");
2089
2049
  try {
@@ -2124,7 +2084,7 @@ async function ensureArtifactRootIndexHtml(root) {
2124
2084
  }
2125
2085
  function registerDeployFrontendCommands(program) {
2126
2086
  program.command("deploy-frontend").description(
2127
- "\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\uFF08\u53EF\u5148\u914D\u7F6E .apm/.env \u7684 MINIO_*\uFF0C\u5DF2\u6709\u73AF\u5883\u53D8\u91CF\u4F18\u5148\uFF09"
2087
+ "\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"
2128
2088
  ).argument("[name]", "\u73AF\u5883\u540D", "online").option(
2129
2089
  "--dir <path>",
2130
2090
  "\u4EA7\u7269\u76EE\u5F55\uFF1B\u5355\u4ED3\u9ED8\u8BA4 apps/web/dist\uFF08\u9700\u5148 rush build / vite build\uFF09",
@@ -2138,12 +2098,9 @@ function registerDeployFrontendCommands(program) {
2138
2098
  (v) => Number.parseInt(String(v), 10)
2139
2099
  ).action(
2140
2100
  async (name, opts) => {
2141
- loadApmDotEnvIfPresent();
2142
2101
  const cfg = loadApmConfig({ configPath: opts.config });
2143
2102
  const namePrefix = resolveArtifactNamePrefix(cfg);
2144
- const settings = mergeMinioFromEnv(
2145
- resolveFrontendDeployFromApmConfig(cfg)
2146
- );
2103
+ const settings = resolveFrontendDeployFromApmConfig(cfg);
2147
2104
  const minio = new MinioClient({
2148
2105
  endPoint: settings.endpoint,
2149
2106
  port: settings.port,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "5.0.14",
3
+ "version": "5.0.15",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -37,4 +37,4 @@
37
37
  "minio": "~8.0.7",
38
38
  "dockerode": "~5.0.0"
39
39
  }
40
- }
40
+ }
@@ -18,7 +18,7 @@
18
18
  2. 根据你的名字从 session.yaml 中找到你对应的人设(system_persona)
19
19
  3. 根据人设完成用户指定的任务
20
20
  4. 任务有阶段行进展或者任务完成后必须使用 `apm append-message` 回复消息,回复要求简洁不用对本轮工作进行总结
21
- 5. 工作日志放到 `.apm/sessions/<会话ID>/docs/<position>.md` 中,并执行`apm sync-document <会话ID> --file=<position>`同步到远程
21
+ 5. 工作日志放到 `.apm/sessions/<会话ID>/docs/<expert>.md` 中,并执行`apm sync-document <会话ID> --file=<expert>`同步到远程
22
22
 
23
23
  ## 目录声明
24
24