ai-project-manage-cli 8.1.13 → 8.1.15
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 +5 -16
- package/dist/worker-script.js +225 -402
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -133,6 +133,11 @@ var requestConfig = {
|
|
|
133
133
|
method: "PUT",
|
|
134
134
|
path: "/cli/webide/transition-prep-events"
|
|
135
135
|
}),
|
|
136
|
+
/** 「继续」开跑后挂新 runId */
|
|
137
|
+
webideAttachContinueRun: defineEndpoint({
|
|
138
|
+
method: "PUT",
|
|
139
|
+
path: "/cli/webide/continue-run"
|
|
140
|
+
}),
|
|
136
141
|
webideUpsertMessageLog: defineEndpoint({
|
|
137
142
|
method: "PUT",
|
|
138
143
|
path: "/cli/webide/message-logs"
|
|
@@ -274,22 +279,6 @@ var requestConfig = {
|
|
|
274
279
|
cursorStoreDeleteRunEvents: defineEndpoint({
|
|
275
280
|
method: "POST",
|
|
276
281
|
path: "/cli/cursor-store/run-events/delete"
|
|
277
|
-
}),
|
|
278
|
-
cursorStorePutCheckpoint: defineEndpoint({
|
|
279
|
-
method: "PUT",
|
|
280
|
-
path: "/cli/cursor-store/checkpoints"
|
|
281
|
-
}),
|
|
282
|
-
cursorStoreGetCheckpoint: defineEndpoint({
|
|
283
|
-
method: "GET",
|
|
284
|
-
path: "/cli/cursor-store/checkpoints/get"
|
|
285
|
-
}),
|
|
286
|
-
cursorStoreListCheckpoints: defineEndpoint({
|
|
287
|
-
method: "POST",
|
|
288
|
-
path: "/cli/cursor-store/checkpoints/list"
|
|
289
|
-
}),
|
|
290
|
-
cursorStoreDeleteCheckpoints: defineEndpoint({
|
|
291
|
-
method: "POST",
|
|
292
|
-
path: "/cli/cursor-store/checkpoints/delete"
|
|
293
282
|
})
|
|
294
283
|
}
|
|
295
284
|
};
|
package/dist/worker-script.js
CHANGED
|
@@ -44,6 +44,11 @@ var requestConfig = {
|
|
|
44
44
|
method: "PUT",
|
|
45
45
|
path: "/cli/webide/transition-prep-events"
|
|
46
46
|
}),
|
|
47
|
+
/** 「继续」开跑后挂新 runId */
|
|
48
|
+
webideAttachContinueRun: defineEndpoint({
|
|
49
|
+
method: "PUT",
|
|
50
|
+
path: "/cli/webide/continue-run"
|
|
51
|
+
}),
|
|
47
52
|
webideUpsertMessageLog: defineEndpoint({
|
|
48
53
|
method: "PUT",
|
|
49
54
|
path: "/cli/webide/message-logs"
|
|
@@ -185,22 +190,6 @@ var requestConfig = {
|
|
|
185
190
|
cursorStoreDeleteRunEvents: defineEndpoint({
|
|
186
191
|
method: "POST",
|
|
187
192
|
path: "/cli/cursor-store/run-events/delete"
|
|
188
|
-
}),
|
|
189
|
-
cursorStorePutCheckpoint: defineEndpoint({
|
|
190
|
-
method: "PUT",
|
|
191
|
-
path: "/cli/cursor-store/checkpoints"
|
|
192
|
-
}),
|
|
193
|
-
cursorStoreGetCheckpoint: defineEndpoint({
|
|
194
|
-
method: "GET",
|
|
195
|
-
path: "/cli/cursor-store/checkpoints/get"
|
|
196
|
-
}),
|
|
197
|
-
cursorStoreListCheckpoints: defineEndpoint({
|
|
198
|
-
method: "POST",
|
|
199
|
-
path: "/cli/cursor-store/checkpoints/list"
|
|
200
|
-
}),
|
|
201
|
-
cursorStoreDeleteCheckpoints: defineEndpoint({
|
|
202
|
-
method: "POST",
|
|
203
|
-
path: "/cli/cursor-store/checkpoints/delete"
|
|
204
193
|
})
|
|
205
194
|
}
|
|
206
195
|
};
|
|
@@ -2467,77 +2456,11 @@ function createPtySessionMcpServers(cfg2) {
|
|
|
2467
2456
|
};
|
|
2468
2457
|
}
|
|
2469
2458
|
|
|
2459
|
+
// src/commands/connect/local-sqlite-agent-store.ts
|
|
2460
|
+
import { composeLocalAgentStore } from "@cursor/sdk";
|
|
2461
|
+
import { SqliteLocalAgentStore } from "@cursor/sdk/sqlite";
|
|
2462
|
+
|
|
2470
2463
|
// src/commands/connect/remote-local-agent-store.ts
|
|
2471
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
2472
|
-
import {
|
|
2473
|
-
existsSync as existsSync5,
|
|
2474
|
-
mkdirSync as mkdirSync4,
|
|
2475
|
-
readFileSync as readFileSync4,
|
|
2476
|
-
rmSync,
|
|
2477
|
-
unlinkSync,
|
|
2478
|
-
writeFileSync as writeFileSync3
|
|
2479
|
-
} from "node:fs";
|
|
2480
|
-
import { dirname as dirname2, join as join4 } from "node:path";
|
|
2481
|
-
var INLINE_CHECKPOINT_MAX_BYTES = 256 * 1024;
|
|
2482
|
-
var CHECKPOINT_CACHE_DIR = join4(APM_CONFIG_DIR, "cursor-checkpoint-cache");
|
|
2483
|
-
function checkpointObjectKey(agentId, blobId) {
|
|
2484
|
-
return `cursor-agents/${agentId}/checkpoints/${blobId}`;
|
|
2485
|
-
}
|
|
2486
|
-
function safeBlobFileName(blobId) {
|
|
2487
|
-
if (/^[a-zA-Z0-9._-]+$/.test(blobId)) return blobId;
|
|
2488
|
-
return createHash2("sha256").update(blobId).digest("hex");
|
|
2489
|
-
}
|
|
2490
|
-
function checkpointCachePath(agentId, blobId) {
|
|
2491
|
-
return join4(CHECKPOINT_CACHE_DIR, agentId, safeBlobFileName(blobId));
|
|
2492
|
-
}
|
|
2493
|
-
function checkpointCacheKey(agentId, blobId) {
|
|
2494
|
-
return `${agentId}\0${blobId}`;
|
|
2495
|
-
}
|
|
2496
|
-
function readLocalCheckpoint(agentId, blobId) {
|
|
2497
|
-
try {
|
|
2498
|
-
const path3 = checkpointCachePath(agentId, blobId);
|
|
2499
|
-
if (!existsSync5(path3)) return null;
|
|
2500
|
-
return new Uint8Array(readFileSync4(path3));
|
|
2501
|
-
} catch {
|
|
2502
|
-
return null;
|
|
2503
|
-
}
|
|
2504
|
-
}
|
|
2505
|
-
function writeLocalCheckpoint(agentId, blobId, data) {
|
|
2506
|
-
try {
|
|
2507
|
-
const path3 = checkpointCachePath(agentId, blobId);
|
|
2508
|
-
mkdirSync4(dirname2(path3), { recursive: true });
|
|
2509
|
-
writeFileSync3(path3, Buffer.from(data));
|
|
2510
|
-
} catch (err) {
|
|
2511
|
-
console.warn(
|
|
2512
|
-
`[apm] checkpoint \u672C\u5730\u7F13\u5B58\u5199\u5165\u5931\u8D25 agentId=${agentId} blobId=${blobId}:`,
|
|
2513
|
-
err instanceof Error ? err.message : err
|
|
2514
|
-
);
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
function deleteLocalCheckpoint(agentId, blobId) {
|
|
2518
|
-
try {
|
|
2519
|
-
const path3 = checkpointCachePath(agentId, blobId);
|
|
2520
|
-
if (existsSync5(path3)) unlinkSync(path3);
|
|
2521
|
-
} catch {
|
|
2522
|
-
}
|
|
2523
|
-
}
|
|
2524
|
-
function clearLocalCheckpointCache(agentId) {
|
|
2525
|
-
try {
|
|
2526
|
-
if (agentId?.trim()) {
|
|
2527
|
-
const dir = join4(CHECKPOINT_CACHE_DIR, agentId.trim());
|
|
2528
|
-
if (existsSync5(dir)) rmSync(dir, { recursive: true, force: true });
|
|
2529
|
-
return;
|
|
2530
|
-
}
|
|
2531
|
-
if (existsSync5(CHECKPOINT_CACHE_DIR)) {
|
|
2532
|
-
rmSync(CHECKPOINT_CACHE_DIR, { recursive: true, force: true });
|
|
2533
|
-
}
|
|
2534
|
-
} catch (err) {
|
|
2535
|
-
console.warn(
|
|
2536
|
-
`[apm] \u6E05\u7406 checkpoint \u672C\u5730\u7F13\u5B58\u5931\u8D25:`,
|
|
2537
|
-
err instanceof Error ? err.message : err
|
|
2538
|
-
);
|
|
2539
|
-
}
|
|
2540
|
-
}
|
|
2541
2464
|
function asCheckpointRef(value) {
|
|
2542
2465
|
if (value === void 0) return void 0;
|
|
2543
2466
|
if (value === null) return null;
|
|
@@ -2592,45 +2515,32 @@ function fromApiRun(row) {
|
|
|
2592
2515
|
latestCheckpointRef: asCheckpointRef(row.latestCheckpointRef) ?? null
|
|
2593
2516
|
};
|
|
2594
2517
|
}
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
}
|
|
2607
|
-
function bytesToBase64(data) {
|
|
2608
|
-
return Buffer.from(data).toString("base64");
|
|
2609
|
-
}
|
|
2610
|
-
function base64ToBytes(dataBase64) {
|
|
2611
|
-
return new Uint8Array(Buffer.from(dataBase64, "base64"));
|
|
2612
|
-
}
|
|
2613
|
-
function createRemoteLocalAgentStore(cfg2) {
|
|
2614
|
-
const api = createApmApiClient(cfg2);
|
|
2615
|
-
let minioCache = null;
|
|
2616
|
-
const memoryCheckpointCache = /* @__PURE__ */ new Map();
|
|
2617
|
-
function getMinio() {
|
|
2618
|
-
if (!minioCache) {
|
|
2619
|
-
minioCache = createApmLogMinioClient(cfg2).then(({ client, bucket }) => ({
|
|
2620
|
-
client,
|
|
2621
|
-
bucket
|
|
2622
|
-
}));
|
|
2623
|
-
}
|
|
2624
|
-
return minioCache;
|
|
2625
|
-
}
|
|
2626
|
-
function rememberCheckpoint(agentId, blobId, data) {
|
|
2627
|
-
memoryCheckpointCache.set(checkpointCacheKey(agentId, blobId), data);
|
|
2628
|
-
writeLocalCheckpoint(agentId, blobId, data);
|
|
2518
|
+
var unsupportedCheckpoints = {
|
|
2519
|
+
async get() {
|
|
2520
|
+
return null;
|
|
2521
|
+
},
|
|
2522
|
+
async create() {
|
|
2523
|
+
},
|
|
2524
|
+
async update() {
|
|
2525
|
+
},
|
|
2526
|
+
async delete() {
|
|
2527
|
+
},
|
|
2528
|
+
async list() {
|
|
2529
|
+
return { items: [] };
|
|
2629
2530
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2531
|
+
};
|
|
2532
|
+
var unsupportedRunEvents = {
|
|
2533
|
+
async append() {
|
|
2534
|
+
throw new Error("runEvents \u4EC5\u5B58\u672C\u673A SQLite");
|
|
2535
|
+
},
|
|
2536
|
+
async list() {
|
|
2537
|
+
return { items: [] };
|
|
2538
|
+
},
|
|
2539
|
+
async delete() {
|
|
2633
2540
|
}
|
|
2541
|
+
};
|
|
2542
|
+
function createRemoteLocalAgentStore(cfg2) {
|
|
2543
|
+
const api = createApmApiClient(cfg2);
|
|
2634
2544
|
async function upsertAgent(agent) {
|
|
2635
2545
|
const row = await api.cli.cursorStoreUpsertAgent({
|
|
2636
2546
|
agentId: agent.agentId,
|
|
@@ -2666,60 +2576,6 @@ function createRemoteLocalAgentStore(cfg2) {
|
|
|
2666
2576
|
});
|
|
2667
2577
|
return fromApiRun(row);
|
|
2668
2578
|
}
|
|
2669
|
-
async function putCheckpoint(input) {
|
|
2670
|
-
const createdAt = Date.now();
|
|
2671
|
-
if (input.data.byteLength > INLINE_CHECKPOINT_MAX_BYTES) {
|
|
2672
|
-
const { client, bucket } = await getMinio();
|
|
2673
|
-
const objectKey = checkpointObjectKey(input.agentId, input.blobId);
|
|
2674
|
-
await client.putObject(bucket, objectKey, Buffer.from(input.data), {
|
|
2675
|
-
"Content-Type": "application/octet-stream"
|
|
2676
|
-
});
|
|
2677
|
-
await api.cli.cursorStorePutCheckpoint({
|
|
2678
|
-
agentId: input.agentId,
|
|
2679
|
-
blobId: input.blobId,
|
|
2680
|
-
objectKey,
|
|
2681
|
-
byteSize: input.data.byteLength,
|
|
2682
|
-
createdAt
|
|
2683
|
-
});
|
|
2684
|
-
rememberCheckpoint(input.agentId, input.blobId, input.data);
|
|
2685
|
-
return;
|
|
2686
|
-
}
|
|
2687
|
-
await api.cli.cursorStorePutCheckpoint({
|
|
2688
|
-
agentId: input.agentId,
|
|
2689
|
-
blobId: input.blobId,
|
|
2690
|
-
dataBase64: bytesToBase64(input.data),
|
|
2691
|
-
byteSize: input.data.byteLength,
|
|
2692
|
-
createdAt
|
|
2693
|
-
});
|
|
2694
|
-
rememberCheckpoint(input.agentId, input.blobId, input.data);
|
|
2695
|
-
}
|
|
2696
|
-
async function readCheckpointBytes(input) {
|
|
2697
|
-
const memKey = checkpointCacheKey(input.agentId, input.blobId);
|
|
2698
|
-
const cached = memoryCheckpointCache.get(memKey);
|
|
2699
|
-
if (cached) return cached;
|
|
2700
|
-
const local = readLocalCheckpoint(input.agentId, input.blobId);
|
|
2701
|
-
if (local) {
|
|
2702
|
-
memoryCheckpointCache.set(memKey, local);
|
|
2703
|
-
return local;
|
|
2704
|
-
}
|
|
2705
|
-
const row = await api.cli.cursorStoreGetCheckpoint({
|
|
2706
|
-
agentId: input.agentId,
|
|
2707
|
-
blobId: input.blobId
|
|
2708
|
-
});
|
|
2709
|
-
if (!row) return null;
|
|
2710
|
-
let bytes = null;
|
|
2711
|
-
if (row.dataBase64) {
|
|
2712
|
-
bytes = base64ToBytes(row.dataBase64);
|
|
2713
|
-
} else {
|
|
2714
|
-
const objectKey = row.objectKey?.trim();
|
|
2715
|
-
if (!objectKey) return null;
|
|
2716
|
-
const { client, bucket } = await getMinio();
|
|
2717
|
-
const buf = await client.getObjectBuffer(bucket, objectKey);
|
|
2718
|
-
bytes = new Uint8Array(buf);
|
|
2719
|
-
}
|
|
2720
|
-
rememberCheckpoint(input.agentId, input.blobId, bytes);
|
|
2721
|
-
return bytes;
|
|
2722
|
-
}
|
|
2723
2579
|
return {
|
|
2724
2580
|
agents: {
|
|
2725
2581
|
async get(input) {
|
|
@@ -2774,10 +2630,11 @@ function createRemoteLocalAgentStore(cfg2) {
|
|
|
2774
2630
|
},
|
|
2775
2631
|
runs: {
|
|
2776
2632
|
async get(input) {
|
|
2777
|
-
const
|
|
2778
|
-
|
|
2779
|
-
|
|
2633
|
+
const page = await api.cli.cursorStoreListRuns({
|
|
2634
|
+
runIds: [input.runId],
|
|
2635
|
+
limit: 1
|
|
2780
2636
|
});
|
|
2637
|
+
const row = page.items[0];
|
|
2781
2638
|
return row ? fromApiRun(row) : null;
|
|
2782
2639
|
},
|
|
2783
2640
|
async create(input) {
|
|
@@ -2821,124 +2678,54 @@ function createRemoteLocalAgentStore(cfg2) {
|
|
|
2821
2678
|
return result;
|
|
2822
2679
|
}
|
|
2823
2680
|
},
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
const { items } = await api.cli.cursorStoreAppendRunEvents({
|
|
2827
|
-
events: [
|
|
2828
|
-
{
|
|
2829
|
-
runId: input.runId,
|
|
2830
|
-
eventType: input.eventType,
|
|
2831
|
-
payload: input.payload,
|
|
2832
|
-
payloadRef: input.payloadRef ?? null,
|
|
2833
|
-
idempotencyKey: input.idempotencyKey ?? null
|
|
2834
|
-
}
|
|
2835
|
-
]
|
|
2836
|
-
});
|
|
2837
|
-
const row = items[0];
|
|
2838
|
-
if (!row) {
|
|
2839
|
-
throw new Error("cursor-store append run event \u672A\u8FD4\u56DE\u7ED3\u679C");
|
|
2840
|
-
}
|
|
2841
|
-
return fromApiEvent(row);
|
|
2842
|
-
},
|
|
2843
|
-
async list(input) {
|
|
2844
|
-
const page = await api.cli.cursorStoreListRunEvents({
|
|
2845
|
-
runId: input.runId,
|
|
2846
|
-
afterOffset: input.afterOffset ?? null,
|
|
2847
|
-
limit: input.limit
|
|
2848
|
-
});
|
|
2849
|
-
return {
|
|
2850
|
-
items: page.items.map(fromApiEvent),
|
|
2851
|
-
...page.nextOffset ? { nextOffset: page.nextOffset } : {}
|
|
2852
|
-
};
|
|
2853
|
-
},
|
|
2854
|
-
async delete(input) {
|
|
2855
|
-
const runIds = input.filter.runIds?.map((id) => id.trim()).filter(Boolean);
|
|
2856
|
-
if (runIds && runIds.length > 0) {
|
|
2857
|
-
await api.cli.cursorStoreDeleteRunEvents({ runIds });
|
|
2858
|
-
return;
|
|
2859
|
-
}
|
|
2860
|
-
let cursor;
|
|
2861
|
-
for (; ; ) {
|
|
2862
|
-
const page = await api.cli.cursorStoreListRuns({
|
|
2863
|
-
cursor,
|
|
2864
|
-
limit: 200
|
|
2865
|
-
});
|
|
2866
|
-
if (page.items.length === 0) break;
|
|
2867
|
-
await api.cli.cursorStoreDeleteRunEvents({
|
|
2868
|
-
runIds: page.items.map((item) => item.runId)
|
|
2869
|
-
});
|
|
2870
|
-
if (!page.nextCursor) break;
|
|
2871
|
-
cursor = page.nextCursor;
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
},
|
|
2875
|
-
checkpoints: {
|
|
2876
|
-
async get(input) {
|
|
2877
|
-
return readCheckpointBytes(input);
|
|
2878
|
-
},
|
|
2879
|
-
async create(input) {
|
|
2880
|
-
await putCheckpoint(input);
|
|
2881
|
-
},
|
|
2882
|
-
async update(input) {
|
|
2883
|
-
await putCheckpoint(input);
|
|
2884
|
-
},
|
|
2885
|
-
async delete(input) {
|
|
2886
|
-
const agentIds = input.filter.agentIds?.map((id) => id.trim()).filter(Boolean);
|
|
2887
|
-
const blobIds = input.filter.blobIds?.map((id) => id.trim()).filter(Boolean);
|
|
2888
|
-
if (agentIds && agentIds.length > 0 || blobIds && blobIds.length > 0) {
|
|
2889
|
-
await api.cli.cursorStoreDeleteCheckpoints({ agentIds, blobIds });
|
|
2890
|
-
if (agentIds && agentIds.length > 0 && !blobIds?.length) {
|
|
2891
|
-
for (const id of agentIds) clearLocalCheckpointCache(id);
|
|
2892
|
-
} else if (agentIds && blobIds) {
|
|
2893
|
-
for (const id of agentIds) {
|
|
2894
|
-
for (const blobId of blobIds) forgetCheckpoint(id, blobId);
|
|
2895
|
-
}
|
|
2896
|
-
} else if (blobIds) {
|
|
2897
|
-
for (const blobId of blobIds) {
|
|
2898
|
-
for (const key of memoryCheckpointCache.keys()) {
|
|
2899
|
-
const sep2 = key.indexOf("\0");
|
|
2900
|
-
if (sep2 < 0) continue;
|
|
2901
|
-
if (key.slice(sep2 + 1) === blobId) {
|
|
2902
|
-
forgetCheckpoint(key.slice(0, sep2), blobId);
|
|
2903
|
-
}
|
|
2904
|
-
}
|
|
2905
|
-
}
|
|
2906
|
-
}
|
|
2907
|
-
return;
|
|
2908
|
-
}
|
|
2909
|
-
let cursor;
|
|
2910
|
-
for (; ; ) {
|
|
2911
|
-
const page = await api.cli.cursorStoreListCheckpoints({
|
|
2912
|
-
cursor,
|
|
2913
|
-
limit: 200
|
|
2914
|
-
});
|
|
2915
|
-
if (page.items.length === 0) break;
|
|
2916
|
-
await api.cli.cursorStoreDeleteCheckpoints({
|
|
2917
|
-
agentIds: [...new Set(page.items.map((item) => item.agentId))],
|
|
2918
|
-
blobIds: page.items.map((item) => item.blobId)
|
|
2919
|
-
});
|
|
2920
|
-
if (!page.nextCursor) break;
|
|
2921
|
-
cursor = page.nextCursor;
|
|
2922
|
-
}
|
|
2923
|
-
clearLocalCheckpointCache();
|
|
2924
|
-
memoryCheckpointCache.clear();
|
|
2925
|
-
},
|
|
2926
|
-
async list(input) {
|
|
2927
|
-
const page = await api.cli.cursorStoreListCheckpoints({
|
|
2928
|
-
agentIds: input?.filter?.agentIds ? [...input.filter.agentIds] : void 0,
|
|
2929
|
-
blobIds: input?.filter?.blobIds ? [...input.filter.blobIds] : void 0,
|
|
2930
|
-
cursor: input?.filter?.cursor,
|
|
2931
|
-
limit: input?.filter?.limit
|
|
2932
|
-
});
|
|
2933
|
-
return {
|
|
2934
|
-
items: page.items.map((item) => item.blobId),
|
|
2935
|
-
...page.nextCursor ? { nextCursor: page.nextCursor } : {}
|
|
2936
|
-
};
|
|
2937
|
-
}
|
|
2938
|
-
}
|
|
2681
|
+
checkpoints: unsupportedCheckpoints,
|
|
2682
|
+
runEvents: unsupportedRunEvents
|
|
2939
2683
|
};
|
|
2940
2684
|
}
|
|
2941
2685
|
|
|
2686
|
+
// src/commands/connect/local-sqlite-agent-store.ts
|
|
2687
|
+
var sqliteByKey = /* @__PURE__ */ new Map();
|
|
2688
|
+
async function openSqliteLocalAgentStore(workspaceRef) {
|
|
2689
|
+
const cwd = workspaceRef.trim();
|
|
2690
|
+
if (!cwd) throw new Error("openSqliteLocalAgentStore: workspaceRef \u4E0D\u80FD\u4E3A\u7A7A");
|
|
2691
|
+
const existing = sqliteByKey.get(cwd);
|
|
2692
|
+
if (existing) return existing;
|
|
2693
|
+
const pending2 = SqliteLocalAgentStore.open({ workspaceRef: cwd }).then(
|
|
2694
|
+
(store) => {
|
|
2695
|
+
console.log(
|
|
2696
|
+
`[apm] Cursor store sqlite ready cwd=${cwd} stateRoot=${store.stateRoot}`
|
|
2697
|
+
);
|
|
2698
|
+
return store;
|
|
2699
|
+
}
|
|
2700
|
+
);
|
|
2701
|
+
sqliteByKey.set(cwd, pending2);
|
|
2702
|
+
return pending2;
|
|
2703
|
+
}
|
|
2704
|
+
async function createApmCursorAgentStore(cfg2, workspaceRef) {
|
|
2705
|
+
const cwd = workspaceRef.trim();
|
|
2706
|
+
const [sqlite, remote] = await Promise.all([
|
|
2707
|
+
openSqliteLocalAgentStore(cwd),
|
|
2708
|
+
Promise.resolve(createRemoteLocalAgentStore(cfg2))
|
|
2709
|
+
]);
|
|
2710
|
+
return composeLocalAgentStore({
|
|
2711
|
+
agents: remote.agents,
|
|
2712
|
+
runs: remote.runs,
|
|
2713
|
+
checkpoints: sqlite.checkpoints,
|
|
2714
|
+
runEvents: sqlite.runEvents
|
|
2715
|
+
});
|
|
2716
|
+
}
|
|
2717
|
+
async function purgeLocalSqliteAgentData(input) {
|
|
2718
|
+
const agentId = input.agentId.trim();
|
|
2719
|
+
const workspaceRef = input.workspaceRef.trim();
|
|
2720
|
+
if (!agentId || !workspaceRef) return;
|
|
2721
|
+
const sqlite = await openSqliteLocalAgentStore(workspaceRef);
|
|
2722
|
+
const runIds = [...input.runIds ?? []];
|
|
2723
|
+
if (runIds.length > 0) {
|
|
2724
|
+
await sqlite.runEvents.delete({ filter: { runIds } });
|
|
2725
|
+
}
|
|
2726
|
+
await sqlite.checkpoints.delete({ filter: { agentIds: [agentId] } });
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2942
2729
|
// src/commands/connect/core/worker/run-steer.ts
|
|
2943
2730
|
var impl = null;
|
|
2944
2731
|
var pending = null;
|
|
@@ -2984,7 +2771,7 @@ function formatCursorRunFailure(runId, options) {
|
|
|
2984
2771
|
return `Cursor run \u5931\u8D25: ${runId} \u2014 ${details.join("\uFF1B")}`;
|
|
2985
2772
|
}
|
|
2986
2773
|
async function obtainAgent(ctx) {
|
|
2987
|
-
const store =
|
|
2774
|
+
const store = await createApmCursorAgentStore(ctx.cfg, ctx.cwd);
|
|
2988
2775
|
const agentOptions = {
|
|
2989
2776
|
apiKey: ctx.apiKey,
|
|
2990
2777
|
model: { id: ctx.model || "default" },
|
|
@@ -3336,14 +3123,14 @@ function createThrottledWebIdeMessageLogSync(cfg2, ctx, onError, options) {
|
|
|
3336
3123
|
|
|
3337
3124
|
// src/commands/sync-webide-agent.ts
|
|
3338
3125
|
import {
|
|
3339
|
-
existsSync as
|
|
3340
|
-
mkdirSync as
|
|
3126
|
+
existsSync as existsSync5,
|
|
3127
|
+
mkdirSync as mkdirSync4,
|
|
3341
3128
|
readdirSync as readdirSync3,
|
|
3342
|
-
readFileSync as
|
|
3343
|
-
unlinkSync
|
|
3344
|
-
writeFileSync as
|
|
3129
|
+
readFileSync as readFileSync4,
|
|
3130
|
+
unlinkSync,
|
|
3131
|
+
writeFileSync as writeFileSync3
|
|
3345
3132
|
} from "fs";
|
|
3346
|
-
import { join as
|
|
3133
|
+
import { join as join4 } from "path";
|
|
3347
3134
|
var REVISION_FILE = ".webide-agent.json";
|
|
3348
3135
|
var RULE_KEY = /^[a-z0-9_]+$/;
|
|
3349
3136
|
function withTrailingNewline(text) {
|
|
@@ -3351,10 +3138,10 @@ function withTrailingNewline(text) {
|
|
|
3351
3138
|
`;
|
|
3352
3139
|
}
|
|
3353
3140
|
function readRevision(apmDir) {
|
|
3354
|
-
const path3 = toFsPath(
|
|
3355
|
-
if (!
|
|
3141
|
+
const path3 = toFsPath(join4(apmDir, REVISION_FILE));
|
|
3142
|
+
if (!existsSync5(path3)) return null;
|
|
3356
3143
|
try {
|
|
3357
|
-
const parsed = JSON.parse(
|
|
3144
|
+
const parsed = JSON.parse(readFileSync4(path3, "utf8"));
|
|
3358
3145
|
if (parsed?.version === 1 && parsed.revision?.trim()) {
|
|
3359
3146
|
return parsed.revision.trim();
|
|
3360
3147
|
}
|
|
@@ -3364,8 +3151,8 @@ function readRevision(apmDir) {
|
|
|
3364
3151
|
return null;
|
|
3365
3152
|
}
|
|
3366
3153
|
function writeRevision(apmDir, revision) {
|
|
3367
|
-
|
|
3368
|
-
toFsPath(
|
|
3154
|
+
writeFileSync3(
|
|
3155
|
+
toFsPath(join4(apmDir, REVISION_FILE)),
|
|
3369
3156
|
`${JSON.stringify({ version: 1, revision }, null, 2)}
|
|
3370
3157
|
`,
|
|
3371
3158
|
"utf8"
|
|
@@ -3379,14 +3166,14 @@ async function syncWebIdeAgentFiles(workdir, cfg2) {
|
|
|
3379
3166
|
throw new Error("[apm] \u5E73\u53F0\u672A\u8FD4\u56DE WebIDE \u89C4\u5219\u7248\u672C");
|
|
3380
3167
|
}
|
|
3381
3168
|
const apmDir = workspaceApmDir(workdir);
|
|
3382
|
-
|
|
3169
|
+
mkdirSync4(toFsPath(apmDir), { recursive: true });
|
|
3383
3170
|
if (readRevision(apmDir) === revision) {
|
|
3384
3171
|
return { revision, wrote: false, ruleCount: bundle.rules?.length ?? 0 };
|
|
3385
3172
|
}
|
|
3386
|
-
const rulesDir =
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
toFsPath(
|
|
3173
|
+
const rulesDir = join4(apmDir, "rules");
|
|
3174
|
+
mkdirSync4(toFsPath(rulesDir), { recursive: true });
|
|
3175
|
+
writeFileSync3(
|
|
3176
|
+
toFsPath(join4(apmDir, "AGENTS.md")),
|
|
3390
3177
|
withTrailingNewline(bundle.guide ?? ""),
|
|
3391
3178
|
"utf8"
|
|
3392
3179
|
);
|
|
@@ -3397,8 +3184,8 @@ async function syncWebIdeAgentFiles(workdir, cfg2) {
|
|
|
3397
3184
|
throw new Error(`[apm] \u975E\u6CD5\u89C4\u5219\u540D: ${key || "(\u7A7A)"}`);
|
|
3398
3185
|
}
|
|
3399
3186
|
keep.add(`${key}.md`);
|
|
3400
|
-
|
|
3401
|
-
toFsPath(
|
|
3187
|
+
writeFileSync3(
|
|
3188
|
+
toFsPath(join4(rulesDir, `${key}.md`)),
|
|
3402
3189
|
withTrailingNewline(rule.body ?? ""),
|
|
3403
3190
|
"utf8"
|
|
3404
3191
|
);
|
|
@@ -3406,7 +3193,7 @@ async function syncWebIdeAgentFiles(workdir, cfg2) {
|
|
|
3406
3193
|
for (const name of readdirSync3(toFsPath(rulesDir))) {
|
|
3407
3194
|
if (!name.endsWith(".md")) continue;
|
|
3408
3195
|
if (keep.has(name)) continue;
|
|
3409
|
-
|
|
3196
|
+
unlinkSync(toFsPath(join4(rulesDir, name)));
|
|
3410
3197
|
}
|
|
3411
3198
|
writeRevision(apmDir, revision);
|
|
3412
3199
|
return {
|
|
@@ -3431,14 +3218,14 @@ async function ensureWorkspaceInitialized(workdir) {
|
|
|
3431
3218
|
|
|
3432
3219
|
// src/utils/project-documents.ts
|
|
3433
3220
|
import {
|
|
3434
|
-
existsSync as
|
|
3221
|
+
existsSync as existsSync6,
|
|
3435
3222
|
readdirSync as readdirSync4,
|
|
3436
|
-
readFileSync as
|
|
3437
|
-
rmSync
|
|
3438
|
-
writeFileSync as
|
|
3223
|
+
readFileSync as readFileSync5,
|
|
3224
|
+
rmSync,
|
|
3225
|
+
writeFileSync as writeFileSync4
|
|
3439
3226
|
} from "fs";
|
|
3440
|
-
import { createHash as
|
|
3441
|
-
import { dirname as
|
|
3227
|
+
import { createHash as createHash2 } from "crypto";
|
|
3228
|
+
import { dirname as dirname2, join as join5, relative as relative4, sep } from "path";
|
|
3442
3229
|
var MANIFEST_FILE = "manifest.json";
|
|
3443
3230
|
function normalizeProjectIdForPath(projectId) {
|
|
3444
3231
|
const id = projectId.trim();
|
|
@@ -3452,11 +3239,11 @@ function normalizeProjectIdForPath(projectId) {
|
|
|
3452
3239
|
}
|
|
3453
3240
|
function projectDocumentsDir(apmRoot, projectId) {
|
|
3454
3241
|
const id = normalizeProjectIdForPath(projectId);
|
|
3455
|
-
return
|
|
3242
|
+
return join5(apmRoot ?? workspaceApmDir(), "project", id);
|
|
3456
3243
|
}
|
|
3457
3244
|
function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
|
|
3458
3245
|
const normalized = normalizeLocalDocumentPath(documentPath);
|
|
3459
|
-
return
|
|
3246
|
+
return join5(
|
|
3460
3247
|
projectDocumentsDir(apmRoot, projectId),
|
|
3461
3248
|
...normalized.split("/")
|
|
3462
3249
|
);
|
|
@@ -3473,19 +3260,19 @@ function normalizeLocalDocumentPath(path3) {
|
|
|
3473
3260
|
return segments.join("/");
|
|
3474
3261
|
}
|
|
3475
3262
|
function hashLocalFileContent(content) {
|
|
3476
|
-
return
|
|
3263
|
+
return createHash2("sha256").update(content, "utf8").digest("hex");
|
|
3477
3264
|
}
|
|
3478
3265
|
function readLocalManifest(apmRoot, projectId) {
|
|
3479
|
-
const manifestPath2 =
|
|
3266
|
+
const manifestPath2 = join5(
|
|
3480
3267
|
projectDocumentsDir(apmRoot, projectId),
|
|
3481
3268
|
MANIFEST_FILE
|
|
3482
3269
|
);
|
|
3483
|
-
if (!
|
|
3270
|
+
if (!existsSync6(manifestPath2)) {
|
|
3484
3271
|
return null;
|
|
3485
3272
|
}
|
|
3486
3273
|
try {
|
|
3487
3274
|
return JSON.parse(
|
|
3488
|
-
|
|
3275
|
+
readFileSync5(manifestPath2, "utf8")
|
|
3489
3276
|
);
|
|
3490
3277
|
} catch {
|
|
3491
3278
|
return null;
|
|
@@ -3493,13 +3280,13 @@ function readLocalManifest(apmRoot, projectId) {
|
|
|
3493
3280
|
}
|
|
3494
3281
|
function listLocalDocumentPaths(apmRoot, projectId) {
|
|
3495
3282
|
const root = projectDocumentsDir(apmRoot, projectId);
|
|
3496
|
-
if (!
|
|
3283
|
+
if (!existsSync6(root)) {
|
|
3497
3284
|
return [];
|
|
3498
3285
|
}
|
|
3499
3286
|
const paths = [];
|
|
3500
3287
|
const walk = (dir) => {
|
|
3501
3288
|
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
3502
|
-
const abs =
|
|
3289
|
+
const abs = join5(dir, entry.name);
|
|
3503
3290
|
if (entry.isDirectory()) {
|
|
3504
3291
|
walk(abs);
|
|
3505
3292
|
continue;
|
|
@@ -3618,8 +3405,8 @@ ${diagnostic ?? ""}`);
|
|
|
3618
3405
|
const absPath = toFsPath(
|
|
3619
3406
|
projectDocumentLocalPath(targetApmDir, projectId, doc.path)
|
|
3620
3407
|
);
|
|
3621
|
-
await ensureDirExists(
|
|
3622
|
-
|
|
3408
|
+
await ensureDirExists(dirname2(absPath));
|
|
3409
|
+
writeFileSync4(absPath, doc.content, "utf8");
|
|
3623
3410
|
downloaded += 1;
|
|
3624
3411
|
}
|
|
3625
3412
|
}
|
|
@@ -3628,13 +3415,13 @@ ${diagnostic ?? ""}`);
|
|
|
3628
3415
|
const absPath = toFsPath(
|
|
3629
3416
|
projectDocumentLocalPath(targetApmDir, projectId, path3)
|
|
3630
3417
|
);
|
|
3631
|
-
if (
|
|
3632
|
-
|
|
3418
|
+
if (existsSync6(absPath)) {
|
|
3419
|
+
rmSync(absPath, { force: true });
|
|
3633
3420
|
deleted += 1;
|
|
3634
3421
|
}
|
|
3635
3422
|
}
|
|
3636
|
-
|
|
3637
|
-
toFsPath(
|
|
3423
|
+
writeFileSync4(
|
|
3424
|
+
toFsPath(join5(docsDir, MANIFEST_FILE)),
|
|
3638
3425
|
`${JSON.stringify(remoteManifest, null, 2)}
|
|
3639
3426
|
`,
|
|
3640
3427
|
"utf8"
|
|
@@ -3677,7 +3464,7 @@ async function syncProjectDocumentsPush(cfg2, workdirPath, apmRoot, options) {
|
|
|
3677
3464
|
const absPath = toFsPath(
|
|
3678
3465
|
projectDocumentLocalPath(targetApmDir, projectId, path3)
|
|
3679
3466
|
);
|
|
3680
|
-
const content =
|
|
3467
|
+
const content = readFileSync5(absPath, "utf8");
|
|
3681
3468
|
const contentHash = hashLocalFileContent(content);
|
|
3682
3469
|
if (remoteHashByPath.get(path3) === contentHash) {
|
|
3683
3470
|
continue;
|
|
@@ -4162,18 +3949,18 @@ async function handleStartProject(cfg2, msg2, signal) {
|
|
|
4162
3949
|
}
|
|
4163
3950
|
|
|
4164
3951
|
// src/commands/connect/webide-agent-registry.ts
|
|
4165
|
-
import { existsSync as
|
|
4166
|
-
import { dirname as
|
|
3952
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3953
|
+
import { dirname as dirname3, resolve as resolve6 } from "node:path";
|
|
4167
3954
|
function registryPath(workdir, taskId, fileName = "cursor-agent.json") {
|
|
4168
3955
|
return resolve6(workdir, ".apm", "webide", taskId, fileName);
|
|
4169
3956
|
}
|
|
4170
3957
|
var DESIGN_AGENT_FILE = "design-agent.json";
|
|
4171
3958
|
function readRegistry(path3) {
|
|
4172
|
-
if (!
|
|
3959
|
+
if (!existsSync7(path3)) {
|
|
4173
3960
|
return {};
|
|
4174
3961
|
}
|
|
4175
3962
|
try {
|
|
4176
|
-
const parsed = JSON.parse(
|
|
3963
|
+
const parsed = JSON.parse(readFileSync6(path3, "utf8"));
|
|
4177
3964
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4178
3965
|
const raw = parsed;
|
|
4179
3966
|
const state = {};
|
|
@@ -4202,8 +3989,8 @@ function readRegistry(path3) {
|
|
|
4202
3989
|
return {};
|
|
4203
3990
|
}
|
|
4204
3991
|
function writeRegistry(path3, registry) {
|
|
4205
|
-
|
|
4206
|
-
|
|
3992
|
+
mkdirSync5(dirname3(path3), { recursive: true });
|
|
3993
|
+
writeFileSync5(path3, `${JSON.stringify(registry, null, 2)}
|
|
4207
3994
|
`, "utf8");
|
|
4208
3995
|
}
|
|
4209
3996
|
function syncWebIdeTaskState(workdir, taskId, patch) {
|
|
@@ -4244,7 +4031,7 @@ function saveWebIdeAgentId(workdir, taskId, agentId) {
|
|
|
4244
4031
|
}
|
|
4245
4032
|
function clearWebIdeAgentId(workdir, taskId) {
|
|
4246
4033
|
const path3 = registryPath(workdir, taskId);
|
|
4247
|
-
if (!
|
|
4034
|
+
if (!existsSync7(path3)) return;
|
|
4248
4035
|
syncWebIdeTaskState(workdir, taskId, { agentId: "" });
|
|
4249
4036
|
}
|
|
4250
4037
|
function loadWebIdeDesignAgentId(workdir, taskId) {
|
|
@@ -4264,7 +4051,7 @@ function saveWebIdeDesignAgentId(workdir, taskId, agentId) {
|
|
|
4264
4051
|
}
|
|
4265
4052
|
function clearWebIdeDesignAgentId(workdir, taskId) {
|
|
4266
4053
|
const path3 = registryPath(workdir, taskId, DESIGN_AGENT_FILE);
|
|
4267
|
-
if (!
|
|
4054
|
+
if (!existsSync7(path3)) return;
|
|
4268
4055
|
const current = readRegistry(path3);
|
|
4269
4056
|
const next = { ...current };
|
|
4270
4057
|
delete next.agentId;
|
|
@@ -4276,9 +4063,9 @@ function clearWebIdeDesignAgentId(workdir, taskId) {
|
|
|
4276
4063
|
}
|
|
4277
4064
|
|
|
4278
4065
|
// src/commands/clean-webide-cache.ts
|
|
4279
|
-
import { existsSync as
|
|
4066
|
+
import { existsSync as existsSync8, rmSync as rmSync2 } from "node:fs";
|
|
4280
4067
|
import { resolve as resolve7 } from "node:path";
|
|
4281
|
-
async function purgeCursorAgentStoreForAgent(cfg2, agentId) {
|
|
4068
|
+
async function purgeCursorAgentStoreForAgent(cfg2, agentId, workspaceRef) {
|
|
4282
4069
|
const trimmedAgentId = agentId.trim();
|
|
4283
4070
|
if (!trimmedAgentId) return false;
|
|
4284
4071
|
const store = createRemoteLocalAgentStore(cfg2);
|
|
@@ -4297,13 +4084,16 @@ async function purgeCursorAgentStoreForAgent(cfg2, agentId) {
|
|
|
4297
4084
|
}
|
|
4298
4085
|
cursor = page.nextCursor;
|
|
4299
4086
|
} while (cursor);
|
|
4300
|
-
if (runIds.length > 0) {
|
|
4301
|
-
await store.runEvents.delete({ filter: { runIds } });
|
|
4302
|
-
}
|
|
4303
4087
|
await store.runs.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
4304
|
-
await store.checkpoints.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
4305
4088
|
await store.agents.delete({ filter: { agentIds: [trimmedAgentId] } });
|
|
4306
|
-
|
|
4089
|
+
const workdir = workspaceRef?.trim();
|
|
4090
|
+
if (workdir) {
|
|
4091
|
+
await purgeLocalSqliteAgentData({
|
|
4092
|
+
workspaceRef: workdir,
|
|
4093
|
+
agentId: trimmedAgentId,
|
|
4094
|
+
runIds
|
|
4095
|
+
});
|
|
4096
|
+
}
|
|
4307
4097
|
return true;
|
|
4308
4098
|
}
|
|
4309
4099
|
async function cleanWebIdeWorkspaceCache(taskId, workdir, cfg2) {
|
|
@@ -4315,7 +4105,11 @@ async function cleanWebIdeWorkspaceCache(taskId, workdir, cfg2) {
|
|
|
4315
4105
|
const agentId = loadWebIdeAgentId(trimmedWorkdir, trimmedTaskId);
|
|
4316
4106
|
if (agentId) {
|
|
4317
4107
|
try {
|
|
4318
|
-
const purged = await purgeCursorAgentStoreForAgent(
|
|
4108
|
+
const purged = await purgeCursorAgentStoreForAgent(
|
|
4109
|
+
cfg2,
|
|
4110
|
+
agentId,
|
|
4111
|
+
trimmedWorkdir
|
|
4112
|
+
);
|
|
4319
4113
|
if (purged) {
|
|
4320
4114
|
console.log(
|
|
4321
4115
|
`[apm] \u5DF2\u6E05\u7406 Cursor agent store agentId=${agentId} taskId=${trimmedTaskId}`
|
|
@@ -4333,8 +4127,8 @@ async function cleanWebIdeWorkspaceCache(taskId, workdir, cfg2) {
|
|
|
4333
4127
|
);
|
|
4334
4128
|
}
|
|
4335
4129
|
const dir = resolve7(trimmedWorkdir, ".apm", "webide", trimmedTaskId);
|
|
4336
|
-
if (
|
|
4337
|
-
|
|
4130
|
+
if (existsSync8(dir)) {
|
|
4131
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
4338
4132
|
console.log(`[apm] \u5DF2\u6E05\u7406 WebIDE \u7F13\u5B58 ${dir}`);
|
|
4339
4133
|
} else {
|
|
4340
4134
|
console.log(`[apm] WebIDE \u7F13\u5B58\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7 ${dir}`);
|
|
@@ -4655,8 +4449,8 @@ async function ensureWebIdePullRequests(cfg2, taskId, workdir) {
|
|
|
4655
4449
|
}
|
|
4656
4450
|
|
|
4657
4451
|
// src/commands/sync-webide-attachments.ts
|
|
4658
|
-
import { existsSync as
|
|
4659
|
-
import { join as
|
|
4452
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
4453
|
+
import { join as join6 } from "path";
|
|
4660
4454
|
var MANIFEST_FILE2 = ".sync-manifest.json";
|
|
4661
4455
|
async function downloadAttachment(cfg2, attachmentId) {
|
|
4662
4456
|
const base = cfg2.baseUrl.trim().replace(/\/+$/, "");
|
|
@@ -4672,13 +4466,13 @@ async function downloadAttachment(cfg2, attachmentId) {
|
|
|
4672
4466
|
return Buffer.from(await res.arrayBuffer());
|
|
4673
4467
|
}
|
|
4674
4468
|
function loadManifest(dir) {
|
|
4675
|
-
const path3 =
|
|
4676
|
-
if (!
|
|
4469
|
+
const path3 = join6(dir, MANIFEST_FILE2);
|
|
4470
|
+
if (!existsSync9(path3)) {
|
|
4677
4471
|
return { version: 1, attachments: {} };
|
|
4678
4472
|
}
|
|
4679
4473
|
try {
|
|
4680
4474
|
const parsed = JSON.parse(
|
|
4681
|
-
|
|
4475
|
+
readFileSync7(path3, "utf8")
|
|
4682
4476
|
);
|
|
4683
4477
|
if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
|
|
4684
4478
|
return parsed;
|
|
@@ -4688,15 +4482,15 @@ function loadManifest(dir) {
|
|
|
4688
4482
|
return { version: 1, attachments: {} };
|
|
4689
4483
|
}
|
|
4690
4484
|
function saveManifest(dir, manifest) {
|
|
4691
|
-
|
|
4692
|
-
|
|
4485
|
+
writeFileSync6(
|
|
4486
|
+
join6(dir, MANIFEST_FILE2),
|
|
4693
4487
|
`${JSON.stringify(manifest, null, 2)}
|
|
4694
4488
|
`,
|
|
4695
4489
|
"utf8"
|
|
4696
4490
|
);
|
|
4697
4491
|
}
|
|
4698
4492
|
function isAttachmentUpToDate(entry, item, dest) {
|
|
4699
|
-
if (!entry || !
|
|
4493
|
+
if (!entry || !existsSync9(dest)) return false;
|
|
4700
4494
|
if (entry.name !== item.name) return false;
|
|
4701
4495
|
const createdAt = item.createdAt ?? "";
|
|
4702
4496
|
return entry.createdAt === createdAt;
|
|
@@ -4711,7 +4505,7 @@ async function syncAttachmentsToDirectory(cfg2, attachments, dir, logLabel) {
|
|
|
4711
4505
|
const nextManifest = { version: 1, attachments: {} };
|
|
4712
4506
|
const names = [];
|
|
4713
4507
|
for (const item of attachments) {
|
|
4714
|
-
const dest =
|
|
4508
|
+
const dest = join6(dir, item.name);
|
|
4715
4509
|
const entry = manifest.attachments[item.id];
|
|
4716
4510
|
const createdAt = item.createdAt ?? "";
|
|
4717
4511
|
names.push(item.name);
|
|
@@ -4721,7 +4515,7 @@ async function syncAttachmentsToDirectory(cfg2, attachments, dir, logLabel) {
|
|
|
4721
4515
|
continue;
|
|
4722
4516
|
}
|
|
4723
4517
|
const buffer = await downloadAttachment(cfg2, item.id);
|
|
4724
|
-
|
|
4518
|
+
writeFileSync6(dest, buffer);
|
|
4725
4519
|
nextManifest.attachments[item.id] = {
|
|
4726
4520
|
name: item.name,
|
|
4727
4521
|
createdAt
|
|
@@ -4742,9 +4536,9 @@ async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
|
|
|
4742
4536
|
}
|
|
4743
4537
|
|
|
4744
4538
|
// src/commands/sync-webide-design.ts
|
|
4745
|
-
import { createHash as
|
|
4746
|
-
import { existsSync as
|
|
4747
|
-
import { join as
|
|
4539
|
+
import { createHash as createHash3 } from "crypto";
|
|
4540
|
+
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
4541
|
+
import { join as join7 } from "path";
|
|
4748
4542
|
|
|
4749
4543
|
// src/opc-shared-types.ts
|
|
4750
4544
|
function webIdeDesignObjectKey(taskId, fileName) {
|
|
@@ -4762,15 +4556,15 @@ function webIdeDesignArtifactContentType(name) {
|
|
|
4762
4556
|
// src/commands/sync-webide-design.ts
|
|
4763
4557
|
var MANIFEST_FILE3 = ".sync-manifest.json";
|
|
4764
4558
|
function hashBuffer(buf) {
|
|
4765
|
-
return
|
|
4559
|
+
return createHash3("sha256").update(buf).digest("hex");
|
|
4766
4560
|
}
|
|
4767
4561
|
function loadManifest2(dir) {
|
|
4768
|
-
const path3 =
|
|
4769
|
-
if (!
|
|
4562
|
+
const path3 = join7(dir, MANIFEST_FILE3);
|
|
4563
|
+
if (!existsSync10(path3)) {
|
|
4770
4564
|
return { version: 1, files: {} };
|
|
4771
4565
|
}
|
|
4772
4566
|
try {
|
|
4773
|
-
const parsed = JSON.parse(
|
|
4567
|
+
const parsed = JSON.parse(readFileSync8(path3, "utf8"));
|
|
4774
4568
|
if (parsed?.version === 1 && parsed.files && typeof parsed.files === "object") {
|
|
4775
4569
|
return parsed;
|
|
4776
4570
|
}
|
|
@@ -4779,8 +4573,8 @@ function loadManifest2(dir) {
|
|
|
4779
4573
|
return { version: 1, files: {} };
|
|
4780
4574
|
}
|
|
4781
4575
|
function saveManifest2(dir, manifest) {
|
|
4782
|
-
|
|
4783
|
-
|
|
4576
|
+
writeFileSync7(
|
|
4577
|
+
join7(dir, MANIFEST_FILE3),
|
|
4784
4578
|
`${JSON.stringify(manifest, null, 2)}
|
|
4785
4579
|
`,
|
|
4786
4580
|
"utf8"
|
|
@@ -4808,13 +4602,13 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
|
|
|
4808
4602
|
for (const art of artifacts) {
|
|
4809
4603
|
const name = art.name?.trim();
|
|
4810
4604
|
if (!name || !isWebIdeDesignArtifactName(name)) continue;
|
|
4811
|
-
const localPath =
|
|
4605
|
+
const localPath = join7(dir, name);
|
|
4812
4606
|
const entry = manifest.files[name];
|
|
4813
|
-
if (entry?.contentHash === art.contentHash &&
|
|
4607
|
+
if (entry?.contentHash === art.contentHash && existsSync10(localPath)) {
|
|
4814
4608
|
continue;
|
|
4815
4609
|
}
|
|
4816
4610
|
const buf = await downloadDesignFile(cfg2, taskId, name);
|
|
4817
|
-
|
|
4611
|
+
writeFileSync7(localPath, buf);
|
|
4818
4612
|
manifest.files[name] = { contentHash: hashBuffer(buf) };
|
|
4819
4613
|
synced.push(name);
|
|
4820
4614
|
}
|
|
@@ -4823,13 +4617,13 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
|
|
|
4823
4617
|
}
|
|
4824
4618
|
function listLocalDesignArtifactFiles(taskId, workdir) {
|
|
4825
4619
|
const dir = webideDesignDir(taskId, workdir);
|
|
4826
|
-
if (!
|
|
4620
|
+
if (!existsSync10(dir)) return [];
|
|
4827
4621
|
const out = [];
|
|
4828
4622
|
for (const name of readdirSync5(dir)) {
|
|
4829
4623
|
if (!isWebIdeDesignArtifactName(name)) continue;
|
|
4830
|
-
const absPath =
|
|
4624
|
+
const absPath = join7(dir, name);
|
|
4831
4625
|
if (!statSync5(absPath).isFile()) continue;
|
|
4832
|
-
const buf =
|
|
4626
|
+
const buf = readFileSync8(absPath);
|
|
4833
4627
|
if (buf.length === 0) continue;
|
|
4834
4628
|
out.push({ name, absPath, contentHash: hashBuffer(buf) });
|
|
4835
4629
|
}
|
|
@@ -4934,26 +4728,36 @@ function completeActionForInbound(action) {
|
|
|
4934
4728
|
switch (action) {
|
|
4935
4729
|
case "request-assessment":
|
|
4936
4730
|
case "confirm-assumptions":
|
|
4731
|
+
case "start-assessment":
|
|
4732
|
+
case "continue-assessment":
|
|
4937
4733
|
return "complete-assessment";
|
|
4938
4734
|
case "request-design":
|
|
4939
4735
|
case "request-revise-design":
|
|
4736
|
+
case "start-design":
|
|
4940
4737
|
return "complete-design";
|
|
4941
4738
|
case "request-write-plan":
|
|
4942
4739
|
case "request-revise-plan":
|
|
4740
|
+
case "start-write-plan":
|
|
4943
4741
|
return "complete-write-plan";
|
|
4944
4742
|
case "request-develop":
|
|
4945
4743
|
case "skip-plan":
|
|
4744
|
+
case "start-develop":
|
|
4946
4745
|
return "complete-develop";
|
|
4947
4746
|
case "request-start-project":
|
|
4747
|
+
case "start-project":
|
|
4948
4748
|
return "complete-project";
|
|
4949
4749
|
case "request-execute-sql":
|
|
4750
|
+
case "start-execute-sql":
|
|
4950
4751
|
return "complete-execute-sql";
|
|
4951
4752
|
case "request-bugfix":
|
|
4753
|
+
case "start-bugfix":
|
|
4952
4754
|
return "complete-bugfix";
|
|
4953
4755
|
case "request-organize-code":
|
|
4954
4756
|
case "request-patch":
|
|
4757
|
+
case "start-organize-code":
|
|
4955
4758
|
return "complete-organize-code";
|
|
4956
4759
|
case "request-accept":
|
|
4760
|
+
case "start-accept":
|
|
4957
4761
|
return "complete-accept";
|
|
4958
4762
|
default:
|
|
4959
4763
|
return null;
|
|
@@ -4964,6 +4768,13 @@ async function webIdeRunAction(cfg2, taskId, action, params) {
|
|
|
4964
4768
|
await api.cli.webideRunAction({ taskId, action, params });
|
|
4965
4769
|
console.log(`[apm] webide runAction ok action=${action} taskId=${taskId}`);
|
|
4966
4770
|
}
|
|
4771
|
+
async function webIdeAttachContinueRun(cfg2, taskId, runId) {
|
|
4772
|
+
const api = createApmApiClient(cfg2);
|
|
4773
|
+
await api.cli.webideAttachContinueRun({ taskId, runId });
|
|
4774
|
+
console.log(
|
|
4775
|
+
`[apm] webide attachContinueRun ok runId=${runId} taskId=${taskId}`
|
|
4776
|
+
);
|
|
4777
|
+
}
|
|
4967
4778
|
async function webIdeSyncTransitionPrepEvents(cfg2, taskId, startAction, prepEvents) {
|
|
4968
4779
|
try {
|
|
4969
4780
|
const api = createApmApiClient(cfg2);
|
|
@@ -5036,8 +4847,11 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
|
|
|
5036
4847
|
const messageId = msg2.messageId;
|
|
5037
4848
|
const taskId = msg2.taskId;
|
|
5038
4849
|
const branchCacheKey = taskId;
|
|
4850
|
+
const continuePayload = msg2.action === "continue" ? parseWebIdePromptPayload(msg2.content) : null;
|
|
4851
|
+
const previousAction = typeof continuePayload?.previousAction === "string" ? continuePayload.previousAction.trim() : "";
|
|
4852
|
+
const effectiveAction = msg2.action === "continue" && previousAction ? previousAction : msg2.action;
|
|
5039
4853
|
console.log(
|
|
5040
|
-
`[apm] webide-message action=${msg2.action} taskId=${taskId} messageId=${messageId}`
|
|
4854
|
+
`[apm] webide-message action=${msg2.action}${previousAction ? ` previousAction=${previousAction}` : ""} taskId=${taskId} messageId=${messageId}`
|
|
5041
4855
|
);
|
|
5042
4856
|
await updateStatus2(cfg2, messageId, "TYPING");
|
|
5043
4857
|
syncLocalTaskStatus(workdir, taskId, msg2, "TYPING");
|
|
@@ -5140,7 +4954,7 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
|
|
|
5140
4954
|
eventSession.addCliStep("\u51C6\u5907\u7279\u6027\u5206\u652F", "\u5DF2\u7F13\u5B58\uFF0C\u8DF3\u8FC7", "skip");
|
|
5141
4955
|
await syncPrepLog();
|
|
5142
4956
|
}
|
|
5143
|
-
if (shouldEnsureWebIdePullRequests(
|
|
4957
|
+
if (shouldEnsureWebIdePullRequests(effectiveAction)) {
|
|
5144
4958
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
5145
4959
|
await runPrepStep(
|
|
5146
4960
|
"\u9A8C\u6536\u524D\u63A8\u9001",
|
|
@@ -5246,8 +5060,8 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
|
|
|
5246
5060
|
"running"
|
|
5247
5061
|
);
|
|
5248
5062
|
await syncPrepLog();
|
|
5249
|
-
const startLocalServices = isStartLocalServicesAction(
|
|
5250
|
-
const designAction = isDesignAction(
|
|
5063
|
+
const startLocalServices = isStartLocalServicesAction(effectiveAction);
|
|
5064
|
+
const designAction = isDesignAction(effectiveAction);
|
|
5251
5065
|
const useNewAgent = msg2.useNewAgent === true;
|
|
5252
5066
|
const toolNames = Array.isArray(msg2.tools) ? msg2.tools.map((t) => String(t).trim()).filter(Boolean) : [];
|
|
5253
5067
|
if (useNewAgent && !startLocalServices) {
|
|
@@ -5258,7 +5072,7 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
|
|
|
5258
5072
|
}
|
|
5259
5073
|
}
|
|
5260
5074
|
const savedAgentId = startLocalServices || useNewAgent ? void 0 : designAction ? loadWebIdeDesignAgentId(workdir, taskId) : loadWebIdeAgentId(workdir, taskId);
|
|
5261
|
-
const promptPayload = toolNames.includes("MysqlExecute") ? parseWebIdePromptPayload(msg2.content) : null;
|
|
5075
|
+
const promptPayload = toolNames.includes("MysqlExecute") ? continuePayload ?? parseWebIdePromptPayload(msg2.content) : null;
|
|
5262
5076
|
const sqlExecutionId = toolNames.includes("MysqlExecute") && typeof promptPayload?.executionId === "string" ? promptPayload.executionId.trim() : void 0;
|
|
5263
5077
|
if (toolNames.includes("MysqlExecute") && !sqlExecutionId) {
|
|
5264
5078
|
console.warn(
|
|
@@ -5348,6 +5162,15 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5348
5162
|
eventSession.getCliSteps()
|
|
5349
5163
|
);
|
|
5350
5164
|
await webIdeRunAction(cfg2, taskId, startAction, { runId });
|
|
5165
|
+
} else if (msg2.action === "continue") {
|
|
5166
|
+
try {
|
|
5167
|
+
await webIdeAttachContinueRun(cfg2, taskId, runId);
|
|
5168
|
+
} catch (err) {
|
|
5169
|
+
console.warn(
|
|
5170
|
+
"[apm] attach continue run failed:",
|
|
5171
|
+
err instanceof Error ? err.message : err
|
|
5172
|
+
);
|
|
5173
|
+
}
|
|
5351
5174
|
}
|
|
5352
5175
|
}
|
|
5353
5176
|
}
|
|
@@ -5374,7 +5197,7 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5374
5197
|
detail,
|
|
5375
5198
|
tokenUsage
|
|
5376
5199
|
);
|
|
5377
|
-
if (sqlExecutionId &&
|
|
5200
|
+
if (sqlExecutionId && effectiveAction !== "request-bugfix") {
|
|
5378
5201
|
try {
|
|
5379
5202
|
await api.cli.webideFinalizeSqlExecution({
|
|
5380
5203
|
executionId: sqlExecutionId,
|
|
@@ -5399,7 +5222,7 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5399
5222
|
"\u5DF2\u53D6\u6D88",
|
|
5400
5223
|
tokenUsage
|
|
5401
5224
|
);
|
|
5402
|
-
if (sqlExecutionId &&
|
|
5225
|
+
if (sqlExecutionId && effectiveAction !== "request-bugfix") {
|
|
5403
5226
|
try {
|
|
5404
5227
|
await api.cli.webideFinalizeSqlExecution({
|
|
5405
5228
|
executionId: sqlExecutionId,
|
|
@@ -5426,7 +5249,7 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5426
5249
|
id: messageId,
|
|
5427
5250
|
content: fallback
|
|
5428
5251
|
});
|
|
5429
|
-
if ((
|
|
5252
|
+
if ((effectiveAction === "write-plan" || effectiveAction === "revise-plan" || effectiveAction === "request-write-plan" || effectiveAction === "request-revise-plan" || effectiveAction === "start-write-plan") && outcome.createPlan && outcome.createPlan.trim()) {
|
|
5430
5253
|
try {
|
|
5431
5254
|
await api.cli.webideUpsertPlan({
|
|
5432
5255
|
taskId,
|
|
@@ -5434,12 +5257,12 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5434
5257
|
});
|
|
5435
5258
|
} catch (err) {
|
|
5436
5259
|
console.warn(
|
|
5437
|
-
`[apm] ${
|
|
5260
|
+
`[apm] ${effectiveAction} \u8865\u5199\u8BA1\u5212\u5931\u8D25:`,
|
|
5438
5261
|
err instanceof Error ? err.message : err
|
|
5439
5262
|
);
|
|
5440
5263
|
}
|
|
5441
5264
|
}
|
|
5442
|
-
if (isDesignAction(
|
|
5265
|
+
if (isDesignAction(effectiveAction)) {
|
|
5443
5266
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
5444
5267
|
try {
|
|
5445
5268
|
const uploaded = await uploadWebIdeDesignArtifacts(
|
|
@@ -5448,7 +5271,7 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5448
5271
|
workdir
|
|
5449
5272
|
);
|
|
5450
5273
|
console.log(
|
|
5451
|
-
`[apm] webide \u8BBE\u8BA1\u4EA7\u7269\u4E0A\u4F20 action=${
|
|
5274
|
+
`[apm] webide \u8BBE\u8BA1\u4EA7\u7269\u4E0A\u4F20 action=${effectiveAction} uploaded=${uploaded.uploaded} skipped=${uploaded.skipped} files=${uploaded.artifacts.map((a) => a.name).join(",")}`
|
|
5452
5275
|
);
|
|
5453
5276
|
} catch (err) {
|
|
5454
5277
|
const detail = err instanceof Error ? err.message : String(err);
|
|
@@ -5463,27 +5286,27 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5463
5286
|
return;
|
|
5464
5287
|
}
|
|
5465
5288
|
}
|
|
5466
|
-
if (shouldCommitAfterWebIdeMessage(
|
|
5289
|
+
if (shouldCommitAfterWebIdeMessage(effectiveAction)) {
|
|
5467
5290
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
5468
5291
|
const committed = await commitWorkspaceReposIfDirty(
|
|
5469
5292
|
workdir,
|
|
5470
|
-
`chore(webide): sync after ${
|
|
5293
|
+
`chore(webide): sync after ${effectiveAction} (${taskId})`
|
|
5471
5294
|
);
|
|
5472
5295
|
console.log(
|
|
5473
|
-
`[apm] webide \u515C\u5E95 commit action=${
|
|
5296
|
+
`[apm] webide \u515C\u5E95 commit action=${effectiveAction} repos=${committed}`
|
|
5474
5297
|
);
|
|
5475
5298
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
5476
5299
|
const pushed = await pushWorkspaceRepos(workdir);
|
|
5477
5300
|
console.log(
|
|
5478
|
-
`[apm] webide \u81EA\u52A8 push action=${
|
|
5301
|
+
`[apm] webide \u81EA\u52A8 push action=${effectiveAction} repos=${pushed}`
|
|
5479
5302
|
);
|
|
5480
5303
|
}
|
|
5481
|
-
if (shouldEnsureWebIdePullRequestsAfterAgent(
|
|
5304
|
+
if (shouldEnsureWebIdePullRequestsAfterAgent(effectiveAction)) {
|
|
5482
5305
|
if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
|
|
5483
|
-
if (!shouldCommitAfterWebIdeMessage(
|
|
5306
|
+
if (!shouldCommitAfterWebIdeMessage(effectiveAction)) {
|
|
5484
5307
|
const pushed = await pushWorkspaceRepos(workdir);
|
|
5485
5308
|
console.log(
|
|
5486
|
-
`[apm] webide create-pr \u524D push action=${
|
|
5309
|
+
`[apm] webide create-pr \u524D push action=${effectiveAction} repos=${pushed}`
|
|
5487
5310
|
);
|
|
5488
5311
|
}
|
|
5489
5312
|
const prResult = await ensureWebIdePullRequests(cfg2, taskId, workdir);
|
|
@@ -5537,20 +5360,20 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5537
5360
|
null,
|
|
5538
5361
|
tokenUsage
|
|
5539
5362
|
);
|
|
5540
|
-
const completeAction = completeActionForInbound(
|
|
5363
|
+
const completeAction = completeActionForInbound(effectiveAction);
|
|
5541
5364
|
if (completeAction && !pausedForAssumptions) {
|
|
5542
5365
|
await webIdeRunAction(cfg2, taskId, completeAction);
|
|
5543
5366
|
} else if (pausedForAssumptions) {
|
|
5544
5367
|
console.log(
|
|
5545
|
-
`[apm] \u672C\u8F6E\u505C\u5728\u5F85\u786E\u8BA4\u5047\u8BBE\uFF0C\u8DF3\u8FC7 complete action=${
|
|
5368
|
+
`[apm] \u672C\u8F6E\u505C\u5728\u5F85\u786E\u8BA4\u5047\u8BBE\uFF0C\u8DF3\u8FC7 complete action=${effectiveAction} taskId=${taskId}`
|
|
5546
5369
|
);
|
|
5547
5370
|
}
|
|
5548
5371
|
await updateStatus2(cfg2, messageId, "SUCCESS");
|
|
5549
5372
|
syncLocalTaskStatus(workdir, taskId, msg2, "SUCCESS");
|
|
5550
5373
|
console.log(
|
|
5551
|
-
`[apm] webide-message \u5B8C\u6210 action=${msg2.action} messageId=${messageId} agentId=${outcome.agentId}`
|
|
5374
|
+
`[apm] webide-message \u5B8C\u6210 action=${msg2.action}${previousAction ? ` previousAction=${previousAction}` : ""} messageId=${messageId} agentId=${outcome.agentId}`
|
|
5552
5375
|
);
|
|
5553
|
-
if (
|
|
5376
|
+
if (effectiveAction === "request-accept" || effectiveAction === "start-accept") {
|
|
5554
5377
|
try {
|
|
5555
5378
|
await cleanWebIdeWorkspaceCache(taskId, workdir, cfg2);
|
|
5556
5379
|
} catch (err) {
|
|
@@ -5577,7 +5400,7 @@ ${assumptionAnswersText}` : msg2.content,
|
|
|
5577
5400
|
statusErr instanceof Error ? statusErr.message : statusErr
|
|
5578
5401
|
);
|
|
5579
5402
|
}
|
|
5580
|
-
const completeAction = completeActionForInbound(
|
|
5403
|
+
const completeAction = completeActionForInbound(effectiveAction);
|
|
5581
5404
|
if (completeAction === "complete-assessment" && !pausedForAssumptions) {
|
|
5582
5405
|
try {
|
|
5583
5406
|
await webIdeRunAction(cfg2, taskId, completeAction, { force: true });
|