ai-project-manage-cli 6.0.50 → 6.0.51

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 +80 -21
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -81,10 +81,17 @@ function buildAgentWsUrl(httpBase, apiKey) {
81
81
 
82
82
  // src/commands/init.ts
83
83
  import { join as join4 } from "path";
84
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
84
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
85
85
 
86
86
  // src/command-utils.ts
87
- import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
87
+ import {
88
+ copyFileSync,
89
+ existsSync,
90
+ mkdirSync as mkdirSync2,
91
+ readFileSync as readFileSync2,
92
+ readdirSync,
93
+ statSync
94
+ } from "fs";
88
95
  import { basename, dirname, extname, join as join2, resolve as resolve2 } from "path";
89
96
  import { fileURLToPath } from "url";
90
97
 
@@ -141,6 +148,56 @@ var CLI_TEMPLATE_DIR = resolve2(__dirname, "../template");
141
148
  function workspaceApmDir(cwd = resolveWorkdirPath()) {
142
149
  return resolve2(resolve2(cwd), ".apm");
143
150
  }
151
+ function assertWorkspaceApmDirExists(workdir) {
152
+ const apmDir = workspaceApmDir(workdir);
153
+ const fsApmDir = toFsPath(apmDir);
154
+ if (!existsSync(fsApmDir)) {
155
+ throw new Error(
156
+ `\u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u4E0B\u672A\u68C0\u6D4B\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5728\u8BE5\u4ED3\u5E93\u6839\u76EE\u5F55\u6267\u884C apm init \u5B8C\u6210\u63A5\u5165\u3002`
157
+ );
158
+ }
159
+ const st = statSync(fsApmDir);
160
+ if (!st.isDirectory()) {
161
+ throw new Error(
162
+ `\u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u4E0B\u7684 .apm \u4E0D\u662F\u76EE\u5F55\uFF0C\u8BF7\u68C0\u67E5\u672C\u5730\u63A5\u5165\u72B6\u6001\u3002`
163
+ );
164
+ }
165
+ }
166
+ var APM_GITIGNORE_PATTERNS = [
167
+ /^\.apm\/?$/,
168
+ /^\.apm\/\*\*$/,
169
+ /^\*\*\/\.apm\/?$/,
170
+ /^\*\*\/\.apm\/\*\*$/,
171
+ /^\/\.apm\/?$/,
172
+ /^\/\.apm\/\*\*$/
173
+ ];
174
+ function normalizeGitignorePattern(line) {
175
+ const trimmed = line.trim();
176
+ if (!trimmed || trimmed.startsWith("#")) return "";
177
+ if (trimmed.startsWith("!")) return "";
178
+ const hashIndex = trimmed.indexOf("#");
179
+ return (hashIndex >= 0 ? trimmed.slice(0, hashIndex) : trimmed).trim();
180
+ }
181
+ function gitignoreIgnoresApm(line) {
182
+ const pattern = normalizeGitignorePattern(line);
183
+ if (!pattern) return false;
184
+ return APM_GITIGNORE_PATTERNS.some((re) => re.test(pattern));
185
+ }
186
+ function assertApmGitignoredInRepo(workdir) {
187
+ const gitignorePath = join2(workdir, ".gitignore");
188
+ const fsGitignorePath = toFsPath(gitignorePath);
189
+ if (!existsSync(fsGitignorePath)) {
190
+ throw new Error(
191
+ `\u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u7F3A\u5C11 .gitignore \u6587\u4EF6\uFF0C\u8BF7\u6DFB\u52A0\u5BF9 .apm \u7684\u5FFD\u7565\u89C4\u5219\uFF08\u4F8B\u5982 **/.apm/**\uFF09\uFF0C\u907F\u514D\u672C\u5730\u4F1A\u8BDD\u4E0E\u90E8\u7F72\u51ED\u636E\u88AB\u63D0\u4EA4\u3002`
192
+ );
193
+ }
194
+ const content = readFileSync2(fsGitignorePath, "utf8");
195
+ if (!content.split(/\r?\n/).some(gitignoreIgnoresApm)) {
196
+ throw new Error(
197
+ `\u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u7684 .gitignore \u672A\u5FFD\u7565 .apm\uFF0C\u8BF7\u6DFB\u52A0 **/.apm/** \u6216 .apm/\uFF0C\u907F\u514D\u672C\u5730\u4F1A\u8BDD\u4E0E\u90E8\u7F72\u51ED\u636E\u88AB\u63D0\u4EA4\u3002`
198
+ );
199
+ }
200
+ }
144
201
  var SESSIONS_SUBDIR = "sessions";
145
202
  var SESSION_DOCS_SUBDIR = "docs";
146
203
  var SESSION_ATTACHMENTS_SUBDIR = "attachments";
@@ -492,7 +549,7 @@ async function runInit(name) {
492
549
  const trimmedName = name?.trim();
493
550
  if (trimmedName) {
494
551
  const apmConfigPath = toFsPath(join4(apmDir, "apm.config.json"));
495
- const config = readFileSync2(apmConfigPath, "utf8");
552
+ const config = readFileSync3(apmConfigPath, "utf8");
496
553
  const configJson = JSON.parse(config);
497
554
  configJson.name = trimmedName;
498
555
  writeFileSync3(
@@ -775,7 +832,7 @@ function formatSessionMessagesXml(sessionId, messages) {
775
832
  }
776
833
 
777
834
  // src/commands/sync-session-attachments.ts
778
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
835
+ import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
779
836
  import { join as join5 } from "path";
780
837
  var MANIFEST_FILE = ".sync-manifest.json";
781
838
  async function downloadAttachment(cfg, attachmentId) {
@@ -796,7 +853,7 @@ function loadManifest(dir) {
796
853
  }
797
854
  try {
798
855
  const parsed = JSON.parse(
799
- readFileSync3(path10, "utf8")
856
+ readFileSync4(path10, "utf8")
800
857
  );
801
858
  if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
802
859
  return parsed;
@@ -852,7 +909,7 @@ async function syncSessionAttachments(cfg, sessionId, attachments, apmRoot) {
852
909
 
853
910
  // src/rules-sync.ts
854
911
  import { basename as basename2, extname as extname2, join as join7 } from "path";
855
- import { existsSync as existsSync5, readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
912
+ import { existsSync as existsSync5, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
856
913
 
857
914
  // src/skills-sync.ts
858
915
  import {
@@ -960,7 +1017,7 @@ function loadManifest2(rulesDir) {
960
1017
  }
961
1018
  try {
962
1019
  const parsed = JSON.parse(
963
- readFileSync4(toFsPath(path10), "utf8")
1020
+ readFileSync5(toFsPath(path10), "utf8")
964
1021
  );
965
1022
  if (parsed?.version === 1 && parsed.rules && typeof parsed.rules === "object") {
966
1023
  return parsed;
@@ -985,7 +1042,7 @@ function isRuleUpToDate(entry, rule, dest) {
985
1042
  if (entry.fileName !== ruleLocalFileName(rule.name)) return false;
986
1043
  const updatedAt = rule.updatedAt ?? "";
987
1044
  if (entry.updatedAt !== updatedAt) return false;
988
- const localContent = readFileSync4(toFsPath(dest), "utf8");
1045
+ const localContent = readFileSync5(toFsPath(dest), "utf8");
989
1046
  return localContent === (rule.content ?? "");
990
1047
  }
991
1048
  async function syncPlatformRules(cfg, sessionId, workdirPath, apmRoot) {
@@ -1112,7 +1169,7 @@ async function runPull(sessionId, remoteWorkdir) {
1112
1169
  import { spawnSync } from "child_process";
1113
1170
 
1114
1171
  // src/version.ts
1115
- import { readFileSync as readFileSync5 } from "fs";
1172
+ import { readFileSync as readFileSync6 } from "fs";
1116
1173
  import { dirname as dirname2, join as join9 } from "path";
1117
1174
  import { fileURLToPath as fileURLToPath2 } from "url";
1118
1175
  var CLI_PACKAGE_NAME = "ai-project-manage-cli";
@@ -1120,7 +1177,7 @@ function readCliVersion() {
1120
1177
  try {
1121
1178
  const dir = dirname2(fileURLToPath2(import.meta.url));
1122
1179
  const pkgPath = join9(dir, "..", "package.json");
1123
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
1180
+ const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
1124
1181
  return pkg.version ?? "0.0.0";
1125
1182
  } catch {
1126
1183
  return "0.0.0";
@@ -1266,7 +1323,7 @@ import { existsSync as existsSync9 } from "fs";
1266
1323
  import { basename as basename3 } from "path";
1267
1324
 
1268
1325
  // src/commands/sync-session-documents.ts
1269
- import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
1326
+ import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync7 } from "fs";
1270
1327
  import { join as join11 } from "path";
1271
1328
  function listLocalMarkdownFiles(docsDir) {
1272
1329
  if (!existsSync8(docsDir)) {
@@ -1285,7 +1342,7 @@ function remoteDocumentByLocalName(remoteDocuments, localFileName) {
1285
1342
  }
1286
1343
  async function upsertLocalDocumentFile(api, sessionId, docsDir, fileName) {
1287
1344
  const absPath = join11(docsDir, fileName);
1288
- const content = readFileSync6(absPath, "utf8");
1345
+ const content = readFileSync7(absPath, "utf8");
1289
1346
  const name = documentPlatformName(absPath);
1290
1347
  return api.cli.upsertDocument({
1291
1348
  sessionId,
@@ -1308,7 +1365,7 @@ async function syncSessionDocuments(cfg, sessionId, apmRoot, options) {
1308
1365
  let synced = 0;
1309
1366
  for (const fileName of localFiles) {
1310
1367
  const absPath = join11(docsDir, fileName);
1311
- const content = readFileSync6(absPath, "utf8");
1368
+ const content = readFileSync7(absPath, "utf8");
1312
1369
  const remote = remoteDocumentByLocalName(remoteDocuments, fileName);
1313
1370
  if (remote && remote.content === content) {
1314
1371
  continue;
@@ -1741,7 +1798,7 @@ ${JSON.stringify(event, null, 2)}
1741
1798
  }
1742
1799
 
1743
1800
  // src/commands/connect/agent-session-registry.ts
1744
- import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "node:fs";
1801
+ import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "node:fs";
1745
1802
  import { dirname as dirname3, resolve as resolve3 } from "node:path";
1746
1803
  function registryPath(workdir, sessionId) {
1747
1804
  return resolve3(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
@@ -1751,7 +1808,7 @@ function readRegistry(path10) {
1751
1808
  return {};
1752
1809
  }
1753
1810
  try {
1754
- const parsed = JSON.parse(readFileSync7(path10, "utf8"));
1811
+ const parsed = JSON.parse(readFileSync8(path10, "utf8"));
1755
1812
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1756
1813
  const result = {};
1757
1814
  for (const [key, value] of Object.entries(
@@ -2159,6 +2216,8 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
2159
2216
  };
2160
2217
  try {
2161
2218
  if (signal.aborted) return;
2219
+ assertWorkspaceApmDirExists(workdir);
2220
+ assertApmGitignoredInRepo(workdir);
2162
2221
  await runStep(
2163
2222
  "status-typing",
2164
2223
  () => updateMessageStatus(cfg, messageId, "TYPING")
@@ -2411,7 +2470,7 @@ async function runCreatePr(options) {
2411
2470
  import path5 from "node:path";
2412
2471
 
2413
2472
  // src/commands/deploy/internal/apm-config.ts
2414
- import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
2473
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
2415
2474
  import { resolve as resolve4 } from "node:path";
2416
2475
  function loadApmConfig(options) {
2417
2476
  const p = resolve4(
@@ -2423,7 +2482,7 @@ function loadApmConfig(options) {
2423
2482
  process.exit(1);
2424
2483
  }
2425
2484
  try {
2426
- const raw = readFileSync8(p, "utf8");
2485
+ const raw = readFileSync9(p, "utf8");
2427
2486
  return JSON.parse(raw);
2428
2487
  } catch (e) {
2429
2488
  console.error(`\u65E0\u6CD5\u89E3\u6790 apm.config.json\uFF1A${p}`, e);
@@ -2545,7 +2604,7 @@ import path4 from "node:path";
2545
2604
  import Docker from "dockerode";
2546
2605
 
2547
2606
  // src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
2548
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
2607
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
2549
2608
  import path from "node:path";
2550
2609
  function asOptionalTlsBuffer(value) {
2551
2610
  if (typeof value !== "string") {
@@ -2558,7 +2617,7 @@ function asOptionalTlsBuffer(value) {
2558
2617
  return void 0;
2559
2618
  }
2560
2619
  if (existsSync12(normalized)) {
2561
- return readFileSync9(normalized);
2620
+ return readFileSync10(normalized);
2562
2621
  }
2563
2622
  const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
2564
2623
  if (looksLikePath) {
@@ -2768,7 +2827,7 @@ var DockerodeClient = class {
2768
2827
  var createDockerodeClient = (config) => new DockerodeClient(config);
2769
2828
 
2770
2829
  // src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
2771
- import { existsSync as existsSync13, readFileSync as readFileSync10, statSync as statSync5 } from "node:fs";
2830
+ import { existsSync as existsSync13, readFileSync as readFileSync11, statSync as statSync5 } from "node:fs";
2772
2831
  import path2 from "node:path";
2773
2832
  function stripSurroundingQuotes(value) {
2774
2833
  const t = value.trim();
@@ -2788,7 +2847,7 @@ function loadEnvFromFile(envFilePath) {
2788
2847
  if (!existsSync13(targetPath) || !statSync5(targetPath).isFile()) {
2789
2848
  return {};
2790
2849
  }
2791
- const raw = readFileSync10(targetPath, "utf-8");
2850
+ const raw = readFileSync11(targetPath, "utf-8");
2792
2851
  const result = {};
2793
2852
  for (const line of raw.split(/\r?\n/)) {
2794
2853
  const normalized = line.trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.50",
3
+ "version": "6.0.51",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -27,7 +27,7 @@
27
27
  "@types/ssh2-sftp-client": "~9.0.6"
28
28
  },
29
29
  "engines": {
30
- "node": ">=18"
30
+ "node": ">=22.13.0"
31
31
  },
32
32
  "dependencies": {
33
33
  "@bufbuild/protobuf": "1.10.0",