ai-project-manage-cli 7.1.31 → 7.1.33
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/README.md +0 -2
- package/dist/index.js +227 -81
- package/dist/webide-message-worker.js +207 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,5 +58,3 @@ apm daemon start -f
|
|
|
58
58
|
使用全局 PM2(未安装时会自动执行 `npm install -g pm2`);同一时刻仅允许一个 connect。启动时会自动检测 CLI 更新并刷新守护配置。
|
|
59
59
|
|
|
60
60
|
`apm pull` 会自动将平台登记的**项目文档**同步到 `.apm/project/<项目ID>/`(含 `manifest.json`)。Agent 修改该目录下文件后,`apm connect` 处理完消息会自动推回平台。
|
|
61
|
-
|
|
62
|
-
详见仓库根目录 [docs/CLI.md](../../docs/CLI.md)。
|
package/dist/index.js
CHANGED
|
@@ -216,10 +216,6 @@ var init_request_config = __esm({
|
|
|
216
216
|
method: "PUT",
|
|
217
217
|
path: "/cli/webide/terminals/meta"
|
|
218
218
|
}),
|
|
219
|
-
acquireSteelBrowser: defineEndpoint({
|
|
220
|
-
method: "POST",
|
|
221
|
-
path: "/cli/steel-browser/acquire"
|
|
222
|
-
}),
|
|
223
219
|
branchBaseline: defineEndpoint({
|
|
224
220
|
method: "GET",
|
|
225
221
|
path: "/cli/tasks/branch-baseline"
|
|
@@ -444,14 +440,14 @@ var init_minio = __esm({
|
|
|
444
440
|
async deleteObjectsByPrefix(bucket, prefix) {
|
|
445
441
|
const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
|
|
446
442
|
const keys = [];
|
|
447
|
-
await new Promise((
|
|
443
|
+
await new Promise((resolve9, reject) => {
|
|
448
444
|
objectsStream.on("data", (obj) => {
|
|
449
445
|
if (obj.name) {
|
|
450
446
|
keys.push(obj.name);
|
|
451
447
|
}
|
|
452
448
|
});
|
|
453
449
|
objectsStream.on("error", reject);
|
|
454
|
-
objectsStream.on("end",
|
|
450
|
+
objectsStream.on("end", resolve9);
|
|
455
451
|
});
|
|
456
452
|
const chunkSize = 500;
|
|
457
453
|
for (let i = 0; i < keys.length; i += chunkSize) {
|
|
@@ -4608,7 +4604,8 @@ function buildConnectPm2Ecosystem(options) {
|
|
|
4608
4604
|
max_restarts: 10,
|
|
4609
4605
|
restart_delay: 3e3,
|
|
4610
4606
|
exp_backoff_restart_delay: 1e3,
|
|
4611
|
-
|
|
4607
|
+
// WebIDE Worker 与主进程同 RSS;8G 机约可到 ~6G,避免把整机打满
|
|
4608
|
+
max_memory_restart: "6G",
|
|
4612
4609
|
kill_timeout: 5e3,
|
|
4613
4610
|
shutdown_with_message: true,
|
|
4614
4611
|
instances: 1,
|
|
@@ -5716,7 +5713,7 @@ function buildSftpConnectOptions(settings) {
|
|
|
5716
5713
|
};
|
|
5717
5714
|
}
|
|
5718
5715
|
async function sleep(ms) {
|
|
5719
|
-
await new Promise((
|
|
5716
|
+
await new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
5720
5717
|
}
|
|
5721
5718
|
async function uploadZipWithRetry(settings, localZip, remoteZipPath) {
|
|
5722
5719
|
let lastError;
|
|
@@ -5760,7 +5757,7 @@ async function ensureRemoteDir(sftp, dir) {
|
|
|
5760
5757
|
}
|
|
5761
5758
|
}
|
|
5762
5759
|
function execCommand(client, command) {
|
|
5763
|
-
return new Promise((
|
|
5760
|
+
return new Promise((resolve9, reject) => {
|
|
5764
5761
|
client.exec(command, (err, stream) => {
|
|
5765
5762
|
if (err) return reject(err);
|
|
5766
5763
|
let stdout = "";
|
|
@@ -5770,7 +5767,7 @@ function execCommand(client, command) {
|
|
|
5770
5767
|
reject(new Error(`\u8FDC\u7A0B\u547D\u4EE4\u5931\u8D25 (${code}): ${stderr || stdout}`));
|
|
5771
5768
|
return;
|
|
5772
5769
|
}
|
|
5773
|
-
|
|
5770
|
+
resolve9(stdout);
|
|
5774
5771
|
}).on("data", (data) => {
|
|
5775
5772
|
stdout += data.toString();
|
|
5776
5773
|
});
|
|
@@ -6245,8 +6242,8 @@ function springbootOutputIndicatesSuccess(action, combined) {
|
|
|
6245
6242
|
async function connectSsh(config) {
|
|
6246
6243
|
const client = new Client2();
|
|
6247
6244
|
log(`\u8FDE\u63A5\u670D\u52A1\u5668 ${config.username}@${config.host}:${config.port}`);
|
|
6248
|
-
await new Promise((
|
|
6249
|
-
client.on("ready", () =>
|
|
6245
|
+
await new Promise((resolve9, reject) => {
|
|
6246
|
+
client.on("ready", () => resolve9()).on("error", (err) => reject(err)).connect({
|
|
6250
6247
|
host: config.host,
|
|
6251
6248
|
port: config.port,
|
|
6252
6249
|
username: config.username,
|
|
@@ -6314,7 +6311,7 @@ async function runRemoteCommand(client, command, options) {
|
|
|
6314
6311
|
const check = options?.check ?? true;
|
|
6315
6312
|
const stream = options?.stream ?? false;
|
|
6316
6313
|
const label = options?.label ?? "\u8FDC\u7A0B\u547D\u4EE4";
|
|
6317
|
-
return new Promise((
|
|
6314
|
+
return new Promise((resolve9, reject) => {
|
|
6318
6315
|
client.exec(command, (err, execStream) => {
|
|
6319
6316
|
if (err) {
|
|
6320
6317
|
reject(err);
|
|
@@ -6344,7 +6341,7 @@ ${errText}`.trim();
|
|
|
6344
6341
|
\u8F93\u51FA: ${combined}` : "")
|
|
6345
6342
|
);
|
|
6346
6343
|
}
|
|
6347
|
-
|
|
6344
|
+
resolve9({ exitCode: code, out: out.trim(), err: errText.trim() });
|
|
6348
6345
|
});
|
|
6349
6346
|
});
|
|
6350
6347
|
});
|
|
@@ -7245,16 +7242,118 @@ function cleanSessionWorkspaceCache(sessionId, workdir) {
|
|
|
7245
7242
|
}
|
|
7246
7243
|
|
|
7247
7244
|
// src/commands/clean-webide-cache.ts
|
|
7248
|
-
import { existsSync as
|
|
7249
|
-
import { resolve as
|
|
7250
|
-
|
|
7245
|
+
import { existsSync as existsSync24, rmSync as rmSync5 } from "node:fs";
|
|
7246
|
+
import { resolve as resolve7 } from "node:path";
|
|
7247
|
+
import { JsonlLocalAgentStore } from "@cursor/sdk";
|
|
7248
|
+
|
|
7249
|
+
// src/commands/connect/webide-agent-registry.ts
|
|
7250
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
|
|
7251
|
+
import { dirname as dirname7, resolve as resolve6 } from "node:path";
|
|
7252
|
+
function registryPath(workdir, taskId) {
|
|
7253
|
+
return resolve6(workdir, ".apm", "webide", taskId, "cursor-agent.json");
|
|
7254
|
+
}
|
|
7255
|
+
function readRegistry(path19) {
|
|
7256
|
+
if (!existsSync23(path19)) {
|
|
7257
|
+
return {};
|
|
7258
|
+
}
|
|
7259
|
+
try {
|
|
7260
|
+
const parsed = JSON.parse(readFileSync17(path19, "utf8"));
|
|
7261
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7262
|
+
const raw = parsed;
|
|
7263
|
+
const state = {};
|
|
7264
|
+
if (typeof raw.agentId === "string" && raw.agentId.trim()) {
|
|
7265
|
+
state.agentId = raw.agentId.trim();
|
|
7266
|
+
}
|
|
7267
|
+
if (typeof raw.taskId === "string" && raw.taskId.trim()) {
|
|
7268
|
+
state.taskId = raw.taskId.trim();
|
|
7269
|
+
}
|
|
7270
|
+
if (typeof raw.messageId === "string" && raw.messageId.trim()) {
|
|
7271
|
+
state.messageId = raw.messageId.trim();
|
|
7272
|
+
}
|
|
7273
|
+
if (typeof raw.action === "string" && raw.action.trim()) {
|
|
7274
|
+
state.action = raw.action.trim();
|
|
7275
|
+
}
|
|
7276
|
+
if (raw.status === "TYPING" || raw.status === "SUCCESS" || raw.status === "FAILED" || raw.status === "CANCELLED") {
|
|
7277
|
+
state.status = raw.status;
|
|
7278
|
+
}
|
|
7279
|
+
if (typeof raw.updatedAt === "string" && raw.updatedAt.trim()) {
|
|
7280
|
+
state.updatedAt = raw.updatedAt.trim();
|
|
7281
|
+
}
|
|
7282
|
+
return state;
|
|
7283
|
+
}
|
|
7284
|
+
} catch {
|
|
7285
|
+
}
|
|
7286
|
+
return {};
|
|
7287
|
+
}
|
|
7288
|
+
function loadWebIdeAgentId(workdir, taskId) {
|
|
7289
|
+
return readRegistry(registryPath(workdir, taskId)).agentId;
|
|
7290
|
+
}
|
|
7291
|
+
|
|
7292
|
+
// src/commands/clean-webide-cache.ts
|
|
7293
|
+
function cursorAgentStoreDir(workdir) {
|
|
7294
|
+
return resolve7(workdir, ".apm", "cursor-agent-store");
|
|
7295
|
+
}
|
|
7296
|
+
async function purgeCursorAgentStoreForAgent(workdir, agentId) {
|
|
7297
|
+
const trimmedAgentId = agentId.trim();
|
|
7298
|
+
const trimmedWorkdir = workdir.trim();
|
|
7299
|
+
if (!trimmedAgentId || !trimmedWorkdir) return false;
|
|
7300
|
+
const rootDir = cursorAgentStoreDir(trimmedWorkdir);
|
|
7301
|
+
if (!existsSync24(rootDir)) return false;
|
|
7302
|
+
const store = new JsonlLocalAgentStore(rootDir);
|
|
7303
|
+
const runIds = [];
|
|
7304
|
+
let cursor;
|
|
7305
|
+
do {
|
|
7306
|
+
const page = await store.runs.list({
|
|
7307
|
+
filter: {
|
|
7308
|
+
agentIds: [trimmedAgentId],
|
|
7309
|
+
...cursor ? { cursor } : {},
|
|
7310
|
+
limit: 200
|
|
7311
|
+
}
|
|
7312
|
+
});
|
|
7313
|
+
for (const run of page.items) {
|
|
7314
|
+
runIds.push(run.runId);
|
|
7315
|
+
}
|
|
7316
|
+
cursor = page.nextCursor;
|
|
7317
|
+
} while (cursor);
|
|
7318
|
+
if (runIds.length > 0) {
|
|
7319
|
+
await store.runEvents.delete({ filter: { runIds } });
|
|
7320
|
+
}
|
|
7321
|
+
await store.runs.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
7322
|
+
await store.checkpoints.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
7323
|
+
await store.agents.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
7324
|
+
return true;
|
|
7325
|
+
}
|
|
7326
|
+
async function cleanWebIdeWorkspaceCache(taskId, workdir) {
|
|
7251
7327
|
const trimmedTaskId = taskId.trim();
|
|
7252
7328
|
const trimmedWorkdir = workdir.trim();
|
|
7253
7329
|
if (!trimmedTaskId || !trimmedWorkdir) {
|
|
7254
7330
|
return;
|
|
7255
7331
|
}
|
|
7256
|
-
const
|
|
7257
|
-
if (
|
|
7332
|
+
const agentId = loadWebIdeAgentId(trimmedWorkdir, trimmedTaskId);
|
|
7333
|
+
if (agentId) {
|
|
7334
|
+
try {
|
|
7335
|
+
const purged = await purgeCursorAgentStoreForAgent(
|
|
7336
|
+
trimmedWorkdir,
|
|
7337
|
+
agentId
|
|
7338
|
+
);
|
|
7339
|
+
if (purged) {
|
|
7340
|
+
console.log(
|
|
7341
|
+
`[apm] \u5DF2\u6E05\u7406 Cursor agent store agentId=${agentId} taskId=${trimmedTaskId}`
|
|
7342
|
+
);
|
|
7343
|
+
}
|
|
7344
|
+
} catch (err) {
|
|
7345
|
+
console.warn(
|
|
7346
|
+
`[apm] \u6E05\u7406 Cursor agent store \u5931\u8D25 agentId=${agentId}:`,
|
|
7347
|
+
err instanceof Error ? err.message : err
|
|
7348
|
+
);
|
|
7349
|
+
}
|
|
7350
|
+
} else {
|
|
7351
|
+
console.log(
|
|
7352
|
+
`[apm] \u65E0 WebIDE agentId\uFF0C\u8DF3\u8FC7 cursor-agent-store taskId=${trimmedTaskId}`
|
|
7353
|
+
);
|
|
7354
|
+
}
|
|
7355
|
+
const dir = resolve7(trimmedWorkdir, ".apm", "webide", trimmedTaskId);
|
|
7356
|
+
if (existsSync24(dir)) {
|
|
7258
7357
|
rmSync5(dir, { recursive: true, force: true });
|
|
7259
7358
|
console.log(`[apm] \u5DF2\u6E05\u7406 WebIDE \u7F13\u5B58 ${dir}`);
|
|
7260
7359
|
} else {
|
|
@@ -7636,17 +7735,17 @@ ${JSON.stringify(event, null, 2)}
|
|
|
7636
7735
|
}
|
|
7637
7736
|
|
|
7638
7737
|
// src/commands/connect/agent-session-registry.ts
|
|
7639
|
-
import { existsSync as
|
|
7640
|
-
import { dirname as
|
|
7641
|
-
function
|
|
7642
|
-
return
|
|
7738
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "node:fs";
|
|
7739
|
+
import { dirname as dirname8, resolve as resolve8 } from "node:path";
|
|
7740
|
+
function registryPath2(workdir, sessionId) {
|
|
7741
|
+
return resolve8(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
|
|
7643
7742
|
}
|
|
7644
|
-
function
|
|
7645
|
-
if (!
|
|
7743
|
+
function readRegistry2(path19) {
|
|
7744
|
+
if (!existsSync25(path19)) {
|
|
7646
7745
|
return {};
|
|
7647
7746
|
}
|
|
7648
7747
|
try {
|
|
7649
|
-
const parsed = JSON.parse(
|
|
7748
|
+
const parsed = JSON.parse(readFileSync18(path19, "utf8"));
|
|
7650
7749
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7651
7750
|
const result = {};
|
|
7652
7751
|
for (const [key, value] of Object.entries(
|
|
@@ -7663,23 +7762,23 @@ function readRegistry(path19) {
|
|
|
7663
7762
|
return {};
|
|
7664
7763
|
}
|
|
7665
7764
|
function writeRegistry(path19, registry) {
|
|
7666
|
-
|
|
7667
|
-
|
|
7765
|
+
mkdirSync11(dirname8(path19), { recursive: true });
|
|
7766
|
+
writeFileSync16(path19, `${JSON.stringify(registry, null, 2)}
|
|
7668
7767
|
`, "utf8");
|
|
7669
7768
|
}
|
|
7670
7769
|
function loadSessionAgentId(workdir, sessionId, user) {
|
|
7671
|
-
const registry =
|
|
7770
|
+
const registry = readRegistry2(registryPath2(workdir, sessionId));
|
|
7672
7771
|
return registry[user];
|
|
7673
7772
|
}
|
|
7674
7773
|
function saveSessionAgentId(workdir, sessionId, user, agentId) {
|
|
7675
|
-
const path19 =
|
|
7676
|
-
const registry =
|
|
7774
|
+
const path19 = registryPath2(workdir, sessionId);
|
|
7775
|
+
const registry = readRegistry2(path19);
|
|
7677
7776
|
registry[user] = agentId;
|
|
7678
7777
|
writeRegistry(path19, registry);
|
|
7679
7778
|
}
|
|
7680
7779
|
function clearSessionAgentId(workdir, sessionId, user) {
|
|
7681
|
-
const path19 =
|
|
7682
|
-
const registry =
|
|
7780
|
+
const path19 = registryPath2(workdir, sessionId);
|
|
7781
|
+
const registry = readRegistry2(path19);
|
|
7683
7782
|
if (!(user in registry)) {
|
|
7684
7783
|
return;
|
|
7685
7784
|
}
|
|
@@ -8267,13 +8366,13 @@ ${WORKSPACE_BOUNDARY_HINT}`;
|
|
|
8267
8366
|
}
|
|
8268
8367
|
|
|
8269
8368
|
// src/commands/connect/local-agent-store.ts
|
|
8270
|
-
import { mkdirSync as
|
|
8369
|
+
import { mkdirSync as mkdirSync12 } from "node:fs";
|
|
8271
8370
|
import { join as join19 } from "node:path";
|
|
8272
|
-
import { JsonlLocalAgentStore } from "@cursor/sdk";
|
|
8371
|
+
import { JsonlLocalAgentStore as JsonlLocalAgentStore2 } from "@cursor/sdk";
|
|
8273
8372
|
function createWorkspaceLocalAgentStore(workdir) {
|
|
8274
8373
|
const rootDir = join19(workdir, ".apm", "cursor-agent-store");
|
|
8275
|
-
|
|
8276
|
-
return new
|
|
8374
|
+
mkdirSync12(rootDir, { recursive: true });
|
|
8375
|
+
return new JsonlLocalAgentStore2(rootDir);
|
|
8277
8376
|
}
|
|
8278
8377
|
|
|
8279
8378
|
// src/commands/connect/cursor-agent.ts
|
|
@@ -8303,6 +8402,19 @@ function formatCursorRunFailure(runId, options) {
|
|
|
8303
8402
|
}
|
|
8304
8403
|
return `Cursor run \u5931\u8D25: ${runId} \u2014 ${details.join("\uFF1B")}`;
|
|
8305
8404
|
}
|
|
8405
|
+
function persistSessionAgentId(ctx, agentId) {
|
|
8406
|
+
if (ctx.skipSessionAgentRegistry || !ctx.user) return;
|
|
8407
|
+
saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agentId);
|
|
8408
|
+
}
|
|
8409
|
+
function invalidatePersistedAgentId(ctx) {
|
|
8410
|
+
if (ctx.skipSessionAgentRegistry) {
|
|
8411
|
+
ctx.onInvalidatePersistedAgentId?.();
|
|
8412
|
+
return;
|
|
8413
|
+
}
|
|
8414
|
+
if (ctx.user) {
|
|
8415
|
+
clearSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user);
|
|
8416
|
+
}
|
|
8417
|
+
}
|
|
8306
8418
|
async function obtainAgent(ctx) {
|
|
8307
8419
|
const agentOptions = {
|
|
8308
8420
|
apiKey: ctx.apiKey,
|
|
@@ -8321,32 +8433,28 @@ async function obtainAgent(ctx) {
|
|
|
8321
8433
|
...ctx.mcpServers ? { mcpServers: ctx.mcpServers } : {}
|
|
8322
8434
|
};
|
|
8323
8435
|
const explicitAgentId = ctx.resumeAgentId?.trim();
|
|
8324
|
-
const savedAgentId = explicitAgentId || (ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0);
|
|
8436
|
+
const savedAgentId = explicitAgentId || (!ctx.skipSessionAgentRegistry && ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0);
|
|
8325
8437
|
if (savedAgentId) {
|
|
8326
8438
|
try {
|
|
8327
8439
|
const agent = await Agent.resume(savedAgentId, agentOptions);
|
|
8328
8440
|
console.log(
|
|
8329
8441
|
`[apm] \u590D\u7528 Agent user=${ctx.user} agentId=${savedAgentId}${explicitAgentId ? "\uFF08\u53C2\u6570\u6307\u5B9A\uFF09" : ""}`
|
|
8330
8442
|
);
|
|
8331
|
-
|
|
8332
|
-
saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
|
|
8333
|
-
}
|
|
8443
|
+
persistSessionAgentId(ctx, agent.agentId);
|
|
8334
8444
|
return { agent, resumed: true };
|
|
8335
8445
|
} catch (err) {
|
|
8336
8446
|
console.warn(
|
|
8337
8447
|
`[apm] \u590D\u7528 Agent \u5931\u8D25\uFF08agentId=${savedAgentId}\uFF09\uFF0C\u56DE\u9000\u4E3A\u65B0\u5EFA:`,
|
|
8338
8448
|
err instanceof Error ? err.message : err
|
|
8339
8449
|
);
|
|
8340
|
-
if (!explicitAgentId
|
|
8341
|
-
|
|
8450
|
+
if (!explicitAgentId) {
|
|
8451
|
+
invalidatePersistedAgentId(ctx);
|
|
8342
8452
|
}
|
|
8343
8453
|
}
|
|
8344
8454
|
}
|
|
8345
8455
|
try {
|
|
8346
8456
|
const agent = await Agent.create(agentOptions);
|
|
8347
|
-
|
|
8348
|
-
saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
|
|
8349
|
-
}
|
|
8457
|
+
persistSessionAgentId(ctx, agent.agentId);
|
|
8350
8458
|
return { agent, resumed: false };
|
|
8351
8459
|
} catch (err) {
|
|
8352
8460
|
if (ctx.enableSandbox && err instanceof Error && /sandbox/i.test(err.message)) {
|
|
@@ -8392,8 +8500,19 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
8392
8500
|
mode: ctx.mode,
|
|
8393
8501
|
resumeAgentId: ctx.resumeAgentId,
|
|
8394
8502
|
customTools,
|
|
8395
|
-
enableSandbox
|
|
8503
|
+
enableSandbox,
|
|
8504
|
+
skipSessionAgentRegistry: options?.skipSessionAgentRegistry,
|
|
8505
|
+
onInvalidatePersistedAgentId: options?.onInvalidatePersistedAgentId
|
|
8396
8506
|
});
|
|
8507
|
+
const invalidateAgentMapping = () => {
|
|
8508
|
+
invalidatePersistedAgentId({
|
|
8509
|
+
workdir,
|
|
8510
|
+
sessionId: ctx.sessionId,
|
|
8511
|
+
user: ctx.user,
|
|
8512
|
+
skipSessionAgentRegistry: options?.skipSessionAgentRegistry,
|
|
8513
|
+
onInvalidatePersistedAgentId: options?.onInvalidatePersistedAgentId
|
|
8514
|
+
});
|
|
8515
|
+
};
|
|
8397
8516
|
const eventSession = options?.eventSession ?? new EventSession(prompt);
|
|
8398
8517
|
const syncRemoteLog = options?.createRemoteLogSync ? options.createRemoteLogSync(agent.agentId) : options?.skipRemoteLogSync ? noopRemoteLogSync : createThrottledCursorMessageLogSync(
|
|
8399
8518
|
cfg,
|
|
@@ -8461,7 +8580,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
8461
8580
|
});
|
|
8462
8581
|
console.error(`[apm] ${failureMessage}`);
|
|
8463
8582
|
if (resumed) {
|
|
8464
|
-
|
|
8583
|
+
invalidateAgentMapping();
|
|
8465
8584
|
}
|
|
8466
8585
|
throw new Error(failureMessage);
|
|
8467
8586
|
}
|
|
@@ -8500,7 +8619,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
8500
8619
|
} catch (err) {
|
|
8501
8620
|
if (err instanceof CursorAgentError) {
|
|
8502
8621
|
if (resumed) {
|
|
8503
|
-
|
|
8622
|
+
invalidateAgentMapping();
|
|
8504
8623
|
}
|
|
8505
8624
|
throw new Error(
|
|
8506
8625
|
`Cursor \u542F\u52A8\u5931\u8D25: ${err.message}${err.isRetryable ? "\uFF08\u53EF\u91CD\u8BD5\uFF09" : ""}`
|
|
@@ -8553,7 +8672,7 @@ async function ensureMessageHasReply(cfg, sessionId, messageId, fallback) {
|
|
|
8553
8672
|
}
|
|
8554
8673
|
|
|
8555
8674
|
// src/commands/connect/cli-version-sync.ts
|
|
8556
|
-
import { existsSync as
|
|
8675
|
+
import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync17 } from "fs";
|
|
8557
8676
|
import { join as join20 } from "path";
|
|
8558
8677
|
var CLI_VERSION_FILE = ".cli-version.json";
|
|
8559
8678
|
function manifestPath2(apmDir) {
|
|
@@ -8561,12 +8680,12 @@ function manifestPath2(apmDir) {
|
|
|
8561
8680
|
}
|
|
8562
8681
|
function loadManifest4(apmDir) {
|
|
8563
8682
|
const path19 = toFsPath(manifestPath2(apmDir));
|
|
8564
|
-
if (!
|
|
8683
|
+
if (!existsSync26(path19)) {
|
|
8565
8684
|
return null;
|
|
8566
8685
|
}
|
|
8567
8686
|
try {
|
|
8568
8687
|
const parsed = JSON.parse(
|
|
8569
|
-
|
|
8688
|
+
readFileSync19(path19, "utf8")
|
|
8570
8689
|
);
|
|
8571
8690
|
if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
|
|
8572
8691
|
return parsed;
|
|
@@ -8577,7 +8696,7 @@ function loadManifest4(apmDir) {
|
|
|
8577
8696
|
}
|
|
8578
8697
|
function saveManifest4(apmDir, cliVersion) {
|
|
8579
8698
|
const manifest = { version: 1, cliVersion };
|
|
8580
|
-
|
|
8699
|
+
writeFileSync17(
|
|
8581
8700
|
toFsPath(manifestPath2(apmDir)),
|
|
8582
8701
|
`${JSON.stringify(manifest, null, 2)}
|
|
8583
8702
|
`,
|
|
@@ -8631,7 +8750,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
8631
8750
|
);
|
|
8632
8751
|
}
|
|
8633
8752
|
const queuedAt = Date.now();
|
|
8634
|
-
return new Promise((
|
|
8753
|
+
return new Promise((resolve9) => {
|
|
8635
8754
|
waiters.push(() => {
|
|
8636
8755
|
active += 1;
|
|
8637
8756
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -8642,7 +8761,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
8642
8761
|
)}s\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`
|
|
8643
8762
|
);
|
|
8644
8763
|
}
|
|
8645
|
-
|
|
8764
|
+
resolve9();
|
|
8646
8765
|
});
|
|
8647
8766
|
});
|
|
8648
8767
|
};
|
|
@@ -8662,21 +8781,46 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
8662
8781
|
// src/commands/connect/webide-worker-pool.ts
|
|
8663
8782
|
init_webide_terminal_registry();
|
|
8664
8783
|
import { Worker } from "node:worker_threads";
|
|
8784
|
+
import { totalmem } from "node:os";
|
|
8665
8785
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
8666
|
-
import { dirname as
|
|
8786
|
+
import { dirname as dirname9, join as join21 } from "node:path";
|
|
8667
8787
|
var workerFile = join21(
|
|
8668
|
-
|
|
8788
|
+
dirname9(fileURLToPath3(import.meta.url)),
|
|
8669
8789
|
"webide-message-worker.js"
|
|
8670
8790
|
);
|
|
8791
|
+
var SYSTEM_RESERVE_MB = 3072;
|
|
8792
|
+
var MIN_WEBIDE_WORKER_HEAP_MB = 1536;
|
|
8793
|
+
var MAX_WEBIDE_WORKER_HEAP_MB = 8192;
|
|
8794
|
+
function defaultWebIdeWorkerHeapMb(totalMemoryBytes = totalmem()) {
|
|
8795
|
+
const totalMb = Math.floor(totalMemoryBytes / (1024 * 1024));
|
|
8796
|
+
return Math.min(
|
|
8797
|
+
MAX_WEBIDE_WORKER_HEAP_MB,
|
|
8798
|
+
Math.max(MIN_WEBIDE_WORKER_HEAP_MB, totalMb - SYSTEM_RESERVE_MB)
|
|
8799
|
+
);
|
|
8800
|
+
}
|
|
8801
|
+
function resolveWebIdeWorkerHeapMb(env = process.env, totalMemoryBytes = totalmem()) {
|
|
8802
|
+
const fallback = defaultWebIdeWorkerHeapMb(totalMemoryBytes);
|
|
8803
|
+
const raw = env.APM_WEBIDE_WORKER_HEAP_MB?.trim();
|
|
8804
|
+
if (!raw) return fallback;
|
|
8805
|
+
const n = Number.parseInt(raw, 10);
|
|
8806
|
+
if (!Number.isFinite(n)) return fallback;
|
|
8807
|
+
return Math.min(16384, Math.max(MIN_WEBIDE_WORKER_HEAP_MB, n));
|
|
8808
|
+
}
|
|
8671
8809
|
function spawnWebIdeMessageWorker(cfg, msg) {
|
|
8810
|
+
const maxOldGenerationSizeMb = resolveWebIdeWorkerHeapMb();
|
|
8672
8811
|
const worker = new Worker(workerFile, {
|
|
8673
|
-
workerData: { cfg, msg }
|
|
8812
|
+
workerData: { cfg, msg },
|
|
8813
|
+
// worker_threads 不支持 execArgv 里的 --max-old-space-size,必须用 resourceLimits
|
|
8814
|
+
resourceLimits: { maxOldGenerationSizeMb }
|
|
8674
8815
|
});
|
|
8816
|
+
console.log(
|
|
8817
|
+
`[apm] webide worker spawn messageId=${msg.messageId} heapMb=${maxOldGenerationSizeMb}`
|
|
8818
|
+
);
|
|
8675
8819
|
const registry = getWebIdeTerminalRegistry(cfg);
|
|
8676
8820
|
let settled = false;
|
|
8677
8821
|
let resolveDone;
|
|
8678
|
-
const done = new Promise((
|
|
8679
|
-
resolveDone =
|
|
8822
|
+
const done = new Promise((resolve9) => {
|
|
8823
|
+
resolveDone = resolve9;
|
|
8680
8824
|
});
|
|
8681
8825
|
const failIfStillQueued = async (reason) => {
|
|
8682
8826
|
if (settled) return;
|
|
@@ -8764,10 +8908,12 @@ function spawnWebIdeMessageWorker(cfg, msg) {
|
|
|
8764
8908
|
}
|
|
8765
8909
|
});
|
|
8766
8910
|
worker.on("error", (err) => {
|
|
8911
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
8767
8912
|
console.error("[apm] webide worker crashed:", err);
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8913
|
+
const oomHint = /memory limit|heap out of memory/i.test(detail) ? `\uFF08\u5F53\u524D\u5806\u4E0A\u9650 ${maxOldGenerationSizeMb}MB\uFF1B8G \u53CA\u4EE5\u4E0B\u673A\u5668\u8C03\u9AD8 APM_WEBIDE_WORKER_HEAP_MB \u6613\u89E6\u53D1\u6574\u673A OOM\uFF0C\u5EFA\u8BAE\u52A0\u5185\u5B58/swap \u6216\u7F29\u77ED\u5355\u6B21\u4EFB\u52A1\uFF09` : "";
|
|
8914
|
+
void failIfStillQueued(`WebIDE worker \u5D29\u6E83: ${detail}${oomHint}`).finally(
|
|
8915
|
+
() => resolveDone()
|
|
8916
|
+
);
|
|
8771
8917
|
});
|
|
8772
8918
|
worker.on("exit", (code) => {
|
|
8773
8919
|
if (!settled && code !== 0) {
|
|
@@ -8948,11 +9094,11 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
|
|
|
8948
9094
|
}
|
|
8949
9095
|
function interruptibleSleep(ms, signal) {
|
|
8950
9096
|
if (signal.aborted) return Promise.resolve();
|
|
8951
|
-
return new Promise((
|
|
8952
|
-
const timer = setTimeout(
|
|
9097
|
+
return new Promise((resolve9) => {
|
|
9098
|
+
const timer = setTimeout(resolve9, ms);
|
|
8953
9099
|
const onAbort = () => {
|
|
8954
9100
|
clearTimeout(timer);
|
|
8955
|
-
|
|
9101
|
+
resolve9();
|
|
8956
9102
|
};
|
|
8957
9103
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
8958
9104
|
});
|
|
@@ -9053,7 +9199,7 @@ function attachWsHandlers(ws, ctx, onOpen) {
|
|
|
9053
9199
|
msg2.taskId,
|
|
9054
9200
|
"cache-cleanup"
|
|
9055
9201
|
);
|
|
9056
|
-
cleanWebIdeWorkspaceCache(msg2.taskId, workdir);
|
|
9202
|
+
await cleanWebIdeWorkspaceCache(msg2.taskId, workdir);
|
|
9057
9203
|
})();
|
|
9058
9204
|
activeTasks.add(task2);
|
|
9059
9205
|
void task2.finally(() => {
|
|
@@ -9182,7 +9328,7 @@ function attachWsHandlers(ws, ctx, onOpen) {
|
|
|
9182
9328
|
});
|
|
9183
9329
|
}
|
|
9184
9330
|
function connectOnce(url, ctx, connectionAbort, onConnected) {
|
|
9185
|
-
return new Promise((
|
|
9331
|
+
return new Promise((resolve9, reject) => {
|
|
9186
9332
|
const ws = new WebSocket(url);
|
|
9187
9333
|
let stopHeartbeat;
|
|
9188
9334
|
let settled = false;
|
|
@@ -9211,7 +9357,7 @@ function connectOnce(url, ctx, connectionAbort, onConnected) {
|
|
|
9211
9357
|
finish(() => reject(new Error("shutdown")));
|
|
9212
9358
|
return;
|
|
9213
9359
|
}
|
|
9214
|
-
finish(
|
|
9360
|
+
finish(resolve9);
|
|
9215
9361
|
});
|
|
9216
9362
|
ws.on("error", (err) => {
|
|
9217
9363
|
console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
|
|
@@ -9706,7 +9852,7 @@ import path15 from "node:path";
|
|
|
9706
9852
|
import Docker from "dockerode";
|
|
9707
9853
|
|
|
9708
9854
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
9709
|
-
import { existsSync as
|
|
9855
|
+
import { existsSync as existsSync27, readFileSync as readFileSync20 } from "node:fs";
|
|
9710
9856
|
import path12 from "node:path";
|
|
9711
9857
|
function asOptionalTlsBuffer(value) {
|
|
9712
9858
|
if (typeof value !== "string") {
|
|
@@ -9718,8 +9864,8 @@ function asOptionalTlsBuffer(value) {
|
|
|
9718
9864
|
if (normalized === "") {
|
|
9719
9865
|
return void 0;
|
|
9720
9866
|
}
|
|
9721
|
-
if (
|
|
9722
|
-
return
|
|
9867
|
+
if (existsSync27(normalized)) {
|
|
9868
|
+
return readFileSync20(normalized);
|
|
9723
9869
|
}
|
|
9724
9870
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
9725
9871
|
if (looksLikePath) {
|
|
@@ -9844,17 +9990,17 @@ var DockerodeClient = class {
|
|
|
9844
9990
|
await this.client.getImage(image).remove({ force: true });
|
|
9845
9991
|
}
|
|
9846
9992
|
async pullImage(image, auth) {
|
|
9847
|
-
const stream = await new Promise((
|
|
9993
|
+
const stream = await new Promise((resolve9, reject) => {
|
|
9848
9994
|
const pullOptions = auth ? { authconfig: auth } : void 0;
|
|
9849
9995
|
this.client.pull(image, pullOptions, (err, output) => {
|
|
9850
9996
|
if (err || !output) {
|
|
9851
9997
|
reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
|
|
9852
9998
|
return;
|
|
9853
9999
|
}
|
|
9854
|
-
|
|
10000
|
+
resolve9(output);
|
|
9855
10001
|
});
|
|
9856
10002
|
});
|
|
9857
|
-
await new Promise((
|
|
10003
|
+
await new Promise((resolve9, reject) => {
|
|
9858
10004
|
this.client.modem.followProgress(
|
|
9859
10005
|
stream,
|
|
9860
10006
|
(err) => {
|
|
@@ -9862,7 +10008,7 @@ var DockerodeClient = class {
|
|
|
9862
10008
|
reject(err);
|
|
9863
10009
|
return;
|
|
9864
10010
|
}
|
|
9865
|
-
|
|
10011
|
+
resolve9();
|
|
9866
10012
|
},
|
|
9867
10013
|
() => void 0
|
|
9868
10014
|
);
|
|
@@ -9929,7 +10075,7 @@ var DockerodeClient = class {
|
|
|
9929
10075
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
9930
10076
|
|
|
9931
10077
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
9932
|
-
import { existsSync as
|
|
10078
|
+
import { existsSync as existsSync28, readFileSync as readFileSync21, statSync as statSync11 } from "node:fs";
|
|
9933
10079
|
import path13 from "node:path";
|
|
9934
10080
|
function stripSurroundingQuotes(value) {
|
|
9935
10081
|
const t = value.trim();
|
|
@@ -9946,10 +10092,10 @@ function loadEnvFromFile(envFilePath) {
|
|
|
9946
10092
|
return {};
|
|
9947
10093
|
}
|
|
9948
10094
|
const targetPath = path13.resolve(envFilePath);
|
|
9949
|
-
if (!
|
|
10095
|
+
if (!existsSync28(targetPath) || !statSync11(targetPath).isFile()) {
|
|
9950
10096
|
return {};
|
|
9951
10097
|
}
|
|
9952
|
-
const raw =
|
|
10098
|
+
const raw = readFileSync21(targetPath, "utf-8");
|
|
9953
10099
|
const result = {};
|
|
9954
10100
|
for (const line of raw.split(/\r?\n/)) {
|
|
9955
10101
|
const normalized = line.trim();
|
|
@@ -10120,12 +10266,12 @@ function dockerPushImage(params, cwd) {
|
|
|
10120
10266
|
}
|
|
10121
10267
|
|
|
10122
10268
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
10123
|
-
import { existsSync as
|
|
10269
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
10124
10270
|
import path14 from "node:path";
|
|
10125
10271
|
function resolveDockerBuildPaths(cwd) {
|
|
10126
10272
|
const dockerfilePath = path14.join(cwd, "Dockerfile");
|
|
10127
10273
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
10128
|
-
if (!
|
|
10274
|
+
if (!existsSync29(dockerfilePath)) {
|
|
10129
10275
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
10130
10276
|
}
|
|
10131
10277
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -120,10 +120,6 @@ var requestConfig = {
|
|
|
120
120
|
method: "PUT",
|
|
121
121
|
path: "/cli/webide/terminals/meta"
|
|
122
122
|
}),
|
|
123
|
-
acquireSteelBrowser: defineEndpoint({
|
|
124
|
-
method: "POST",
|
|
125
|
-
path: "/cli/steel-browser/acquire"
|
|
126
|
-
}),
|
|
127
123
|
branchBaseline: defineEndpoint({
|
|
128
124
|
method: "GET",
|
|
129
125
|
path: "/cli/tasks/branch-baseline"
|
|
@@ -2304,6 +2300,19 @@ function formatCursorRunFailure(runId, options) {
|
|
|
2304
2300
|
}
|
|
2305
2301
|
return `Cursor run \u5931\u8D25: ${runId} \u2014 ${details.join("\uFF1B")}`;
|
|
2306
2302
|
}
|
|
2303
|
+
function persistSessionAgentId(ctx, agentId) {
|
|
2304
|
+
if (ctx.skipSessionAgentRegistry || !ctx.user) return;
|
|
2305
|
+
saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agentId);
|
|
2306
|
+
}
|
|
2307
|
+
function invalidatePersistedAgentId(ctx) {
|
|
2308
|
+
if (ctx.skipSessionAgentRegistry) {
|
|
2309
|
+
ctx.onInvalidatePersistedAgentId?.();
|
|
2310
|
+
return;
|
|
2311
|
+
}
|
|
2312
|
+
if (ctx.user) {
|
|
2313
|
+
clearSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2307
2316
|
async function obtainAgent(ctx) {
|
|
2308
2317
|
const agentOptions = {
|
|
2309
2318
|
apiKey: ctx.apiKey,
|
|
@@ -2322,32 +2331,28 @@ async function obtainAgent(ctx) {
|
|
|
2322
2331
|
...ctx.mcpServers ? { mcpServers: ctx.mcpServers } : {}
|
|
2323
2332
|
};
|
|
2324
2333
|
const explicitAgentId = ctx.resumeAgentId?.trim();
|
|
2325
|
-
const savedAgentId = explicitAgentId || (ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0);
|
|
2334
|
+
const savedAgentId = explicitAgentId || (!ctx.skipSessionAgentRegistry && ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0);
|
|
2326
2335
|
if (savedAgentId) {
|
|
2327
2336
|
try {
|
|
2328
2337
|
const agent = await Agent.resume(savedAgentId, agentOptions);
|
|
2329
2338
|
console.log(
|
|
2330
2339
|
`[apm] \u590D\u7528 Agent user=${ctx.user} agentId=${savedAgentId}${explicitAgentId ? "\uFF08\u53C2\u6570\u6307\u5B9A\uFF09" : ""}`
|
|
2331
2340
|
);
|
|
2332
|
-
|
|
2333
|
-
saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
|
|
2334
|
-
}
|
|
2341
|
+
persistSessionAgentId(ctx, agent.agentId);
|
|
2335
2342
|
return { agent, resumed: true };
|
|
2336
2343
|
} catch (err) {
|
|
2337
2344
|
console.warn(
|
|
2338
2345
|
`[apm] \u590D\u7528 Agent \u5931\u8D25\uFF08agentId=${savedAgentId}\uFF09\uFF0C\u56DE\u9000\u4E3A\u65B0\u5EFA:`,
|
|
2339
2346
|
err instanceof Error ? err.message : err
|
|
2340
2347
|
);
|
|
2341
|
-
if (!explicitAgentId
|
|
2342
|
-
|
|
2348
|
+
if (!explicitAgentId) {
|
|
2349
|
+
invalidatePersistedAgentId(ctx);
|
|
2343
2350
|
}
|
|
2344
2351
|
}
|
|
2345
2352
|
}
|
|
2346
2353
|
try {
|
|
2347
2354
|
const agent = await Agent.create(agentOptions);
|
|
2348
|
-
|
|
2349
|
-
saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
|
|
2350
|
-
}
|
|
2355
|
+
persistSessionAgentId(ctx, agent.agentId);
|
|
2351
2356
|
return { agent, resumed: false };
|
|
2352
2357
|
} catch (err) {
|
|
2353
2358
|
if (ctx.enableSandbox && err instanceof Error && /sandbox/i.test(err.message)) {
|
|
@@ -2393,8 +2398,19 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
2393
2398
|
mode: ctx.mode,
|
|
2394
2399
|
resumeAgentId: ctx.resumeAgentId,
|
|
2395
2400
|
customTools,
|
|
2396
|
-
enableSandbox
|
|
2401
|
+
enableSandbox,
|
|
2402
|
+
skipSessionAgentRegistry: options?.skipSessionAgentRegistry,
|
|
2403
|
+
onInvalidatePersistedAgentId: options?.onInvalidatePersistedAgentId
|
|
2397
2404
|
});
|
|
2405
|
+
const invalidateAgentMapping = () => {
|
|
2406
|
+
invalidatePersistedAgentId({
|
|
2407
|
+
workdir,
|
|
2408
|
+
sessionId: ctx.sessionId,
|
|
2409
|
+
user: ctx.user,
|
|
2410
|
+
skipSessionAgentRegistry: options?.skipSessionAgentRegistry,
|
|
2411
|
+
onInvalidatePersistedAgentId: options?.onInvalidatePersistedAgentId
|
|
2412
|
+
});
|
|
2413
|
+
};
|
|
2398
2414
|
const eventSession = options?.eventSession ?? new EventSession(prompt);
|
|
2399
2415
|
const syncRemoteLog = options?.createRemoteLogSync ? options.createRemoteLogSync(agent.agentId) : options?.skipRemoteLogSync ? noopRemoteLogSync : createThrottledCursorMessageLogSync(
|
|
2400
2416
|
cfg,
|
|
@@ -2462,7 +2478,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
2462
2478
|
});
|
|
2463
2479
|
console.error(`[apm] ${failureMessage}`);
|
|
2464
2480
|
if (resumed) {
|
|
2465
|
-
|
|
2481
|
+
invalidateAgentMapping();
|
|
2466
2482
|
}
|
|
2467
2483
|
throw new Error(failureMessage);
|
|
2468
2484
|
}
|
|
@@ -2501,7 +2517,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
2501
2517
|
} catch (err) {
|
|
2502
2518
|
if (err instanceof CursorAgentError) {
|
|
2503
2519
|
if (resumed) {
|
|
2504
|
-
|
|
2520
|
+
invalidateAgentMapping();
|
|
2505
2521
|
}
|
|
2506
2522
|
throw new Error(
|
|
2507
2523
|
`Cursor \u542F\u52A8\u5931\u8D25: ${err.message}${err.isRetryable ? "\uFF08\u53EF\u91CD\u8BD5\uFF09" : ""}`
|
|
@@ -2529,10 +2545,27 @@ function readRegistry2(path) {
|
|
|
2529
2545
|
try {
|
|
2530
2546
|
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
2531
2547
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2532
|
-
const
|
|
2533
|
-
|
|
2534
|
-
|
|
2548
|
+
const raw = parsed;
|
|
2549
|
+
const state = {};
|
|
2550
|
+
if (typeof raw.agentId === "string" && raw.agentId.trim()) {
|
|
2551
|
+
state.agentId = raw.agentId.trim();
|
|
2552
|
+
}
|
|
2553
|
+
if (typeof raw.taskId === "string" && raw.taskId.trim()) {
|
|
2554
|
+
state.taskId = raw.taskId.trim();
|
|
2555
|
+
}
|
|
2556
|
+
if (typeof raw.messageId === "string" && raw.messageId.trim()) {
|
|
2557
|
+
state.messageId = raw.messageId.trim();
|
|
2558
|
+
}
|
|
2559
|
+
if (typeof raw.action === "string" && raw.action.trim()) {
|
|
2560
|
+
state.action = raw.action.trim();
|
|
2561
|
+
}
|
|
2562
|
+
if (raw.status === "TYPING" || raw.status === "SUCCESS" || raw.status === "FAILED" || raw.status === "CANCELLED") {
|
|
2563
|
+
state.status = raw.status;
|
|
2564
|
+
}
|
|
2565
|
+
if (typeof raw.updatedAt === "string" && raw.updatedAt.trim()) {
|
|
2566
|
+
state.updatedAt = raw.updatedAt.trim();
|
|
2535
2567
|
}
|
|
2568
|
+
return state;
|
|
2536
2569
|
}
|
|
2537
2570
|
} catch {
|
|
2538
2571
|
}
|
|
@@ -2543,16 +2576,121 @@ function writeRegistry2(path, registry) {
|
|
|
2543
2576
|
writeFileSync5(path, `${JSON.stringify(registry, null, 2)}
|
|
2544
2577
|
`, "utf8");
|
|
2545
2578
|
}
|
|
2579
|
+
function syncWebIdeTaskState(workdir, taskId, patch) {
|
|
2580
|
+
const trimmedTaskId = taskId.trim();
|
|
2581
|
+
if (!trimmedTaskId) return;
|
|
2582
|
+
const path = registryPath2(workdir, trimmedTaskId);
|
|
2583
|
+
const current = readRegistry2(path);
|
|
2584
|
+
const next = {
|
|
2585
|
+
...current,
|
|
2586
|
+
taskId: trimmedTaskId,
|
|
2587
|
+
updatedAt: patch.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
2588
|
+
};
|
|
2589
|
+
if (patch.agentId !== void 0) {
|
|
2590
|
+
const agentId = patch.agentId.trim();
|
|
2591
|
+
if (agentId) next.agentId = agentId;
|
|
2592
|
+
else delete next.agentId;
|
|
2593
|
+
}
|
|
2594
|
+
if (patch.messageId !== void 0) {
|
|
2595
|
+
const messageId = patch.messageId.trim();
|
|
2596
|
+
if (messageId) next.messageId = messageId;
|
|
2597
|
+
else delete next.messageId;
|
|
2598
|
+
}
|
|
2599
|
+
if (patch.action !== void 0) {
|
|
2600
|
+
const action = patch.action.trim();
|
|
2601
|
+
if (action) next.action = action;
|
|
2602
|
+
else delete next.action;
|
|
2603
|
+
}
|
|
2604
|
+
if (patch.status !== void 0) {
|
|
2605
|
+
next.status = patch.status;
|
|
2606
|
+
}
|
|
2607
|
+
writeRegistry2(path, next);
|
|
2608
|
+
}
|
|
2546
2609
|
function loadWebIdeAgentId(workdir, taskId) {
|
|
2547
2610
|
return readRegistry2(registryPath2(workdir, taskId)).agentId;
|
|
2548
2611
|
}
|
|
2549
2612
|
function saveWebIdeAgentId(workdir, taskId, agentId) {
|
|
2550
|
-
|
|
2613
|
+
syncWebIdeTaskState(workdir, taskId, { agentId });
|
|
2551
2614
|
}
|
|
2552
2615
|
function clearWebIdeAgentId(workdir, taskId) {
|
|
2553
2616
|
const path = registryPath2(workdir, taskId);
|
|
2554
2617
|
if (!existsSync4(path)) return;
|
|
2555
|
-
|
|
2618
|
+
syncWebIdeTaskState(workdir, taskId, { agentId: "" });
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
// src/commands/clean-webide-cache.ts
|
|
2622
|
+
import { existsSync as existsSync5, rmSync } from "node:fs";
|
|
2623
|
+
import { resolve as resolve6 } from "node:path";
|
|
2624
|
+
import { JsonlLocalAgentStore as JsonlLocalAgentStore2 } from "@cursor/sdk";
|
|
2625
|
+
function cursorAgentStoreDir(workdir) {
|
|
2626
|
+
return resolve6(workdir, ".apm", "cursor-agent-store");
|
|
2627
|
+
}
|
|
2628
|
+
async function purgeCursorAgentStoreForAgent(workdir, agentId) {
|
|
2629
|
+
const trimmedAgentId = agentId.trim();
|
|
2630
|
+
const trimmedWorkdir = workdir.trim();
|
|
2631
|
+
if (!trimmedAgentId || !trimmedWorkdir) return false;
|
|
2632
|
+
const rootDir = cursorAgentStoreDir(trimmedWorkdir);
|
|
2633
|
+
if (!existsSync5(rootDir)) return false;
|
|
2634
|
+
const store = new JsonlLocalAgentStore2(rootDir);
|
|
2635
|
+
const runIds = [];
|
|
2636
|
+
let cursor;
|
|
2637
|
+
do {
|
|
2638
|
+
const page = await store.runs.list({
|
|
2639
|
+
filter: {
|
|
2640
|
+
agentIds: [trimmedAgentId],
|
|
2641
|
+
...cursor ? { cursor } : {},
|
|
2642
|
+
limit: 200
|
|
2643
|
+
}
|
|
2644
|
+
});
|
|
2645
|
+
for (const run of page.items) {
|
|
2646
|
+
runIds.push(run.runId);
|
|
2647
|
+
}
|
|
2648
|
+
cursor = page.nextCursor;
|
|
2649
|
+
} while (cursor);
|
|
2650
|
+
if (runIds.length > 0) {
|
|
2651
|
+
await store.runEvents.delete({ filter: { runIds } });
|
|
2652
|
+
}
|
|
2653
|
+
await store.runs.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
2654
|
+
await store.checkpoints.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
2655
|
+
await store.agents.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
2656
|
+
return true;
|
|
2657
|
+
}
|
|
2658
|
+
async function cleanWebIdeWorkspaceCache(taskId, workdir) {
|
|
2659
|
+
const trimmedTaskId = taskId.trim();
|
|
2660
|
+
const trimmedWorkdir = workdir.trim();
|
|
2661
|
+
if (!trimmedTaskId || !trimmedWorkdir) {
|
|
2662
|
+
return;
|
|
2663
|
+
}
|
|
2664
|
+
const agentId = loadWebIdeAgentId(trimmedWorkdir, trimmedTaskId);
|
|
2665
|
+
if (agentId) {
|
|
2666
|
+
try {
|
|
2667
|
+
const purged = await purgeCursorAgentStoreForAgent(
|
|
2668
|
+
trimmedWorkdir,
|
|
2669
|
+
agentId
|
|
2670
|
+
);
|
|
2671
|
+
if (purged) {
|
|
2672
|
+
console.log(
|
|
2673
|
+
`[apm] \u5DF2\u6E05\u7406 Cursor agent store agentId=${agentId} taskId=${trimmedTaskId}`
|
|
2674
|
+
);
|
|
2675
|
+
}
|
|
2676
|
+
} catch (err) {
|
|
2677
|
+
console.warn(
|
|
2678
|
+
`[apm] \u6E05\u7406 Cursor agent store \u5931\u8D25 agentId=${agentId}:`,
|
|
2679
|
+
err instanceof Error ? err.message : err
|
|
2680
|
+
);
|
|
2681
|
+
}
|
|
2682
|
+
} else {
|
|
2683
|
+
console.log(
|
|
2684
|
+
`[apm] \u65E0 WebIDE agentId\uFF0C\u8DF3\u8FC7 cursor-agent-store taskId=${trimmedTaskId}`
|
|
2685
|
+
);
|
|
2686
|
+
}
|
|
2687
|
+
const dir = resolve6(trimmedWorkdir, ".apm", "webide", trimmedTaskId);
|
|
2688
|
+
if (existsSync5(dir)) {
|
|
2689
|
+
rmSync(dir, { recursive: true, force: true });
|
|
2690
|
+
console.log(`[apm] \u5DF2\u6E05\u7406 WebIDE \u7F13\u5B58 ${dir}`);
|
|
2691
|
+
} else {
|
|
2692
|
+
console.log(`[apm] WebIDE \u7F13\u5B58\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7 ${dir}`);
|
|
2693
|
+
}
|
|
2556
2694
|
}
|
|
2557
2695
|
|
|
2558
2696
|
// src/commands/connect/webide-ask-question.ts
|
|
@@ -2669,14 +2807,14 @@ var MinioClient = class {
|
|
|
2669
2807
|
async deleteObjectsByPrefix(bucket, prefix) {
|
|
2670
2808
|
const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
|
|
2671
2809
|
const keys = [];
|
|
2672
|
-
await new Promise((
|
|
2810
|
+
await new Promise((resolve7, reject) => {
|
|
2673
2811
|
objectsStream.on("data", (obj) => {
|
|
2674
2812
|
if (obj.name) {
|
|
2675
2813
|
keys.push(obj.name);
|
|
2676
2814
|
}
|
|
2677
2815
|
});
|
|
2678
2816
|
objectsStream.on("error", reject);
|
|
2679
|
-
objectsStream.on("end",
|
|
2817
|
+
objectsStream.on("end", resolve7);
|
|
2680
2818
|
});
|
|
2681
2819
|
const chunkSize = 500;
|
|
2682
2820
|
for (let i = 0; i < keys.length; i += chunkSize) {
|
|
@@ -2950,10 +3088,10 @@ ${diagnostic ?? ""}
|
|
|
2950
3088
|
|
|
2951
3089
|
// src/project-documents-sync.ts
|
|
2952
3090
|
import {
|
|
2953
|
-
existsSync as
|
|
3091
|
+
existsSync as existsSync6,
|
|
2954
3092
|
readdirSync as readdirSync3,
|
|
2955
3093
|
readFileSync as readFileSync6,
|
|
2956
|
-
rmSync,
|
|
3094
|
+
rmSync as rmSync2,
|
|
2957
3095
|
writeFileSync as writeFileSync7
|
|
2958
3096
|
} from "fs";
|
|
2959
3097
|
import { createHash } from "crypto";
|
|
@@ -2999,7 +3137,7 @@ function readLocalManifest(apmRoot, projectId) {
|
|
|
2999
3137
|
projectDocumentsDir(apmRoot, projectId),
|
|
3000
3138
|
MANIFEST_FILE
|
|
3001
3139
|
);
|
|
3002
|
-
if (!
|
|
3140
|
+
if (!existsSync6(manifestPath3)) {
|
|
3003
3141
|
return null;
|
|
3004
3142
|
}
|
|
3005
3143
|
try {
|
|
@@ -3012,7 +3150,7 @@ function readLocalManifest(apmRoot, projectId) {
|
|
|
3012
3150
|
}
|
|
3013
3151
|
function listLocalDocumentPaths(apmRoot, projectId) {
|
|
3014
3152
|
const root = projectDocumentsDir(apmRoot, projectId);
|
|
3015
|
-
if (!
|
|
3153
|
+
if (!existsSync6(root)) {
|
|
3016
3154
|
return [];
|
|
3017
3155
|
}
|
|
3018
3156
|
const paths = [];
|
|
@@ -3146,8 +3284,8 @@ ${diagnostic ?? ""}`);
|
|
|
3146
3284
|
const absPath = toFsPath(
|
|
3147
3285
|
projectDocumentLocalPath(targetApmDir, projectId, path)
|
|
3148
3286
|
);
|
|
3149
|
-
if (
|
|
3150
|
-
|
|
3287
|
+
if (existsSync6(absPath)) {
|
|
3288
|
+
rmSync2(absPath, { force: true });
|
|
3151
3289
|
deleted += 1;
|
|
3152
3290
|
}
|
|
3153
3291
|
}
|
|
@@ -3513,17 +3651,17 @@ function readCliVersion() {
|
|
|
3513
3651
|
}
|
|
3514
3652
|
|
|
3515
3653
|
// src/commands/update-skills.ts
|
|
3516
|
-
import { existsSync as
|
|
3654
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
|
|
3517
3655
|
import { join as join10 } from "path";
|
|
3518
3656
|
|
|
3519
3657
|
// src/skills-sync.ts
|
|
3520
3658
|
import {
|
|
3521
3659
|
copyFileSync as copyFileSync2,
|
|
3522
3660
|
cpSync,
|
|
3523
|
-
existsSync as
|
|
3661
|
+
existsSync as existsSync7,
|
|
3524
3662
|
mkdirSync as mkdirSync7,
|
|
3525
3663
|
readdirSync as readdirSync4,
|
|
3526
|
-
rmSync as
|
|
3664
|
+
rmSync as rmSync3,
|
|
3527
3665
|
statSync as statSync3,
|
|
3528
3666
|
writeFileSync as writeFileSync9
|
|
3529
3667
|
} from "fs";
|
|
@@ -3537,20 +3675,20 @@ function sanitizeSkillDirName(name) {
|
|
|
3537
3675
|
return trimmed.replace(/[/\\:*?"<>|]/g, "_");
|
|
3538
3676
|
}
|
|
3539
3677
|
function listBaseSkillDirNames() {
|
|
3540
|
-
if (!
|
|
3678
|
+
if (!existsSync7(BASE_SKILLS_TEMPLATE_DIR)) return [];
|
|
3541
3679
|
return readdirSync4(BASE_SKILLS_TEMPLATE_DIR).filter((name) => {
|
|
3542
3680
|
const path = join9(BASE_SKILLS_TEMPLATE_DIR, name);
|
|
3543
3681
|
return statSync3(path).isDirectory();
|
|
3544
3682
|
});
|
|
3545
3683
|
}
|
|
3546
3684
|
function syncAgentsGuide(apmDir) {
|
|
3547
|
-
if (!
|
|
3685
|
+
if (!existsSync7(AGENTS_TEMPLATE_PATH)) return false;
|
|
3548
3686
|
mkdirSync7(apmDir, { recursive: true });
|
|
3549
3687
|
copyFileSync2(AGENTS_TEMPLATE_PATH, join9(apmDir, "AGENTS.md"));
|
|
3550
3688
|
return true;
|
|
3551
3689
|
}
|
|
3552
3690
|
function listBaseRuleFileNames() {
|
|
3553
|
-
if (!
|
|
3691
|
+
if (!existsSync7(BASE_RULES_TEMPLATE_DIR)) return [];
|
|
3554
3692
|
return readdirSync4(BASE_RULES_TEMPLATE_DIR).filter((name) => {
|
|
3555
3693
|
const path = join9(BASE_RULES_TEMPLATE_DIR, name);
|
|
3556
3694
|
return statSync3(path).isFile();
|
|
@@ -3594,13 +3732,13 @@ function syncSupplementarySkills(skillsDir, list) {
|
|
|
3594
3732
|
written.push(dirName);
|
|
3595
3733
|
}
|
|
3596
3734
|
const removed = [];
|
|
3597
|
-
if (!
|
|
3735
|
+
if (!existsSync7(skillsDir)) return { written, skipped, removed };
|
|
3598
3736
|
for (const entry of readdirSync4(skillsDir)) {
|
|
3599
3737
|
const full = join9(skillsDir, entry);
|
|
3600
3738
|
if (!statSync3(full).isDirectory()) continue;
|
|
3601
3739
|
if (baseNames.has(entry)) continue;
|
|
3602
3740
|
if (apiDirNames.has(entry)) continue;
|
|
3603
|
-
|
|
3741
|
+
rmSync3(full, { recursive: true, force: true });
|
|
3604
3742
|
removed.push(entry);
|
|
3605
3743
|
}
|
|
3606
3744
|
return { written, skipped, removed };
|
|
@@ -3610,7 +3748,7 @@ function syncSupplementarySkills(skillsDir, list) {
|
|
|
3610
3748
|
async function syncWorkspaceSkills(cfg, workdir) {
|
|
3611
3749
|
const apmDir = workspaceApmDir(workdir);
|
|
3612
3750
|
const fsApmDir = toFsPath(apmDir);
|
|
3613
|
-
if (!
|
|
3751
|
+
if (!existsSync8(fsApmDir)) {
|
|
3614
3752
|
throw new Error("[apm] \u672A\u627E\u5230 .apm \u76EE\u5F55\uFF0C\u8BF7\u5148\u6267\u884C apm init");
|
|
3615
3753
|
}
|
|
3616
3754
|
const apmStat = statSync4(fsApmDir);
|
|
@@ -3654,7 +3792,7 @@ async function syncWorkspaceSkills(cfg, workdir) {
|
|
|
3654
3792
|
}
|
|
3655
3793
|
|
|
3656
3794
|
// src/commands/sync-session-attachments.ts
|
|
3657
|
-
import { existsSync as
|
|
3795
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
3658
3796
|
import { join as join11 } from "path";
|
|
3659
3797
|
var MANIFEST_FILE2 = ".sync-manifest.json";
|
|
3660
3798
|
async function downloadAttachment(cfg, attachmentId) {
|
|
@@ -3672,7 +3810,7 @@ async function downloadAttachment(cfg, attachmentId) {
|
|
|
3672
3810
|
}
|
|
3673
3811
|
function loadManifest(dir) {
|
|
3674
3812
|
const path = join11(dir, MANIFEST_FILE2);
|
|
3675
|
-
if (!
|
|
3813
|
+
if (!existsSync9(path)) {
|
|
3676
3814
|
return { version: 1, attachments: {} };
|
|
3677
3815
|
}
|
|
3678
3816
|
try {
|
|
@@ -3695,7 +3833,7 @@ function saveManifest(dir, manifest) {
|
|
|
3695
3833
|
);
|
|
3696
3834
|
}
|
|
3697
3835
|
function isAttachmentUpToDate(entry, item, dest) {
|
|
3698
|
-
if (!entry || !
|
|
3836
|
+
if (!entry || !existsSync9(dest)) return false;
|
|
3699
3837
|
if (entry.name !== item.name) return false;
|
|
3700
3838
|
const createdAt = item.createdAt ?? "";
|
|
3701
3839
|
return entry.createdAt === createdAt;
|
|
@@ -3741,7 +3879,7 @@ async function syncWebIdeAttachments(cfg, taskId, workdir, attachments) {
|
|
|
3741
3879
|
}
|
|
3742
3880
|
|
|
3743
3881
|
// src/commands/connect/cli-version-sync.ts
|
|
3744
|
-
import { existsSync as
|
|
3882
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
3745
3883
|
import { join as join12 } from "path";
|
|
3746
3884
|
var CLI_VERSION_FILE = ".cli-version.json";
|
|
3747
3885
|
function manifestPath2(apmDir) {
|
|
@@ -3749,7 +3887,7 @@ function manifestPath2(apmDir) {
|
|
|
3749
3887
|
}
|
|
3750
3888
|
function loadManifest2(apmDir) {
|
|
3751
3889
|
const path = toFsPath(manifestPath2(apmDir));
|
|
3752
|
-
if (!
|
|
3890
|
+
if (!existsSync10(path)) {
|
|
3753
3891
|
return null;
|
|
3754
3892
|
}
|
|
3755
3893
|
try {
|
|
@@ -3802,6 +3940,13 @@ var WEBIDE_CODE_CHANGE_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
3802
3940
|
function shouldCommitAfterWebIdeMessage(action) {
|
|
3803
3941
|
return WEBIDE_CODE_CHANGE_ACTIONS.has(action);
|
|
3804
3942
|
}
|
|
3943
|
+
function syncLocalTaskStatus(workdir, taskId, msg, status) {
|
|
3944
|
+
syncWebIdeTaskState(workdir, taskId, {
|
|
3945
|
+
messageId: msg.messageId,
|
|
3946
|
+
action: msg.action,
|
|
3947
|
+
status
|
|
3948
|
+
});
|
|
3949
|
+
}
|
|
3805
3950
|
async function updateStatus(cfg, messageId, status) {
|
|
3806
3951
|
const api = createApmApiClient(cfg);
|
|
3807
3952
|
await api.cli.webideUpdateMessageStatus({ id: messageId, status });
|
|
@@ -3823,6 +3968,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
3823
3968
|
`[apm] webide-message action=${msg.action} taskId=${taskId} messageId=${messageId}`
|
|
3824
3969
|
);
|
|
3825
3970
|
await updateStatus(cfg, messageId, "TYPING");
|
|
3971
|
+
syncLocalTaskStatus(workdir, taskId, msg, "TYPING");
|
|
3826
3972
|
const eventSession = new EventSession(msg.content);
|
|
3827
3973
|
const prepAgentId = loadWebIdeAgentId(workdir, taskId) ?? "webide-cli-prep";
|
|
3828
3974
|
const logSyncRef = {
|
|
@@ -4030,6 +4176,8 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
4030
4176
|
}),
|
|
4031
4177
|
enableWebIdePlanTools: true,
|
|
4032
4178
|
enableSandbox: false,
|
|
4179
|
+
skipSessionAgentRegistry: true,
|
|
4180
|
+
onInvalidatePersistedAgentId: () => clearWebIdeAgentId(workdir, taskId),
|
|
4033
4181
|
taskId,
|
|
4034
4182
|
terminalRpc: options?.terminalRpc,
|
|
4035
4183
|
createRemoteLogSync: (agentId) => {
|
|
@@ -4080,6 +4228,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
4080
4228
|
tokenUsage
|
|
4081
4229
|
);
|
|
4082
4230
|
await setError(cfg, messageId, detail);
|
|
4231
|
+
syncLocalTaskStatus(workdir, taskId, msg, "FAILED");
|
|
4083
4232
|
return;
|
|
4084
4233
|
}
|
|
4085
4234
|
if (outcome.status === "cancelled" || signal.aborted) {
|
|
@@ -4090,6 +4239,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
4090
4239
|
tokenUsage
|
|
4091
4240
|
);
|
|
4092
4241
|
await updateStatus(cfg, messageId, "CANCELLED");
|
|
4242
|
+
syncLocalTaskStatus(workdir, taskId, msg, "CANCELLED");
|
|
4093
4243
|
return;
|
|
4094
4244
|
}
|
|
4095
4245
|
const fallback = resolveMessageReplyFallback({
|
|
@@ -4189,9 +4339,20 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
4189
4339
|
tokenUsage
|
|
4190
4340
|
);
|
|
4191
4341
|
await updateStatus(cfg, messageId, "SUCCESS");
|
|
4342
|
+
syncLocalTaskStatus(workdir, taskId, msg, "SUCCESS");
|
|
4192
4343
|
console.log(
|
|
4193
4344
|
`[apm] webide-message \u5B8C\u6210 action=${msg.action} messageId=${messageId} agentId=${outcome.agentId}`
|
|
4194
4345
|
);
|
|
4346
|
+
if (msg.action === "accept") {
|
|
4347
|
+
try {
|
|
4348
|
+
await cleanWebIdeWorkspaceCache(taskId, workdir);
|
|
4349
|
+
} catch (err) {
|
|
4350
|
+
console.warn(
|
|
4351
|
+
"[apm] \u5408\u5E76 PR \u540E\u6E05\u7406 WebIDE agent \u7F13\u5B58\u5931\u8D25:",
|
|
4352
|
+
err instanceof Error ? err.message : err
|
|
4353
|
+
);
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4195
4356
|
} catch (err) {
|
|
4196
4357
|
const detail = err instanceof Error ? err.message : String(err);
|
|
4197
4358
|
console.error(`[apm] webide-message \u5931\u8D25: ${detail}`);
|
|
@@ -4206,6 +4367,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal, options) {
|
|
|
4206
4367
|
statusErr instanceof Error ? statusErr.message : statusErr
|
|
4207
4368
|
);
|
|
4208
4369
|
}
|
|
4370
|
+
syncLocalTaskStatus(workdir, taskId, msg, "FAILED");
|
|
4209
4371
|
}
|
|
4210
4372
|
}
|
|
4211
4373
|
|
|
@@ -4225,12 +4387,12 @@ function installTerminalRpcListener() {
|
|
|
4225
4387
|
}
|
|
4226
4388
|
function call(op, args) {
|
|
4227
4389
|
const id = nextId++;
|
|
4228
|
-
return new Promise((
|
|
4390
|
+
return new Promise((resolve7, reject) => {
|
|
4229
4391
|
if (!parentPort) {
|
|
4230
4392
|
reject(new Error("parentPort \u4E0D\u53EF\u7528"));
|
|
4231
4393
|
return;
|
|
4232
4394
|
}
|
|
4233
|
-
pending.set(id, { resolve:
|
|
4395
|
+
pending.set(id, { resolve: resolve7, reject });
|
|
4234
4396
|
parentPort.postMessage({
|
|
4235
4397
|
type: "terminal-rpc",
|
|
4236
4398
|
id,
|