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.
- package/dist/index.js +63 -62
- 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 {
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
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=${
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1916
|
-
|
|
1917
|
-
function shouldRunBranch(sessionId) {
|
|
1918
|
-
return lastBranchSessionId !== sessionId;
|
|
1916
|
+
function sessionWorkdirKey(sessionId, workdir) {
|
|
1917
|
+
return `${sessionId}\0${workdir}`;
|
|
1919
1918
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
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
|
|
1924
|
-
|
|
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
|
-
|
|
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((
|
|
1949
|
+
return new Promise((resolve5) => {
|
|
1945
1950
|
waiters.push(() => {
|
|
1946
1951
|
active += 1;
|
|
1947
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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,
|
|
2049
|
+
() => syncSessionDocuments(cfg, msg.sessionId, apmRoot)
|
|
2049
2050
|
);
|
|
2050
2051
|
await runStep(
|
|
2051
2052
|
"commit-files",
|
|
2052
|
-
() => commitWorkingTreeIfDirty(
|
|
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((
|
|
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
|
-
|
|
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
|
|
2230
|
+
import { resolve as resolve4 } from "node:path";
|
|
2230
2231
|
function loadApmConfig(options) {
|
|
2231
|
-
const p =
|
|
2232
|
+
const p = resolve4(
|
|
2232
2233
|
process.cwd(),
|
|
2233
|
-
options?.configPath ??
|
|
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((
|
|
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
|
-
|
|
2508
|
+
resolve5(output);
|
|
2508
2509
|
});
|
|
2509
2510
|
});
|
|
2510
|
-
await new Promise((
|
|
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
|
-
|
|
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((
|
|
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",
|
|
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((
|
|
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
|
-
|
|
3265
|
+
resolve5(stdout);
|
|
3265
3266
|
}).on("data", (data) => {
|
|
3266
3267
|
stdout += data.toString();
|
|
3267
3268
|
});
|