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.
- package/dist/index.js +57 -54
- 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
|
|
17
|
-
return (cfg.
|
|
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"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
65
|
+
const apiKey = resolveApiKey(cfg);
|
|
69
66
|
const normalized = {
|
|
70
67
|
baseUrl: cfg.baseUrl.trim().replace(/\/+$/, ""),
|
|
71
|
-
|
|
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,
|
|
76
|
+
function buildAgentWsUrl(httpBase, apiKey) {
|
|
81
77
|
const origin = httpBaseToWsOrigin(httpBase);
|
|
82
|
-
const q = new URLSearchParams({
|
|
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
|
|
139
|
+
if (!resolveApiKey(cfg)) {
|
|
144
140
|
console.error(
|
|
145
|
-
"[apm] \u672A\u68C0\u6D4B\u5230
|
|
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
|
|
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
|
-
|
|
283
|
+
apiKey
|
|
285
284
|
});
|
|
286
285
|
let data;
|
|
287
286
|
try {
|
|
288
|
-
data = await api.
|
|
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] \
|
|
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?.
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
"\
|
|
2457
|
-
).
|
|
2458
|
-
|
|
2459
|
-
|
|
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
|
});
|