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 CHANGED
@@ -885,7 +885,73 @@ async function runUpdateSkills() {
885
885
  }
886
886
 
887
887
  // src/commands/sync-document.ts
888
- import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
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 (!existsSync5(absPath)) {
902
- const docsDir = sessionDocsDir(trimmedSessionId);
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 ${docsDir} \u4E0B\u5B58\u5728\u5BF9\u5E94\u6587\u4EF6`
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 doc = await api.cli.upsertDocument({
914
- sessionId: trimmedSessionId,
915
- name,
916
- content
917
- });
918
- console.log(`[apm] \u5DF2\u540C\u6B65\u6587\u6863: ${name} (id=${doc.id})`);
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 existsSync6, readFileSync as readFileSync6 } from "node:fs";
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 (!existsSync6(p)) {
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 existsSync7, readFileSync as readFileSync7 } from "node:fs";
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 (existsSync7(normalized)) {
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 existsSync8, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
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 (!existsSync8(targetPath) || !statSync4(targetPath).isFile()) {
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 existsSync9 } from "node:fs";
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 (!existsSync9(dockerfilePath)) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.27",
3
+ "version": "6.0.28",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -18,9 +18,11 @@
18
18
 
19
19
  ## 在保存完成之后需要同步到远程
20
20
 
21
- 同步命令: `apm sync-document <会话 ID> --file=<文档名称>
21
+ 通过 `apm connect` 连接平台时,每轮 Agent 结束后会自动推送 `docs/` 下变更的 Markdown,一般无需手动同步。
22
22
 
23
- 示例: `apm sync-document <会话ID> --file=张三.md`
23
+ 手动同步命令: `apm sync-document <会话 ID> --file=<文档名称>`
24
+
25
+ 示例: `apm sync-document <会话ID> --file=张三-工作日志.md`
24
26
 
25
27
  ## 注意事项
26
28