ai-project-manage-cli 7.1.7 → 7.1.9
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 +23 -5
- package/dist/webide-message-worker.js +32 -71
- package/package.json +1 -1
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.
|
|
6640
|
+
session.clearDirtyIfUnchanged(events);
|
|
6625
6641
|
} catch (err) {
|
|
6626
6642
|
onError(err);
|
|
6627
6643
|
}
|
|
@@ -7023,7 +7039,11 @@ async function obtainAgent(ctx) {
|
|
|
7023
7039
|
cwd: ctx.cwd,
|
|
7024
7040
|
store: createWorkspaceLocalAgentStore(ctx.workdir),
|
|
7025
7041
|
...ctx.customTools ? { customTools: ctx.customTools } : {},
|
|
7026
|
-
...ctx.enableSandbox ? {
|
|
7042
|
+
...ctx.enableSandbox ? {
|
|
7043
|
+
sandboxOptions: { enabled: true },
|
|
7044
|
+
// 只加载项目级设置,避免 ~/.cursor/mcp.json 里需 OAuth/审批的 MCP 在无头沙箱被拒
|
|
7045
|
+
settingSources: ["project"]
|
|
7046
|
+
} : {}
|
|
7027
7047
|
},
|
|
7028
7048
|
...ctx.mode ? { mode: ctx.mode } : {}
|
|
7029
7049
|
// mcpServers: createPlaywrightMcpServers(),
|
|
@@ -7084,9 +7104,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
7084
7104
|
});
|
|
7085
7105
|
const enableSandbox = Boolean(options?.enableSandbox);
|
|
7086
7106
|
let prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
7087
|
-
|
|
7088
|
-
prompt = withWorkspaceBoundaryHint(prompt);
|
|
7089
|
-
}
|
|
7107
|
+
prompt = withWorkspaceBoundaryHint(prompt);
|
|
7090
7108
|
console.log(
|
|
7091
7109
|
`[apm] Cursor Agent \u5F00\u59CB messageId=${ctx.messageId} sessionId=${ctx.sessionId} cwd=${workdir} sandbox=${enableSandbox}`
|
|
7092
7110
|
);
|
|
@@ -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.
|
|
1284
|
+
session.clearDirtyIfUnchanged(events);
|
|
1269
1285
|
} catch (err) {
|
|
1270
1286
|
onError(err);
|
|
1271
1287
|
}
|
|
@@ -1743,7 +1759,11 @@ async function obtainAgent(ctx) {
|
|
|
1743
1759
|
cwd: ctx.cwd,
|
|
1744
1760
|
store: createWorkspaceLocalAgentStore(ctx.workdir),
|
|
1745
1761
|
...ctx.customTools ? { customTools: ctx.customTools } : {},
|
|
1746
|
-
...ctx.enableSandbox ? {
|
|
1762
|
+
...ctx.enableSandbox ? {
|
|
1763
|
+
sandboxOptions: { enabled: true },
|
|
1764
|
+
// 只加载项目级设置,避免 ~/.cursor/mcp.json 里需 OAuth/审批的 MCP 在无头沙箱被拒
|
|
1765
|
+
settingSources: ["project"]
|
|
1766
|
+
} : {}
|
|
1747
1767
|
},
|
|
1748
1768
|
...ctx.mode ? { mode: ctx.mode } : {}
|
|
1749
1769
|
// mcpServers: createPlaywrightMcpServers(),
|
|
@@ -1804,9 +1824,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1804
1824
|
});
|
|
1805
1825
|
const enableSandbox = Boolean(options?.enableSandbox);
|
|
1806
1826
|
let prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
1807
|
-
|
|
1808
|
-
prompt = withWorkspaceBoundaryHint(prompt);
|
|
1809
|
-
}
|
|
1827
|
+
prompt = withWorkspaceBoundaryHint(prompt);
|
|
1810
1828
|
console.log(
|
|
1811
1829
|
`[apm] Cursor Agent \u5F00\u59CB messageId=${ctx.messageId} sessionId=${ctx.sessionId} cwd=${workdir} sandbox=${enableSandbox}`
|
|
1812
1830
|
);
|
|
@@ -2200,7 +2218,7 @@ function createThrottledWebIdeMessageLogSync(cfg, ctx, onError) {
|
|
|
2200
2218
|
await upsertLogHeader(cfg, ctx, {
|
|
2201
2219
|
eventCount: session.getEventCount()
|
|
2202
2220
|
});
|
|
2203
|
-
session.
|
|
2221
|
+
session.clearDirtyIfUnchanged(events);
|
|
2204
2222
|
} catch (err) {
|
|
2205
2223
|
onError(err);
|
|
2206
2224
|
}
|
|
@@ -2581,66 +2599,9 @@ async function ensureWebIdeDraftPullRequests(cfg, taskId, workdir) {
|
|
|
2581
2599
|
}
|
|
2582
2600
|
}
|
|
2583
2601
|
|
|
2584
|
-
// src/commands/connect/ensure-workspace-permissions.ts
|
|
2585
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
|
|
2586
|
-
import { join as join8 } from "path";
|
|
2587
|
-
var WEBIDE_MCP_ALLOWLIST = ["custom-user-tools:*"];
|
|
2588
|
-
function parsePermissionsConfig(raw) {
|
|
2589
|
-
try {
|
|
2590
|
-
const parsed = JSON.parse(raw);
|
|
2591
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
2592
|
-
return void 0;
|
|
2593
|
-
}
|
|
2594
|
-
return parsed;
|
|
2595
|
-
} catch {
|
|
2596
|
-
return void 0;
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
function mergeMcpAllowlist(existing) {
|
|
2600
|
-
const merged = /* @__PURE__ */ new Set([
|
|
2601
|
-
...existing ?? [],
|
|
2602
|
-
...WEBIDE_MCP_ALLOWLIST
|
|
2603
|
-
]);
|
|
2604
|
-
return [...merged];
|
|
2605
|
-
}
|
|
2606
|
-
function needsMcpAllowlistUpdate(existing) {
|
|
2607
|
-
const current = existing ?? [];
|
|
2608
|
-
return WEBIDE_MCP_ALLOWLIST.some((entry) => !current.includes(entry));
|
|
2609
|
-
}
|
|
2610
|
-
function ensureWorkspacePermissionsConfig(workdir) {
|
|
2611
|
-
const cursorDir = toFsPath(join8(workdir, ".cursor"));
|
|
2612
|
-
const permissionsPath = toFsPath(join8(cursorDir, "permissions.json"));
|
|
2613
|
-
let config = {};
|
|
2614
|
-
if (existsSync6(permissionsPath)) {
|
|
2615
|
-
const raw = readFileSync8(permissionsPath, "utf8");
|
|
2616
|
-
const parsed = parsePermissionsConfig(raw);
|
|
2617
|
-
if (!parsed) {
|
|
2618
|
-
console.warn(
|
|
2619
|
-
`[apm] \u5DE5\u4F5C\u533A permissions.json \u65E0\u6CD5\u89E3\u6790\uFF0C\u8DF3\u8FC7\u5199\u5165\uFF1A${permissionsPath}`
|
|
2620
|
-
);
|
|
2621
|
-
return;
|
|
2622
|
-
}
|
|
2623
|
-
config = parsed;
|
|
2624
|
-
}
|
|
2625
|
-
if (!needsMcpAllowlistUpdate(config.mcpAllowlist)) {
|
|
2626
|
-
return;
|
|
2627
|
-
}
|
|
2628
|
-
config.mcpAllowlist = mergeMcpAllowlist(config.mcpAllowlist);
|
|
2629
|
-
mkdirSync7(cursorDir, { recursive: true });
|
|
2630
|
-
writeFileSync9(
|
|
2631
|
-
permissionsPath,
|
|
2632
|
-
`${JSON.stringify(config, null, 2)}
|
|
2633
|
-
`,
|
|
2634
|
-
"utf8"
|
|
2635
|
-
);
|
|
2636
|
-
console.log(
|
|
2637
|
-
`[apm] \u5DF2\u66F4\u65B0\u5DE5\u4F5C\u533A permissions \u914D\u7F6E\uFF08mcpAllowlist\uFF09\uFF1A${permissionsPath}`
|
|
2638
|
-
);
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
2602
|
// src/commands/connect/ensure-workspace-sandbox.ts
|
|
2642
|
-
import { mkdirSync as
|
|
2643
|
-
import { join as
|
|
2603
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync9, existsSync as existsSync6 } from "fs";
|
|
2604
|
+
import { join as join8 } from "path";
|
|
2644
2605
|
var DEFAULT_SANDBOX_JSON = `{
|
|
2645
2606
|
"type": "workspace_readwrite",
|
|
2646
2607
|
"networkPolicy": {
|
|
@@ -2649,11 +2610,11 @@ var DEFAULT_SANDBOX_JSON = `{
|
|
|
2649
2610
|
}
|
|
2650
2611
|
`;
|
|
2651
2612
|
function ensureWorkspaceSandboxConfig(workdir) {
|
|
2652
|
-
const cursorDir = toFsPath(
|
|
2653
|
-
const sandboxPath = toFsPath(
|
|
2654
|
-
if (
|
|
2655
|
-
|
|
2656
|
-
|
|
2613
|
+
const cursorDir = toFsPath(join8(workdir, ".cursor"));
|
|
2614
|
+
const sandboxPath = toFsPath(join8(cursorDir, "sandbox.json"));
|
|
2615
|
+
if (existsSync6(sandboxPath)) return;
|
|
2616
|
+
mkdirSync7(cursorDir, { recursive: true });
|
|
2617
|
+
writeFileSync9(sandboxPath, DEFAULT_SANDBOX_JSON, "utf8");
|
|
2657
2618
|
console.log(`[apm] \u5DF2\u5199\u5165\u5DE5\u4F5C\u533A sandbox \u914D\u7F6E\uFF1A${sandboxPath}`);
|
|
2658
2619
|
}
|
|
2659
2620
|
|
|
@@ -2686,7 +2647,6 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
|
|
|
2686
2647
|
assertApmGitignoredInRepo(workdir);
|
|
2687
2648
|
}
|
|
2688
2649
|
ensureWorkspaceSandboxConfig(workdir);
|
|
2689
|
-
ensureWorkspacePermissionsConfig(workdir);
|
|
2690
2650
|
resolveWorkspaceRepos(workdir);
|
|
2691
2651
|
if (shouldRunBranch(branchCacheKey, workdir)) {
|
|
2692
2652
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
@@ -2727,6 +2687,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
|
|
|
2727
2687
|
signal
|
|
2728
2688
|
}),
|
|
2729
2689
|
enableWebIdePlanTools: true,
|
|
2690
|
+
// sandbox:工作区 FS 硬隔离;自定义工具由 CLI createCursorCustomTools 注册
|
|
2730
2691
|
enableSandbox: true,
|
|
2731
2692
|
taskId,
|
|
2732
2693
|
createRemoteLogSync: (agentId) => {
|