ai-project-manage-cli 5.0.22 → 6.0.24

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 +57 -54
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13,8 +13,8 @@ var DEFAULT_BASE_URL = "http://127.0.0.1:3000";
13
13
  function resolveClientMachineId(cfg) {
14
14
  return (cfg.clientMachineId ?? cfg.userId ?? "").trim();
15
15
  }
16
- function resolveAccount(cfg) {
17
- return (cfg.account ?? cfg.email ?? "").trim();
16
+ function resolveApiKey(cfg) {
17
+ return (cfg.apiKey ?? cfg.token ?? "").trim();
18
18
  }
19
19
  async function readApmConfig() {
20
20
  try {
@@ -24,18 +24,17 @@ async function readApmConfig() {
24
24
  return null;
25
25
  }
26
26
  const rawCfg = v;
27
- if (typeof rawCfg.baseUrl !== "string" || typeof rawCfg.token !== "string") {
27
+ if (typeof rawCfg.baseUrl !== "string") {
28
28
  return null;
29
29
  }
30
+ const apiKey = resolveApiKey(rawCfg);
31
+ if (!apiKey) return null;
30
32
  const cfg = v;
31
33
  const clientMachineId = resolveClientMachineId(cfg);
32
- const account = resolveAccount(cfg);
33
34
  return {
34
35
  baseUrl: cfg.baseUrl.trim().replace(/\/+$/, ""),
35
- token: cfg.token,
36
- ...clientMachineId ? { clientMachineId } : {},
37
- ...account ? { account } : {},
38
- ...typeof cfg.email === "string" ? { email: cfg.email } : {}
36
+ apiKey,
37
+ ...clientMachineId ? { clientMachineId } : {}
39
38
  };
40
39
  } catch {
41
40
  return null;
@@ -45,9 +44,7 @@ function defaultApmConfig() {
45
44
  return {
46
45
  baseUrl: DEFAULT_BASE_URL,
47
46
  clientMachineId: "",
48
- token: "",
49
- account: "",
50
- email: ""
47
+ apiKey: ""
51
48
  };
52
49
  }
53
50
  function httpBaseToWsOrigin(httpBase) {
@@ -65,21 +62,20 @@ async function ensureApmConfig() {
65
62
  }
66
63
  async function writeApmConfig(cfg) {
67
64
  const clientMachineId = resolveClientMachineId(cfg);
68
- const account = resolveAccount(cfg);
65
+ const apiKey = resolveApiKey(cfg);
69
66
  const normalized = {
70
67
  baseUrl: cfg.baseUrl.trim().replace(/\/+$/, ""),
71
- token: cfg.token,
72
- ...clientMachineId ? { clientMachineId } : {},
73
- ...account ? { account, email: account } : {}
68
+ apiKey,
69
+ ...clientMachineId ? { clientMachineId } : {}
74
70
  };
75
71
  mkdirSync(APM_CONFIG_DIR, { recursive: true });
76
72
  writeFileSync(APM_CONFIG_PATH, JSON.stringify(normalized, null, 2) + "\n", {
77
73
  mode: 384
78
74
  });
79
75
  }
80
- function buildAgentWsUrl(httpBase, token) {
76
+ function buildAgentWsUrl(httpBase, apiKey) {
81
77
  const origin = httpBaseToWsOrigin(httpBase);
82
- const q = new URLSearchParams({ token });
78
+ const q = new URLSearchParams({ apiKey });
83
79
  return `${origin}/ws/agent?${q.toString()}`;
84
80
  }
85
81
 
@@ -140,9 +136,9 @@ function resolveSessionDocumentPath(sessionId, documentName, apmRoot) {
140
136
  }
141
137
  async function ensureLoggedConfig() {
142
138
  const cfg = await ensureApmConfig();
143
- if (!cfg.token) {
139
+ if (!resolveApiKey(cfg)) {
144
140
  console.error(
145
- "[apm] \u672A\u68C0\u6D4B\u5230 token\uFF0C\u8BF7\u5148\u6267\u884C: apm login --email ... --password ..."
141
+ "[apm] \u672A\u68C0\u6D4B\u5230 API Key\uFF0C\u8BF7\u5148\u6267\u884C: apm login --api-key cm_xxx"
146
142
  );
147
143
  process.exit(1);
148
144
  }
@@ -207,14 +203,11 @@ import { createApiClient } from "listpage-http";
207
203
  // src/api/request-config.ts
208
204
  import { defineEndpoint } from "listpage-http";
209
205
  var requestConfig = {
210
- auth: {
211
- login: defineEndpoint({
212
- method: "POST",
213
- path: "/auth/login",
214
- authRequired: false
215
- })
216
- },
217
206
  cli: {
207
+ me: defineEndpoint({
208
+ method: "GET",
209
+ path: "/cli/me"
210
+ }),
218
211
  sessionDetail: defineEndpoint({
219
212
  method: "GET",
220
213
  path: "/cli/sessions/detail"
@@ -269,7 +262,7 @@ function createApmApiClient(cfg) {
269
262
  const baseURL = `${cfg.baseUrl.trim().replace(/\/+$/, "")}/api/v1`;
270
263
  return createApiClient(requestConfig, {
271
264
  baseURL,
272
- getToken: () => cfg.token || void 0,
265
+ getToken: () => resolveApiKey(cfg) || void 0,
273
266
  successCodes: [0],
274
267
  unauthorizedCodes: [401]
275
268
  });
@@ -278,22 +271,25 @@ function createApmApiClient(cfg) {
278
271
  // src/commands/login.ts
279
272
  async function runLogin(opts) {
280
273
  const baseUrl = (opts.server?.trim() || process.env.AI_PM_SERVER?.trim() || DEFAULT_BASE_URL).replace(/\/+$/, "");
274
+ const apiKey = (opts.apiKey?.trim() || process.env.APM_API_KEY?.trim() || "").replace(/^Bearer\s+/i, "");
275
+ if (!apiKey.startsWith("cm_")) {
276
+ console.error("[apm] \u8BF7\u63D0\u4F9B\u6709\u6548\u7684 API Key\uFF08cm_ \u5F00\u5934\uFF09");
277
+ console.error("[apm] \u7528\u6CD5: apm login --api-key cm_xxx [--server URL]");
278
+ process.exit(1);
279
+ }
281
280
  const api = createApmApiClient({
282
281
  baseUrl,
283
282
  clientMachineId: "",
284
- token: ""
283
+ apiKey
285
284
  });
286
285
  let data;
287
286
  try {
288
- data = await api.auth.login({
289
- account: opts.email,
290
- password: opts.password
291
- });
287
+ data = await api.cli.me({});
292
288
  } catch (raw) {
293
289
  if (raw instanceof ApiError) {
294
290
  const err = raw;
295
291
  console.error(
296
- `[apm] \u767B\u5F55\u5931\u8D25 (${err.httpStatus ?? err.code}):`,
292
+ `[apm] API Key \u9A8C\u8BC1\u5931\u8D25 (${err.httpStatus ?? err.code}):`,
297
293
  err.message
298
294
  );
299
295
  process.exit(1);
@@ -301,26 +297,25 @@ async function runLogin(opts) {
301
297
  console.error("[apm] \u8BF7\u6C42\u5931\u8D25:", raw instanceof Error ? raw.message : raw);
302
298
  process.exit(1);
303
299
  }
304
- const clientMachineId = data?.clientMachine?.id;
305
- const token = data?.token;
306
- if (!clientMachineId || !token) {
307
- console.error(
308
- "[apm] \u54CD\u5E94\u7F3A\u5C11 clientMachine.id / token\uFF08\u8BF7\u786E\u8BA4\u670D\u52A1\u7AEF\u4E3A /api/v1/auth/login\uFF09"
309
- );
300
+ const clientMachineId = data?.clientMachineId;
301
+ if (!clientMachineId) {
302
+ console.error("[apm] \u54CD\u5E94\u7F3A\u5C11 clientMachineId");
310
303
  process.exit(1);
311
304
  }
312
305
  const cfg = {
313
306
  baseUrl,
314
307
  clientMachineId,
315
- token,
316
- account: opts.email,
317
- email: opts.email
308
+ apiKey
318
309
  };
319
310
  await writeApmConfig(cfg);
320
311
  console.error(`[apm] \u5DF2\u4FDD\u5B58\u767B\u5F55\u4FE1\u606F: ${APM_CONFIG_PATH}`);
321
312
  console.log(
322
313
  JSON.stringify(
323
- { clientMachineId: cfg.clientMachineId, baseUrl: cfg.baseUrl },
314
+ {
315
+ clientMachineId: cfg.clientMachineId,
316
+ clientName: data.clientName,
317
+ baseUrl: cfg.baseUrl
318
+ },
324
319
  null,
325
320
  2
326
321
  )
@@ -1224,7 +1219,8 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1224
1219
  let lastRunAt = 0;
1225
1220
  let timer;
1226
1221
  let latestSession;
1227
- const syncDirtyEvents = async (session) => {
1222
+ let syncChain = Promise.resolve();
1223
+ const syncDirtyEventsOnce = async (session) => {
1228
1224
  const events = session.getDirtyEvents();
1229
1225
  if (events.length === 0) {
1230
1226
  return;
@@ -1237,6 +1233,14 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1237
1233
  onError(err);
1238
1234
  }
1239
1235
  };
1236
+ const drainDirtyEvents = async (session) => {
1237
+ while (session.getDirtyEvents().length > 0) {
1238
+ await syncDirtyEventsOnce(session);
1239
+ }
1240
+ };
1241
+ const enqueueSync = (session) => {
1242
+ syncChain = syncChain.then(() => drainDirtyEvents(session));
1243
+ };
1240
1244
  return {
1241
1245
  schedule(session) {
1242
1246
  latestSession = session;
@@ -1247,7 +1251,7 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1247
1251
  clearTimeout(timer);
1248
1252
  timer = void 0;
1249
1253
  }
1250
- void syncDirtyEvents(session);
1254
+ enqueueSync(session);
1251
1255
  return;
1252
1256
  }
1253
1257
  if (timer) {
@@ -1255,7 +1259,7 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1255
1259
  }
1256
1260
  timer = setTimeout(() => {
1257
1261
  timer = void 0;
1258
- void syncDirtyEvents(latestSession);
1262
+ enqueueSync(latestSession);
1259
1263
  }, CURSOR_MESSAGE_LOG_SYNC_INTERVAL_MS - elapsed);
1260
1264
  },
1261
1265
  async flush(session) {
@@ -1264,7 +1268,8 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1264
1268
  clearTimeout(timer);
1265
1269
  timer = void 0;
1266
1270
  }
1267
- await syncDirtyEvents(session);
1271
+ await syncChain;
1272
+ await drainDirtyEvents(session);
1268
1273
  }
1269
1274
  };
1270
1275
  }
@@ -1438,7 +1443,7 @@ async function runConnect(options) {
1438
1443
  console.error("[apm] config \u7F3A\u5C11 clientMachineId\uFF0C\u8BF7\u91CD\u65B0 apm login");
1439
1444
  process.exit(1);
1440
1445
  }
1441
- const url = buildAgentWsUrl(cfg.baseUrl, cfg.token);
1446
+ const url = buildAgentWsUrl(cfg.baseUrl, resolveApiKey(cfg));
1442
1447
  console.log(`[apm] \u8FDE\u63A5 ${cfg.baseUrl} \u2026`);
1443
1448
  await new Promise((resolve5, reject) => {
1444
1449
  const ws = new WebSocket(url);
@@ -2453,12 +2458,10 @@ function buildProgram() {
2453
2458
  \u672A\u4F20 --server \u65F6\u4F18\u5148\u4F7F\u7528\u73AF\u5883\u53D8\u91CF AI_PM_SERVER\uFF0C\u5426\u5219\u9ED8\u8BA4 ${DEFAULT_BASE_URL}\u3002`
2454
2459
  ).version(readCliVersion(), "-V, --version", "\u663E\u793A\u7248\u672C\u53F7").helpOption("-h, --help", "\u663E\u793A\u5E2E\u52A9").showHelpAfterError(true);
2455
2460
  program.command("login").description(
2456
- "\u8C03\u7528 POST /api/v1/auth/login\uFF0C\u5C06 token \u5199\u5165 ~/.config/apm/config.json"
2457
- ).requiredOption("--email <\u90AE\u7BB1>", "\u767B\u5F55\u90AE\u7BB1").requiredOption("--password <\u5BC6\u7801>", "\u767B\u5F55\u5BC6\u7801").option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u4F8B\u5982 http://127.0.0.1:3000").action(
2458
- async (opts) => {
2459
- await runLogin(opts);
2460
- }
2461
- );
2461
+ "\u9A8C\u8BC1 API Key \u5E76\u5199\u5165 ~/.config/apm/config.json\uFF08GET /api/v1/cli/me\uFF09"
2462
+ ).option("--api-key <key>", "\u5BA2\u6237\u673A API Key\uFF08cm_ \u5F00\u5934\uFF09").option("--server <url>", "API \u6839\u5730\u5740\uFF0C\u4F8B\u5982 http://127.0.0.1:3000").action(async (opts) => {
2463
+ await runLogin(opts);
2464
+ });
2462
2465
  program.command("init").description("\u5728\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u521D\u59CB\u5316 .apm \u6A21\u677F\uFF08\u82E5 .apm \u5DF2\u5B58\u5728\u4E14\u975E\u7A7A\u5219\u62A5\u9519\uFF09").option("--name <name>", "\u5DE5\u4F5C\u76EE\u5F55\u540D\u79F0").action(async (opts) => {
2463
2466
  await runInit(opts.name);
2464
2467
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "5.0.22",
3
+ "version": "6.0.24",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,