ai-project-manage-cli 6.0.27 → 6.0.28
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 +97 -20
- package/package.json +1 -1
- package/template/rules/write_doc.md +4 -2
package/dist/index.js
CHANGED
|
@@ -885,7 +885,73 @@ async function runUpdateSkills() {
|
|
|
885
885
|
}
|
|
886
886
|
|
|
887
887
|
// src/commands/sync-document.ts
|
|
888
|
-
import { existsSync as
|
|
888
|
+
import { existsSync as existsSync6 } from "fs";
|
|
889
|
+
import { basename as basename2 } from "path";
|
|
890
|
+
|
|
891
|
+
// src/commands/sync-session-documents.ts
|
|
892
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "fs";
|
|
893
|
+
import { join as join9 } from "path";
|
|
894
|
+
function listLocalMarkdownFiles(docsDir) {
|
|
895
|
+
if (!existsSync5(docsDir)) {
|
|
896
|
+
return [];
|
|
897
|
+
}
|
|
898
|
+
return readdirSync3(docsDir).filter(
|
|
899
|
+
(name) => name.toLowerCase().endsWith(".md")
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
function remoteDocumentByLocalName(remoteDocuments, localFileName) {
|
|
903
|
+
const platformName = documentPlatformName(localFileName);
|
|
904
|
+
return remoteDocuments.find((doc) => {
|
|
905
|
+
const remoteLocalName = documentLocalFileName(doc.name);
|
|
906
|
+
return remoteLocalName === localFileName || documentPlatformName(doc.name) === platformName;
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
async function upsertLocalDocumentFile(api, sessionId, docsDir, fileName) {
|
|
910
|
+
const absPath = join9(docsDir, fileName);
|
|
911
|
+
const content = readFileSync5(absPath, "utf8");
|
|
912
|
+
const name = documentPlatformName(absPath);
|
|
913
|
+
return api.cli.upsertDocument({
|
|
914
|
+
sessionId,
|
|
915
|
+
name,
|
|
916
|
+
content
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
async function syncSessionDocuments(cfg, sessionId, apmRoot, options) {
|
|
920
|
+
const trimmedSessionId = sessionId.trim();
|
|
921
|
+
if (!trimmedSessionId) {
|
|
922
|
+
return 0;
|
|
923
|
+
}
|
|
924
|
+
const docsDir = sessionDocsDir(trimmedSessionId, apmRoot);
|
|
925
|
+
const localFiles = listLocalMarkdownFiles(docsDir);
|
|
926
|
+
if (localFiles.length === 0) {
|
|
927
|
+
return 0;
|
|
928
|
+
}
|
|
929
|
+
const api = options?.api ?? createApmApiClient(cfg);
|
|
930
|
+
const remoteDocuments = options?.remoteDocuments ?? await api.cli.listDocuments({ sessionId: trimmedSessionId });
|
|
931
|
+
let synced = 0;
|
|
932
|
+
for (const fileName of localFiles) {
|
|
933
|
+
const absPath = join9(docsDir, fileName);
|
|
934
|
+
const content = readFileSync5(absPath, "utf8");
|
|
935
|
+
const remote = remoteDocumentByLocalName(remoteDocuments, fileName);
|
|
936
|
+
if (remote && remote.content === content) {
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
const doc = await upsertLocalDocumentFile(
|
|
940
|
+
api,
|
|
941
|
+
trimmedSessionId,
|
|
942
|
+
docsDir,
|
|
943
|
+
fileName
|
|
944
|
+
);
|
|
945
|
+
synced += 1;
|
|
946
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u6587\u6863: ${doc.name} (id=${doc.id})`);
|
|
947
|
+
}
|
|
948
|
+
if (synced === 0) {
|
|
949
|
+
console.log("[apm] \u4F1A\u8BDD\u6587\u6863\u65E0\u53D8\u5316\uFF0C\u8DF3\u8FC7\u63A8\u9001");
|
|
950
|
+
}
|
|
951
|
+
return synced;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/commands/sync-document.ts
|
|
889
955
|
async function runSyncDocument(sessionId, options) {
|
|
890
956
|
const trimmedSessionId = sessionId.trim();
|
|
891
957
|
if (!trimmedSessionId) {
|
|
@@ -898,24 +964,24 @@ async function runSyncDocument(sessionId, options) {
|
|
|
898
964
|
process.exit(1);
|
|
899
965
|
}
|
|
900
966
|
const absPath = resolveSessionDocumentPath(trimmedSessionId, fileArg);
|
|
901
|
-
if (!
|
|
902
|
-
const
|
|
967
|
+
if (!existsSync6(absPath)) {
|
|
968
|
+
const docsDir2 = sessionDocsDir(trimmedSessionId);
|
|
903
969
|
console.error(
|
|
904
970
|
`[apm] \u6587\u6863\u4E0D\u5B58\u5728: ${absPath}
|
|
905
|
-
[apm] \u8BF7\u786E\u8BA4\u5DF2 pull\uFF0C\u4E14 ${
|
|
971
|
+
[apm] \u8BF7\u786E\u8BA4\u5DF2 pull\uFF0C\u4E14 ${docsDir2} \u4E0B\u5B58\u5728\u5BF9\u5E94\u6587\u4EF6`
|
|
906
972
|
);
|
|
907
973
|
process.exit(1);
|
|
908
974
|
}
|
|
909
|
-
const content = readFileSync5(absPath, "utf8");
|
|
910
|
-
const name = documentPlatformName(absPath);
|
|
911
975
|
const cfg = await ensureLoggedConfig();
|
|
912
976
|
const api = createApmApiClient(cfg);
|
|
913
|
-
const
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
977
|
+
const docsDir = sessionDocsDir(trimmedSessionId);
|
|
978
|
+
const doc = await upsertLocalDocumentFile(
|
|
979
|
+
api,
|
|
980
|
+
trimmedSessionId,
|
|
981
|
+
docsDir,
|
|
982
|
+
basename2(absPath)
|
|
983
|
+
);
|
|
984
|
+
console.log(`[apm] \u5DF2\u540C\u6B65\u6587\u6863: ${doc.name} (id=${doc.id})`);
|
|
919
985
|
}
|
|
920
986
|
|
|
921
987
|
// src/commands/append-message.ts
|
|
@@ -1038,6 +1104,7 @@ function validateAgentWsMessage(value, kind) {
|
|
|
1038
1104
|
|
|
1039
1105
|
// src/commands/connect/cursor-agent.ts
|
|
1040
1106
|
import { Agent, CursorAgentError } from "@cursor/sdk";
|
|
1107
|
+
import { setMaxListeners } from "node:events";
|
|
1041
1108
|
import { resolve as resolve3 } from "path";
|
|
1042
1109
|
|
|
1043
1110
|
// src/session-utils.ts
|
|
@@ -1285,6 +1352,7 @@ async function syncCursorMessageLog(cfg, ctx, events) {
|
|
|
1285
1352
|
}
|
|
1286
1353
|
|
|
1287
1354
|
// src/commands/connect/cursor-agent.ts
|
|
1355
|
+
setMaxListeners(50);
|
|
1288
1356
|
var logCtx = (ctx, agentId) => ({
|
|
1289
1357
|
sessionId: ctx.sessionId,
|
|
1290
1358
|
messageId: ctx.messageId,
|
|
@@ -1393,6 +1461,15 @@ async function handleInboundMessage(cfg, raw) {
|
|
|
1393
1461
|
apiKey: msg.apiKey,
|
|
1394
1462
|
workdir: msg.workdir
|
|
1395
1463
|
});
|
|
1464
|
+
await syncSessionDocuments(
|
|
1465
|
+
cfg,
|
|
1466
|
+
msg.sessionId,
|
|
1467
|
+
workspaceApmDir(msg.workdir)
|
|
1468
|
+
);
|
|
1469
|
+
await commitWorkingTreeIfDirty(
|
|
1470
|
+
msg.workdir,
|
|
1471
|
+
"chore(apm): sync session documents"
|
|
1472
|
+
);
|
|
1396
1473
|
await updateMessageStatus(cfg, messageId, "SUCCESS");
|
|
1397
1474
|
} catch (err) {
|
|
1398
1475
|
console.error(
|
|
@@ -1489,14 +1566,14 @@ async function runConnect(options) {
|
|
|
1489
1566
|
import path5 from "node:path";
|
|
1490
1567
|
|
|
1491
1568
|
// src/commands/deploy/internal/apm-config.ts
|
|
1492
|
-
import { existsSync as
|
|
1569
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
|
|
1493
1570
|
import { resolve as resolve4 } from "node:path";
|
|
1494
1571
|
function loadApmConfig(options) {
|
|
1495
1572
|
const p = resolve4(
|
|
1496
1573
|
process.cwd(),
|
|
1497
1574
|
options?.configPath ?? resolve4(workspaceApmDir(), "apm.config.json")
|
|
1498
1575
|
);
|
|
1499
|
-
if (!
|
|
1576
|
+
if (!existsSync7(p)) {
|
|
1500
1577
|
console.error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\uFF1A${p}`);
|
|
1501
1578
|
process.exit(1);
|
|
1502
1579
|
}
|
|
@@ -1623,7 +1700,7 @@ import path4 from "node:path";
|
|
|
1623
1700
|
import Docker from "dockerode";
|
|
1624
1701
|
|
|
1625
1702
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
1626
|
-
import { existsSync as
|
|
1703
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
|
|
1627
1704
|
import path from "node:path";
|
|
1628
1705
|
function asOptionalTlsBuffer(value) {
|
|
1629
1706
|
if (typeof value !== "string") {
|
|
@@ -1635,7 +1712,7 @@ function asOptionalTlsBuffer(value) {
|
|
|
1635
1712
|
if (normalized === "") {
|
|
1636
1713
|
return void 0;
|
|
1637
1714
|
}
|
|
1638
|
-
if (
|
|
1715
|
+
if (existsSync8(normalized)) {
|
|
1639
1716
|
return readFileSync7(normalized);
|
|
1640
1717
|
}
|
|
1641
1718
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
@@ -1846,7 +1923,7 @@ var DockerodeClient = class {
|
|
|
1846
1923
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
1847
1924
|
|
|
1848
1925
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
1849
|
-
import { existsSync as
|
|
1926
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
1850
1927
|
import path2 from "node:path";
|
|
1851
1928
|
function stripSurroundingQuotes(value) {
|
|
1852
1929
|
const t = value.trim();
|
|
@@ -1863,7 +1940,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
1863
1940
|
return {};
|
|
1864
1941
|
}
|
|
1865
1942
|
const targetPath = path2.resolve(envFilePath);
|
|
1866
|
-
if (!
|
|
1943
|
+
if (!existsSync9(targetPath) || !statSync4(targetPath).isFile()) {
|
|
1867
1944
|
return {};
|
|
1868
1945
|
}
|
|
1869
1946
|
const raw = readFileSync8(targetPath, "utf-8");
|
|
@@ -2037,12 +2114,12 @@ function dockerPushImage(params, cwd) {
|
|
|
2037
2114
|
}
|
|
2038
2115
|
|
|
2039
2116
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
2040
|
-
import { existsSync as
|
|
2117
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
2041
2118
|
import path3 from "node:path";
|
|
2042
2119
|
function resolveDockerBuildPaths(cwd) {
|
|
2043
2120
|
const dockerfilePath = path3.join(cwd, "Dockerfile");
|
|
2044
2121
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
2045
|
-
if (!
|
|
2122
|
+
if (!existsSync10(dockerfilePath)) {
|
|
2046
2123
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
2047
2124
|
}
|
|
2048
2125
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
package/package.json
CHANGED
|
@@ -18,9 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
## 在保存完成之后需要同步到远程
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
通过 `apm connect` 连接平台时,每轮 Agent 结束后会自动推送 `docs/` 下变更的 Markdown,一般无需手动同步。
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
手动同步命令: `apm sync-document <会话 ID> --file=<文档名称>`
|
|
24
|
+
|
|
25
|
+
示例: `apm sync-document <会话ID> --file=张三-工作日志.md`
|
|
24
26
|
|
|
25
27
|
## 注意事项
|
|
26
28
|
|