ai-project-manage-cli 7.1.6 → 7.1.8

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
@@ -6469,6 +6469,22 @@ var EventSession = class {
6469
6469
  this.dirtyIndices.delete(index);
6470
6470
  }
6471
6471
  }
6472
+ /**
6473
+ * 仅清除仍与上传快照一致的 dirty index。
6474
+ * 异步同步期间若事件内容又变了,保留 dirty,由下一轮 drain 继续覆盖写入。
6475
+ */
6476
+ clearDirtyIfUnchanged(synced) {
6477
+ for (const { index, data } of synced) {
6478
+ const event = this.events[index];
6479
+ if (!event) {
6480
+ this.dirtyIndices.delete(index);
6481
+ continue;
6482
+ }
6483
+ if (JSON.stringify(event) === data) {
6484
+ this.dirtyIndices.delete(index);
6485
+ }
6486
+ }
6487
+ }
6472
6488
  getEventCount() {
6473
6489
  return this.events.length;
6474
6490
  }
@@ -6621,7 +6637,7 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
6621
6637
  lastRunAt = Date.now();
6622
6638
  try {
6623
6639
  await syncCursorMessageLog(cfg, ctx, events);
6624
- session.clearDirty(events.map((event) => event.index));
6640
+ session.clearDirtyIfUnchanged(events);
6625
6641
  } catch (err) {
6626
6642
  onError(err);
6627
6643
  }
@@ -1113,6 +1113,22 @@ var EventSession = class {
1113
1113
  this.dirtyIndices.delete(index);
1114
1114
  }
1115
1115
  }
1116
+ /**
1117
+ * 仅清除仍与上传快照一致的 dirty index。
1118
+ * 异步同步期间若事件内容又变了,保留 dirty,由下一轮 drain 继续覆盖写入。
1119
+ */
1120
+ clearDirtyIfUnchanged(synced) {
1121
+ for (const { index, data } of synced) {
1122
+ const event = this.events[index];
1123
+ if (!event) {
1124
+ this.dirtyIndices.delete(index);
1125
+ continue;
1126
+ }
1127
+ if (JSON.stringify(event) === data) {
1128
+ this.dirtyIndices.delete(index);
1129
+ }
1130
+ }
1131
+ }
1116
1132
  getEventCount() {
1117
1133
  return this.events.length;
1118
1134
  }
@@ -1265,7 +1281,7 @@ function createThrottledCursorMessageLogSync(cfg, ctx, onError) {
1265
1281
  lastRunAt = Date.now();
1266
1282
  try {
1267
1283
  await syncCursorMessageLog(cfg, ctx, events);
1268
- session.clearDirty(events.map((event) => event.index));
1284
+ session.clearDirtyIfUnchanged(events);
1269
1285
  } catch (err) {
1270
1286
  onError(err);
1271
1287
  }
@@ -2200,7 +2216,7 @@ function createThrottledWebIdeMessageLogSync(cfg, ctx, onError) {
2200
2216
  await upsertLogHeader(cfg, ctx, {
2201
2217
  eventCount: session.getEventCount()
2202
2218
  });
2203
- session.clearDirty(events.map((e) => e.index));
2219
+ session.clearDirtyIfUnchanged(events);
2204
2220
  } catch (err) {
2205
2221
  onError(err);
2206
2222
  }
@@ -2581,9 +2597,66 @@ async function ensureWebIdeDraftPullRequests(cfg, taskId, workdir) {
2581
2597
  }
2582
2598
  }
2583
2599
 
2584
- // src/commands/connect/ensure-workspace-sandbox.ts
2585
- import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync9, existsSync as existsSync6 } from "fs";
2600
+ // src/commands/connect/ensure-workspace-permissions.ts
2601
+ import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
2586
2602
  import { join as join8 } from "path";
2603
+ var WEBIDE_MCP_ALLOWLIST = ["custom-user-tools:*"];
2604
+ function parsePermissionsConfig(raw) {
2605
+ try {
2606
+ const parsed = JSON.parse(raw);
2607
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2608
+ return void 0;
2609
+ }
2610
+ return parsed;
2611
+ } catch {
2612
+ return void 0;
2613
+ }
2614
+ }
2615
+ function mergeMcpAllowlist(existing) {
2616
+ const merged = /* @__PURE__ */ new Set([
2617
+ ...existing ?? [],
2618
+ ...WEBIDE_MCP_ALLOWLIST
2619
+ ]);
2620
+ return [...merged];
2621
+ }
2622
+ function needsMcpAllowlistUpdate(existing) {
2623
+ const current = existing ?? [];
2624
+ return WEBIDE_MCP_ALLOWLIST.some((entry) => !current.includes(entry));
2625
+ }
2626
+ function ensureWorkspacePermissionsConfig(workdir) {
2627
+ const cursorDir = toFsPath(join8(workdir, ".cursor"));
2628
+ const permissionsPath = toFsPath(join8(cursorDir, "permissions.json"));
2629
+ let config = {};
2630
+ if (existsSync6(permissionsPath)) {
2631
+ const raw = readFileSync8(permissionsPath, "utf8");
2632
+ const parsed = parsePermissionsConfig(raw);
2633
+ if (!parsed) {
2634
+ console.warn(
2635
+ `[apm] \u5DE5\u4F5C\u533A permissions.json \u65E0\u6CD5\u89E3\u6790\uFF0C\u8DF3\u8FC7\u5199\u5165\uFF1A${permissionsPath}`
2636
+ );
2637
+ return;
2638
+ }
2639
+ config = parsed;
2640
+ }
2641
+ if (!needsMcpAllowlistUpdate(config.mcpAllowlist)) {
2642
+ return;
2643
+ }
2644
+ config.mcpAllowlist = mergeMcpAllowlist(config.mcpAllowlist);
2645
+ mkdirSync7(cursorDir, { recursive: true });
2646
+ writeFileSync9(
2647
+ permissionsPath,
2648
+ `${JSON.stringify(config, null, 2)}
2649
+ `,
2650
+ "utf8"
2651
+ );
2652
+ console.log(
2653
+ `[apm] \u5DF2\u66F4\u65B0\u5DE5\u4F5C\u533A permissions \u914D\u7F6E\uFF08mcpAllowlist\uFF09\uFF1A${permissionsPath}`
2654
+ );
2655
+ }
2656
+
2657
+ // src/commands/connect/ensure-workspace-sandbox.ts
2658
+ import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync10, existsSync as existsSync7 } from "fs";
2659
+ import { join as join9 } from "path";
2587
2660
  var DEFAULT_SANDBOX_JSON = `{
2588
2661
  "type": "workspace_readwrite",
2589
2662
  "networkPolicy": {
@@ -2592,11 +2665,11 @@ var DEFAULT_SANDBOX_JSON = `{
2592
2665
  }
2593
2666
  `;
2594
2667
  function ensureWorkspaceSandboxConfig(workdir) {
2595
- const cursorDir = toFsPath(join8(workdir, ".cursor"));
2596
- const sandboxPath = toFsPath(join8(cursorDir, "sandbox.json"));
2597
- if (existsSync6(sandboxPath)) return;
2598
- mkdirSync7(cursorDir, { recursive: true });
2599
- writeFileSync9(sandboxPath, DEFAULT_SANDBOX_JSON, "utf8");
2668
+ const cursorDir = toFsPath(join9(workdir, ".cursor"));
2669
+ const sandboxPath = toFsPath(join9(cursorDir, "sandbox.json"));
2670
+ if (existsSync7(sandboxPath)) return;
2671
+ mkdirSync8(cursorDir, { recursive: true });
2672
+ writeFileSync10(sandboxPath, DEFAULT_SANDBOX_JSON, "utf8");
2600
2673
  console.log(`[apm] \u5DF2\u5199\u5165\u5DE5\u4F5C\u533A sandbox \u914D\u7F6E\uFF1A${sandboxPath}`);
2601
2674
  }
2602
2675
 
@@ -2629,6 +2702,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
2629
2702
  assertApmGitignoredInRepo(workdir);
2630
2703
  }
2631
2704
  ensureWorkspaceSandboxConfig(workdir);
2705
+ ensureWorkspacePermissionsConfig(workdir);
2632
2706
  resolveWorkspaceRepos(workdir);
2633
2707
  if (shouldRunBranch(branchCacheKey, workdir)) {
2634
2708
  if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "7.1.6",
3
+ "version": "7.1.8",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,