ai-project-manage-cli 8.0.17 → 8.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -142,6 +142,14 @@ var init_request_config = __esm({
142
142
  method: "GET",
143
143
  path: "/cli/webide/attachments"
144
144
  }),
145
+ webideListDesignArtifacts: defineEndpoint({
146
+ method: "GET",
147
+ path: "/cli/webide/design-artifacts"
148
+ }),
149
+ webideRegisterDesignArtifacts: defineEndpoint({
150
+ method: "PUT",
151
+ path: "/cli/webide/design-artifacts"
152
+ }),
145
153
  webideRecommendPlan: defineEndpoint({
146
154
  method: "PUT",
147
155
  path: "/cli/webide/plan-recommendation"
@@ -46,6 +46,14 @@ var requestConfig = {
46
46
  method: "GET",
47
47
  path: "/cli/webide/attachments"
48
48
  }),
49
+ webideListDesignArtifacts: defineEndpoint({
50
+ method: "GET",
51
+ path: "/cli/webide/design-artifacts"
52
+ }),
53
+ webideRegisterDesignArtifacts: defineEndpoint({
54
+ method: "PUT",
55
+ path: "/cli/webide/design-artifacts"
56
+ }),
49
57
  webideRecommendPlan: defineEndpoint({
50
58
  method: "PUT",
51
59
  path: "/cli/webide/plan-recommendation"
@@ -263,12 +271,16 @@ function isWorkspaceApmInitialized(workdir) {
263
271
  }
264
272
  var WEBIDE_SUBDIR = "webide";
265
273
  var WEBIDE_ATTACHMENTS_SUBDIR = "attachments";
274
+ var WEBIDE_DESIGN_SUBDIR = "design";
266
275
  function webideTaskDir(taskId, workdir) {
267
276
  return join2(workdir, ".apm", WEBIDE_SUBDIR, taskId);
268
277
  }
269
278
  function webideAttachmentsDir(taskId, workdir) {
270
279
  return join2(webideTaskDir(taskId, workdir), WEBIDE_ATTACHMENTS_SUBDIR);
271
280
  }
281
+ function webideDesignDir(taskId, workdir) {
282
+ return join2(webideTaskDir(taskId, workdir), WEBIDE_DESIGN_SUBDIR);
283
+ }
272
284
  async function ensureLoggedConfig() {
273
285
  const cfg = await ensureApmConfig();
274
286
  if (!resolveApiKey(cfg)) {
@@ -2563,9 +2575,10 @@ async function runCursorAgent(cfg, ctx, options) {
2563
2575
  // src/commands/connect/webide-agent-registry.ts
2564
2576
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
2565
2577
  import { dirname as dirname3, resolve as resolve6 } from "node:path";
2566
- function registryPath(workdir, taskId) {
2567
- return resolve6(workdir, ".apm", "webide", taskId, "cursor-agent.json");
2578
+ function registryPath(workdir, taskId, fileName = "cursor-agent.json") {
2579
+ return resolve6(workdir, ".apm", "webide", taskId, fileName);
2568
2580
  }
2581
+ var DESIGN_AGENT_FILE = "design-agent.json";
2569
2582
  function readRegistry(path3) {
2570
2583
  if (!existsSync5(path3)) {
2571
2584
  return {};
@@ -2645,6 +2658,33 @@ function clearWebIdeAgentId(workdir, taskId) {
2645
2658
  if (!existsSync5(path3)) return;
2646
2659
  syncWebIdeTaskState(workdir, taskId, { agentId: "" });
2647
2660
  }
2661
+ function loadWebIdeDesignAgentId(workdir, taskId) {
2662
+ return readRegistry(registryPath(workdir, taskId, DESIGN_AGENT_FILE)).agentId;
2663
+ }
2664
+ function saveWebIdeDesignAgentId(workdir, taskId, agentId) {
2665
+ const trimmedTaskId = taskId.trim();
2666
+ if (!trimmedTaskId) return;
2667
+ const path3 = registryPath(workdir, trimmedTaskId, DESIGN_AGENT_FILE);
2668
+ const current = readRegistry(path3);
2669
+ writeRegistry(path3, {
2670
+ ...current,
2671
+ taskId: trimmedTaskId,
2672
+ agentId: agentId.trim() || void 0,
2673
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2674
+ });
2675
+ }
2676
+ function clearWebIdeDesignAgentId(workdir, taskId) {
2677
+ const path3 = registryPath(workdir, taskId, DESIGN_AGENT_FILE);
2678
+ if (!existsSync5(path3)) return;
2679
+ const current = readRegistry(path3);
2680
+ const next = { ...current };
2681
+ delete next.agentId;
2682
+ writeRegistry(path3, {
2683
+ ...next,
2684
+ taskId: taskId.trim(),
2685
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2686
+ });
2687
+ }
2648
2688
 
2649
2689
  // src/commands/clean-webide-cache.ts
2650
2690
  import { existsSync as existsSync6, rmSync } from "node:fs";
@@ -3314,17 +3354,149 @@ async function syncWebIdeAttachments(cfg, taskId, workdir, attachments) {
3314
3354
  );
3315
3355
  }
3316
3356
 
3357
+ // src/commands/sync-webide-design.ts
3358
+ import { createHash as createHash2 } from "crypto";
3359
+ import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
3360
+ import { join as join6 } from "path";
3361
+ var MANIFEST_FILE2 = ".sync-manifest.json";
3362
+ function hashBuffer(buf) {
3363
+ return createHash2("sha256").update(buf).digest("hex");
3364
+ }
3365
+ function loadManifest2(dir) {
3366
+ const path3 = join6(dir, MANIFEST_FILE2);
3367
+ if (!existsSync8(path3)) {
3368
+ return { version: 1, files: {} };
3369
+ }
3370
+ try {
3371
+ const parsed = JSON.parse(readFileSync7(path3, "utf8"));
3372
+ if (parsed?.version === 1 && parsed.files && typeof parsed.files === "object") {
3373
+ return parsed;
3374
+ }
3375
+ } catch {
3376
+ }
3377
+ return { version: 1, files: {} };
3378
+ }
3379
+ function saveManifest2(dir, manifest) {
3380
+ writeFileSync5(
3381
+ join6(dir, MANIFEST_FILE2),
3382
+ `${JSON.stringify(manifest, null, 2)}
3383
+ `,
3384
+ "utf8"
3385
+ );
3386
+ }
3387
+ async function downloadDesignFile(cfg, taskId, name) {
3388
+ const base = cfg.baseUrl.trim().replace(/\/+$/, "");
3389
+ const apiKey = resolveApiKey(cfg);
3390
+ const params = new URLSearchParams({ taskId, name });
3391
+ if (apiKey) params.set("apiKey", apiKey);
3392
+ const url = `${base}/api/v1/cli/webide/design-artifacts/file?${params}`;
3393
+ const res = await fetch(url);
3394
+ if (!res.ok) {
3395
+ throw new Error(
3396
+ `[apm] \u4E0B\u8F7D\u8BBE\u8BA1\u6587\u4EF6\u5931\u8D25 (${res.status}): taskId=${taskId} name=${name}`
3397
+ );
3398
+ }
3399
+ return Buffer.from(await res.arrayBuffer());
3400
+ }
3401
+ async function syncWebIdeDesign(cfg, taskId, workdir, artifacts) {
3402
+ const dir = webideDesignDir(taskId, workdir);
3403
+ await ensureDirExists(dir);
3404
+ const manifest = loadManifest2(dir);
3405
+ const synced = [];
3406
+ for (const art of artifacts) {
3407
+ const name = art.name?.trim();
3408
+ if (!name || !name.toLowerCase().endsWith(".html")) continue;
3409
+ const localPath = join6(dir, name);
3410
+ const entry = manifest.files[name];
3411
+ if (entry?.contentHash === art.contentHash && existsSync8(localPath)) {
3412
+ continue;
3413
+ }
3414
+ const buf = await downloadDesignFile(cfg, taskId, name);
3415
+ writeFileSync5(localPath, buf);
3416
+ manifest.files[name] = { contentHash: hashBuffer(buf) };
3417
+ synced.push(name);
3418
+ }
3419
+ saveManifest2(dir, manifest);
3420
+ return synced;
3421
+ }
3422
+ function listLocalDesignHtmlFiles(taskId, workdir) {
3423
+ const dir = webideDesignDir(taskId, workdir);
3424
+ if (!existsSync8(dir)) return [];
3425
+ const out = [];
3426
+ for (const name of readdirSync3(dir)) {
3427
+ if (!name.toLowerCase().endsWith(".html")) continue;
3428
+ const absPath = join6(dir, name);
3429
+ const buf = readFileSync7(absPath);
3430
+ if (buf.length === 0) continue;
3431
+ out.push({ name, absPath, contentHash: hashBuffer(buf) });
3432
+ }
3433
+ return out;
3434
+ }
3435
+
3436
+ // src/opc-shared-types.ts
3437
+ function webIdeDesignObjectKey(taskId, fileName) {
3438
+ const safe = fileName.replace(/[/\\:*?"<>|]/g, "_").trim() || "index.html";
3439
+ return `tasks/${taskId.trim()}/design/${safe}`;
3440
+ }
3441
+
3442
+ // src/commands/connect/upload-webide-design.ts
3443
+ async function uploadWebIdeDesignArtifacts(cfg, taskId, workdir) {
3444
+ const locals = listLocalDesignHtmlFiles(taskId, workdir);
3445
+ if (locals.length === 0) {
3446
+ throw new Error(
3447
+ `\u8BBE\u8BA1\u76EE\u5F55\u65E0 HTML \u4EA7\u7269\uFF1A.apm/webide/${taskId}/design/\uFF08\u8BF7\u5199\u5165\u81F3\u5C11\u4E00\u4EFD .html\uFF09`
3448
+ );
3449
+ }
3450
+ const api = createApmApiClient(cfg);
3451
+ const remote = await api.cli.webideListDesignArtifacts({ taskId }) ?? [];
3452
+ const remoteByName = new Map(
3453
+ remote.map((r) => [r.name, r])
3454
+ );
3455
+ const { client, bucket } = await createApmLogMinioClient(cfg);
3456
+ await client.ensureBucket(bucket);
3457
+ let uploaded = 0;
3458
+ let skipped = 0;
3459
+ const artifacts = [];
3460
+ for (const file of locals) {
3461
+ const objectKey = webIdeDesignObjectKey(taskId, file.name);
3462
+ const prev = remoteByName.get(file.name);
3463
+ if (prev?.contentHash === file.contentHash) {
3464
+ skipped += 1;
3465
+ artifacts.push({
3466
+ name: file.name,
3467
+ objectKey: prev.objectKey || objectKey,
3468
+ contentHash: file.contentHash
3469
+ });
3470
+ continue;
3471
+ }
3472
+ await client.fPutObject(bucket, objectKey, file.absPath, {
3473
+ "Content-Type": "text/html; charset=utf-8"
3474
+ });
3475
+ uploaded += 1;
3476
+ artifacts.push({
3477
+ name: file.name,
3478
+ objectKey,
3479
+ contentHash: file.contentHash
3480
+ });
3481
+ }
3482
+ await api.cli.webideRegisterDesignArtifacts({
3483
+ taskId,
3484
+ artifacts
3485
+ });
3486
+ return { uploaded, skipped, artifacts };
3487
+ }
3488
+
3317
3489
  // src/utils/project-documents.ts
3318
3490
  import {
3319
- existsSync as existsSync8,
3320
- readdirSync as readdirSync3,
3321
- readFileSync as readFileSync7,
3491
+ existsSync as existsSync9,
3492
+ readdirSync as readdirSync4,
3493
+ readFileSync as readFileSync8,
3322
3494
  rmSync as rmSync2,
3323
- writeFileSync as writeFileSync5
3495
+ writeFileSync as writeFileSync6
3324
3496
  } from "fs";
3325
- import { createHash as createHash2 } from "crypto";
3326
- import { dirname as dirname5, join as join6, relative as relative4, sep } from "path";
3327
- var MANIFEST_FILE2 = "manifest.json";
3497
+ import { createHash as createHash3 } from "crypto";
3498
+ import { dirname as dirname5, join as join7, relative as relative4, sep } from "path";
3499
+ var MANIFEST_FILE3 = "manifest.json";
3328
3500
  function normalizeProjectIdForPath(projectId) {
3329
3501
  const id = projectId.trim();
3330
3502
  if (!id) {
@@ -3337,11 +3509,11 @@ function normalizeProjectIdForPath(projectId) {
3337
3509
  }
3338
3510
  function projectDocumentsDir(apmRoot, projectId) {
3339
3511
  const id = normalizeProjectIdForPath(projectId);
3340
- return join6(apmRoot ?? workspaceApmDir(), "project", id);
3512
+ return join7(apmRoot ?? workspaceApmDir(), "project", id);
3341
3513
  }
3342
3514
  function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
3343
3515
  const normalized = normalizeLocalDocumentPath(documentPath);
3344
- return join6(
3516
+ return join7(
3345
3517
  projectDocumentsDir(apmRoot, projectId),
3346
3518
  ...normalized.split("/")
3347
3519
  );
@@ -3358,19 +3530,19 @@ function normalizeLocalDocumentPath(path3) {
3358
3530
  return segments.join("/");
3359
3531
  }
3360
3532
  function hashLocalFileContent(content) {
3361
- return createHash2("sha256").update(content, "utf8").digest("hex");
3533
+ return createHash3("sha256").update(content, "utf8").digest("hex");
3362
3534
  }
3363
3535
  function readLocalManifest(apmRoot, projectId) {
3364
- const manifestPath3 = join6(
3536
+ const manifestPath3 = join7(
3365
3537
  projectDocumentsDir(apmRoot, projectId),
3366
- MANIFEST_FILE2
3538
+ MANIFEST_FILE3
3367
3539
  );
3368
- if (!existsSync8(manifestPath3)) {
3540
+ if (!existsSync9(manifestPath3)) {
3369
3541
  return null;
3370
3542
  }
3371
3543
  try {
3372
3544
  return JSON.parse(
3373
- readFileSync7(manifestPath3, "utf8")
3545
+ readFileSync8(manifestPath3, "utf8")
3374
3546
  );
3375
3547
  } catch {
3376
3548
  return null;
@@ -3378,18 +3550,18 @@ function readLocalManifest(apmRoot, projectId) {
3378
3550
  }
3379
3551
  function listLocalDocumentPaths(apmRoot, projectId) {
3380
3552
  const root = projectDocumentsDir(apmRoot, projectId);
3381
- if (!existsSync8(root)) {
3553
+ if (!existsSync9(root)) {
3382
3554
  return [];
3383
3555
  }
3384
3556
  const paths = [];
3385
3557
  const walk = (dir) => {
3386
- for (const entry of readdirSync3(dir, { withFileTypes: true })) {
3387
- const abs = join6(dir, entry.name);
3558
+ for (const entry of readdirSync4(dir, { withFileTypes: true })) {
3559
+ const abs = join7(dir, entry.name);
3388
3560
  if (entry.isDirectory()) {
3389
3561
  walk(abs);
3390
3562
  continue;
3391
3563
  }
3392
- if (entry.isFile() && entry.name === MANIFEST_FILE2) {
3564
+ if (entry.isFile() && entry.name === MANIFEST_FILE3) {
3393
3565
  continue;
3394
3566
  }
3395
3567
  const rel = relative4(root, abs).split(sep).join("/");
@@ -3504,7 +3676,7 @@ ${diagnostic ?? ""}`);
3504
3676
  projectDocumentLocalPath(targetApmDir, projectId, doc.path)
3505
3677
  );
3506
3678
  await ensureDirExists(dirname5(absPath));
3507
- writeFileSync5(absPath, doc.content, "utf8");
3679
+ writeFileSync6(absPath, doc.content, "utf8");
3508
3680
  downloaded += 1;
3509
3681
  }
3510
3682
  }
@@ -3513,13 +3685,13 @@ ${diagnostic ?? ""}`);
3513
3685
  const absPath = toFsPath(
3514
3686
  projectDocumentLocalPath(targetApmDir, projectId, path3)
3515
3687
  );
3516
- if (existsSync8(absPath)) {
3688
+ if (existsSync9(absPath)) {
3517
3689
  rmSync2(absPath, { force: true });
3518
3690
  deleted += 1;
3519
3691
  }
3520
3692
  }
3521
- writeFileSync5(
3522
- toFsPath(join6(docsDir, MANIFEST_FILE2)),
3693
+ writeFileSync6(
3694
+ toFsPath(join7(docsDir, MANIFEST_FILE3)),
3523
3695
  `${JSON.stringify(remoteManifest, null, 2)}
3524
3696
  `,
3525
3697
  "utf8"
@@ -3562,7 +3734,7 @@ async function syncProjectDocumentsPush(cfg, workdirPath, apmRoot, options) {
3562
3734
  const absPath = toFsPath(
3563
3735
  projectDocumentLocalPath(targetApmDir, projectId, path3)
3564
3736
  );
3565
- const content = readFileSync7(absPath, "utf8");
3737
+ const content = readFileSync8(absPath, "utf8");
3566
3738
  const contentHash = hashLocalFileContent(content);
3567
3739
  if (remoteHashByPath.get(path3) === contentHash) {
3568
3740
  continue;
@@ -3583,20 +3755,20 @@ async function syncProjectDocumentsPush(cfg, workdirPath, apmRoot, options) {
3583
3755
  }
3584
3756
 
3585
3757
  // src/commands/connect/cli-version-sync.ts
3586
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
3587
- import { join as join7 } from "path";
3758
+ import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
3759
+ import { join as join8 } from "path";
3588
3760
  var CLI_VERSION_FILE = ".cli-version.json";
3589
3761
  function manifestPath2(apmDir) {
3590
- return join7(apmDir, CLI_VERSION_FILE);
3762
+ return join8(apmDir, CLI_VERSION_FILE);
3591
3763
  }
3592
- function loadManifest2(apmDir) {
3764
+ function loadManifest3(apmDir) {
3593
3765
  const path3 = toFsPath(manifestPath2(apmDir));
3594
- if (!existsSync9(path3)) {
3766
+ if (!existsSync10(path3)) {
3595
3767
  return null;
3596
3768
  }
3597
3769
  try {
3598
3770
  const parsed = JSON.parse(
3599
- readFileSync8(path3, "utf8")
3771
+ readFileSync9(path3, "utf8")
3600
3772
  );
3601
3773
  if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
3602
3774
  return parsed;
@@ -3605,9 +3777,9 @@ function loadManifest2(apmDir) {
3605
3777
  }
3606
3778
  return null;
3607
3779
  }
3608
- function saveManifest2(apmDir, cliVersion) {
3780
+ function saveManifest3(apmDir, cliVersion) {
3609
3781
  const manifest = { version: 1, cliVersion };
3610
- writeFileSync6(
3782
+ writeFileSync7(
3611
3783
  toFsPath(manifestPath2(apmDir)),
3612
3784
  `${JSON.stringify(manifest, null, 2)}
3613
3785
  `,
@@ -3620,7 +3792,7 @@ function shouldSyncSkillsForCliVersion(workdir, currentVersion) {
3620
3792
  if (cached === currentVersion) {
3621
3793
  return false;
3622
3794
  }
3623
- const stored = loadManifest2(workspaceApmDir(workdir));
3795
+ const stored = loadManifest3(workspaceApmDir(workdir));
3624
3796
  if (stored?.cliVersion === currentVersion) {
3625
3797
  syncedInSession.set(workdir, currentVersion);
3626
3798
  return false;
@@ -3628,7 +3800,7 @@ function shouldSyncSkillsForCliVersion(workdir, currentVersion) {
3628
3800
  return true;
3629
3801
  }
3630
3802
  function markSkillsSyncedForCliVersion(workdir, cliVersion) {
3631
- saveManifest2(workspaceApmDir(workdir), cliVersion);
3803
+ saveManifest3(workspaceApmDir(workdir), cliVersion);
3632
3804
  syncedInSession.set(workdir, cliVersion);
3633
3805
  }
3634
3806
 
@@ -3665,6 +3837,9 @@ function shouldCommitAfterWebIdeMessage(action) {
3665
3837
  function isStartLocalServicesAction(action) {
3666
3838
  return action === "enter-manual-test" || action === "skip-test";
3667
3839
  }
3840
+ function isDesignAction(action) {
3841
+ return action === "start-design" || action === "revise-design";
3842
+ }
3668
3843
  function isExecuteSqlAction(action) {
3669
3844
  return action === "execute-sql";
3670
3845
  }
@@ -3870,6 +4045,28 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
3870
4045
  },
3871
4046
  (names) => names.length > 0 ? `\u5DF2\u540C\u6B65 ${names.length} \u4E2A\u9644\u4EF6` : "\u65E0\u9644\u4EF6\u6216\u540C\u6B65\u8DF3\u8FC7"
3872
4047
  );
4048
+ await runPrepStep(
4049
+ "\u540C\u6B65\u8BBE\u8BA1\u4EA7\u7269",
4050
+ async () => {
4051
+ try {
4052
+ const artifacts = await api.cli.webideListDesignArtifacts({ taskId });
4053
+ const names = await syncWebIdeDesign(
4054
+ cfg,
4055
+ taskId,
4056
+ workdir,
4057
+ artifacts ?? []
4058
+ );
4059
+ return names;
4060
+ } catch (err) {
4061
+ console.warn(
4062
+ "[apm] WebIDE \u8BBE\u8BA1\u4EA7\u7269\u540C\u6B65\u5931\u8D25:",
4063
+ err instanceof Error ? err.message : err
4064
+ );
4065
+ return [];
4066
+ }
4067
+ },
4068
+ (names) => names.length > 0 ? `\u5DF2\u540C\u6B65 ${names.length} \u4E2A\u8BBE\u8BA1\u6587\u4EF6` : "\u65E0\u8BBE\u8BA1\u6587\u4EF6\u6216\u540C\u6B65\u8DF3\u8FC7"
4069
+ );
3873
4070
  eventSession.addCliStep(
3874
4071
  "\u542F\u52A8 Cursor Agent",
3875
4072
  "\u51C6\u5907 resume/create\u2026",
@@ -3877,10 +4074,19 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
3877
4074
  );
3878
4075
  await syncPrepLog();
3879
4076
  const startLocalServices = isStartLocalServicesAction(msg.action);
4077
+ const designAction = isDesignAction(msg.action);
3880
4078
  const executeSql = isExecuteSqlAction(msg.action);
3881
- const savedAgentId = startLocalServices ? void 0 : loadWebIdeAgentId(workdir, taskId);
4079
+ const savedAgentId = startLocalServices ? void 0 : designAction ? loadWebIdeDesignAgentId(workdir, taskId) : loadWebIdeAgentId(workdir, taskId);
3882
4080
  const promptPayload = executeSql ? parseWebIdePromptPayload(msg.content) : null;
3883
4081
  const sqlExecutionId = executeSql && typeof promptPayload?.executionId === "string" ? promptPayload.executionId.trim() : void 0;
4082
+ const persistAgentId = (agentId) => {
4083
+ if (startLocalServices) return;
4084
+ if (designAction) {
4085
+ saveWebIdeDesignAgentId(workdir, taskId, agentId);
4086
+ } else {
4087
+ saveWebIdeAgentId(workdir, taskId, agentId);
4088
+ }
4089
+ };
3884
4090
  const outcome = await runCursorAgent(
3885
4091
  cfg,
3886
4092
  {
@@ -3903,17 +4109,21 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
3903
4109
  signal
3904
4110
  }),
3905
4111
  enableAskQuestion: !startLocalServices && !executeSql,
3906
- enableWebIdePlanTools: !startLocalServices && !executeSql,
4112
+ enableWebIdePlanTools: !startLocalServices && !executeSql && !designAction,
3907
4113
  enablePtySessionMcp: startLocalServices,
3908
4114
  enableMysqlTools: executeSql,
3909
4115
  sqlExecutionId,
3910
4116
  enableSandbox: false,
3911
- onInvalidatePersistedAgentId: startLocalServices ? void 0 : () => clearWebIdeAgentId(workdir, taskId),
4117
+ onInvalidatePersistedAgentId: startLocalServices ? void 0 : () => {
4118
+ if (designAction) {
4119
+ clearWebIdeDesignAgentId(workdir, taskId);
4120
+ } else {
4121
+ clearWebIdeAgentId(workdir, taskId);
4122
+ }
4123
+ },
3912
4124
  taskId,
3913
4125
  createRemoteLogSync: (agentId) => {
3914
- if (!startLocalServices) {
3915
- saveWebIdeAgentId(workdir, taskId, agentId);
3916
- }
4126
+ persistAgentId(agentId);
3917
4127
  logSyncRef.current = createThrottledWebIdeMessageLogSync(
3918
4128
  cfg,
3919
4129
  { taskId, messageId, agentId },
@@ -3927,9 +4137,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
3927
4137
  return logSyncRef.current;
3928
4138
  },
3929
4139
  onRunStarted: async ({ agentId, runId }) => {
3930
- if (!startLocalServices) {
3931
- saveWebIdeAgentId(workdir, taskId, agentId);
3932
- }
4140
+ persistAgentId(agentId);
3933
4141
  eventSession.addCliStep(
3934
4142
  "\u542F\u52A8 Cursor Agent",
3935
4143
  `agentId=${agentId} runId=${runId}`,
@@ -3942,7 +4150,7 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
3942
4150
  }
3943
4151
  );
3944
4152
  if (!startLocalServices) {
3945
- saveWebIdeAgentId(workdir, taskId, outcome.agentId);
4153
+ persistAgentId(outcome.agentId);
3946
4154
  }
3947
4155
  const tokenUsage = outcome.usage != null ? {
3948
4156
  modelId: outcome.modelId ?? (msg.model?.trim() || void 0),
@@ -4028,6 +4236,30 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
4028
4236
  );
4029
4237
  }
4030
4238
  }
4239
+ if (isDesignAction(msg.action)) {
4240
+ if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
4241
+ try {
4242
+ const uploaded = await uploadWebIdeDesignArtifacts(
4243
+ cfg,
4244
+ taskId,
4245
+ workdir
4246
+ );
4247
+ console.log(
4248
+ `[apm] webide \u8BBE\u8BA1\u4EA7\u7269\u4E0A\u4F20 action=${msg.action} uploaded=${uploaded.uploaded} skipped=${uploaded.skipped} files=${uploaded.artifacts.map((a) => a.name).join(",")}`
4249
+ );
4250
+ } catch (err) {
4251
+ const detail = err instanceof Error ? err.message : String(err);
4252
+ await logSyncRef.current?.markRun(
4253
+ outcome.runId,
4254
+ "error",
4255
+ detail,
4256
+ tokenUsage
4257
+ );
4258
+ await setError(cfg, messageId, detail);
4259
+ syncLocalTaskStatus(workdir, taskId, msg, "FAILED");
4260
+ return;
4261
+ }
4262
+ }
4031
4263
  if (shouldCommitAfterWebIdeMessage(msg.action)) {
4032
4264
  if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
4033
4265
  const committed = await commitWorkspaceReposIfDirty(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "8.0.17",
3
+ "version": "8.0.18",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,