ai-project-manage-cli 8.1.7 → 8.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,10 @@ var requestConfig = {
14
14
  path: "/cli/me"
15
15
  }
16
16
  ),
17
+ webideAgentConfig: defineEndpoint({
18
+ method: "GET",
19
+ path: "/cli/webide/agent-config"
20
+ }),
17
21
  webideAppendMessageContent: defineEndpoint({
18
22
  method: "PUT",
19
23
  path: "/cli/webide/messages/content"
@@ -325,11 +329,8 @@ function requireRemoteWorkdir(workdir) {
325
329
  }
326
330
 
327
331
  // src/utils/workspace.ts
328
- import { copyFileSync, existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
329
- import { dirname, join as join2, resolve as resolve2 } from "path";
330
- import { fileURLToPath } from "url";
331
- var __dirname = dirname(fileURLToPath(import.meta.url));
332
- var CLI_TEMPLATE_DIR = resolve2(__dirname, "../template");
332
+ import { existsSync, mkdirSync as mkdirSync2, readdirSync, statSync } from "fs";
333
+ import { join as join2, resolve as resolve2 } from "path";
333
334
  function workspaceApmDir(cwd = resolveWorkdirPath()) {
334
335
  return resolve2(resolve2(cwd), ".apm");
335
336
  }
@@ -380,90 +381,6 @@ async function ensureWorkspaceApmDirForInit(cwd = resolveWorkdirPath()) {
380
381
  }
381
382
  mkdirSync2(fsDir, { recursive: true });
382
383
  }
383
- var WEBIDE_AGENTS_TEMPLATE_NAME = "AGENTS.webide.md";
384
- function shouldSkipTemplateEntry(name) {
385
- return name === ".DS_Store" || name === "Thumbs.db";
386
- }
387
- function isWebIdeRuleFileName(name) {
388
- return name.startsWith("webide");
389
- }
390
- function copyTemplateEntry(src, dest) {
391
- const fsSrc = toFsPath(src);
392
- const fsDest = toFsPath(dest);
393
- const st = statSync(fsSrc);
394
- if (st.isDirectory()) {
395
- mkdirSync2(fsDest, { recursive: true });
396
- for (const name of readdirSync(fsSrc)) {
397
- if (shouldSkipTemplateEntry(name)) continue;
398
- copyTemplateEntry(join2(src, name), join2(dest, name));
399
- }
400
- return;
401
- }
402
- if (!st.isFile()) return;
403
- mkdirSync2(toFsPath(dirname(dest)), { recursive: true });
404
- copyFileSync(fsSrc, fsDest);
405
- }
406
- function listWebIdeRuleFileNames(rulesDir) {
407
- const fsRulesDir = toFsPath(rulesDir);
408
- if (!existsSync(fsRulesDir) || !statSync(fsRulesDir).isDirectory()) {
409
- return [];
410
- }
411
- return readdirSync(fsRulesDir).filter((name) => {
412
- if (shouldSkipTemplateEntry(name) || !isWebIdeRuleFileName(name)) {
413
- return false;
414
- }
415
- return statSync(toFsPath(join2(rulesDir, name))).isFile();
416
- });
417
- }
418
- function assertWebIdeTemplateCopiedToApm(apmDir, workdir) {
419
- const required = ["AGENTS.md", "rules"];
420
- for (const item of required) {
421
- const path3 = join2(apmDir, item);
422
- if (!existsSync(toFsPath(path3))) {
423
- throw new Error(`[apm] WebIDE \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11: ${path3}`);
424
- }
425
- }
426
- const rulesDir = join2(apmDir, "rules");
427
- const ruleNames = listWebIdeRuleFileNames(rulesDir);
428
- if (ruleNames.length === 0) {
429
- throw new Error(`[apm] WebIDE \u521D\u59CB\u5316\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11 webide \u89C4\u5219: ${rulesDir}`);
430
- }
431
- const leakedRules = join2(workdir, "rules");
432
- const apmRules = join2(apmDir, "rules");
433
- if (existsSync(toFsPath(leakedRules)) && !existsSync(toFsPath(join2(apmRules, "webide_reply.md")))) {
434
- throw new Error(
435
- `[apm] \u6A21\u677F\u88AB\u590D\u5236\u5230\u9519\u8BEF\u4F4D\u7F6E: ${leakedRules}\uFF08\u5E94\u5728 ${apmRules}\uFF09`
436
- );
437
- }
438
- }
439
- async function copyWebIdeTemplateFiles(targetDir, workdir = resolveWorkdirPath()) {
440
- const resolvedTarget = resolve2(targetDir);
441
- const templateDir = resolve2(CLI_TEMPLATE_DIR);
442
- const fsTemplateDir = toFsPath(templateDir);
443
- if (!existsSync(fsTemplateDir) || !statSync(fsTemplateDir).isDirectory()) {
444
- throw new Error(`[apm] \u672A\u627E\u5230 CLI \u6A21\u677F\u76EE\u5F55: ${templateDir}`);
445
- }
446
- const agentsSrc = join2(templateDir, WEBIDE_AGENTS_TEMPLATE_NAME);
447
- if (!existsSync(toFsPath(agentsSrc))) {
448
- throw new Error(`[apm] \u672A\u627E\u5230 WebIDE \u6307\u5357: ${agentsSrc}`);
449
- }
450
- const rulesSrc = join2(templateDir, "rules");
451
- const ruleNames = listWebIdeRuleFileNames(rulesSrc);
452
- if (ruleNames.length === 0) {
453
- throw new Error(`[apm] CLI \u6A21\u677F\u4E2D\u6CA1\u6709 webide \u89C4\u5219: ${rulesSrc}`);
454
- }
455
- mkdirSync2(toFsPath(resolvedTarget), { recursive: true });
456
- copyFileSync(
457
- toFsPath(agentsSrc),
458
- toFsPath(join2(resolvedTarget, "AGENTS.md"))
459
- );
460
- const rulesDest = join2(resolvedTarget, "rules");
461
- mkdirSync2(toFsPath(rulesDest), { recursive: true });
462
- for (const name of ruleNames) {
463
- copyTemplateEntry(join2(rulesSrc, name), join2(rulesDest, name));
464
- }
465
- assertWebIdeTemplateCopiedToApm(resolvedTarget, resolve2(workdir));
466
- }
467
384
 
468
385
  // src/utils/git.ts
469
386
  import { execFile as execFile2 } from "child_process";
@@ -664,7 +581,7 @@ import {
664
581
  statSync as statSync2,
665
582
  writeFileSync as writeFileSync2
666
583
  } from "fs";
667
- import { basename, dirname as dirname2, join as join3, relative, resolve as resolve3 } from "path";
584
+ import { basename, dirname, join as join3, relative, resolve as resolve3 } from "path";
668
585
  var WORKSPACE_REPOS_MANIFEST = "workspace-repos.json";
669
586
  var WORKSPACE_REPOS_VERSION = 1;
670
587
  var SKIP_DIR_NAMES = /* @__PURE__ */ new Set([".apm", "node_modules"]);
@@ -3220,14 +3137,75 @@ function createThrottledWebIdeMessageLogSync(cfg2, ctx, onError, options) {
3220
3137
  };
3221
3138
  }
3222
3139
 
3223
- // src/commands/init.ts
3224
- async function initializeWorkspace(workdir) {
3225
- await ensureWorkspaceApmDirForInit(workdir);
3140
+ // src/commands/sync-webide-agent.ts
3141
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
3142
+ import { join as join4 } from "path";
3143
+ var REVISION_FILE = ".webide-agent.json";
3144
+ var RULE_KEY = /^webide_[a-z0-9_]+$/;
3145
+ function withTrailingNewline(text) {
3146
+ return text.endsWith("\n") ? text : `${text}
3147
+ `;
3148
+ }
3149
+ function readRevision(apmDir) {
3150
+ const path3 = toFsPath(join4(apmDir, REVISION_FILE));
3151
+ if (!existsSync5(path3)) return null;
3152
+ try {
3153
+ const parsed = JSON.parse(readFileSync4(path3, "utf8"));
3154
+ if (parsed?.version === 1 && parsed.revision?.trim()) {
3155
+ return parsed.revision.trim();
3156
+ }
3157
+ } catch {
3158
+ return null;
3159
+ }
3160
+ return null;
3161
+ }
3162
+ function writeRevision(apmDir, revision) {
3163
+ writeFileSync3(
3164
+ toFsPath(join4(apmDir, REVISION_FILE)),
3165
+ `${JSON.stringify({ version: 1, revision }, null, 2)}
3166
+ `,
3167
+ "utf8"
3168
+ );
3169
+ }
3170
+ async function syncWebIdeAgentFiles(workdir, cfg2) {
3171
+ const api = createApmApiClient(cfg2);
3172
+ const bundle = await api.cli.webideAgentConfig();
3173
+ const revision = bundle.revision?.trim();
3174
+ if (!revision) {
3175
+ throw new Error("[apm] \u5E73\u53F0\u672A\u8FD4\u56DE WebIDE \u89C4\u5219\u7248\u672C");
3176
+ }
3226
3177
  const apmDir = workspaceApmDir(workdir);
3227
- await copyWebIdeTemplateFiles(apmDir, workdir);
3228
- console.log(`[apm] \u5DF2\u6309 WebIDE \u521D\u59CB\u5316\u5DE5\u4F5C\u533A\uFF1A${apmDir}`);
3229
- return { didInit: true };
3178
+ mkdirSync4(toFsPath(apmDir), { recursive: true });
3179
+ if (readRevision(apmDir) === revision) {
3180
+ return { revision, wrote: false, ruleCount: bundle.rules?.length ?? 0 };
3181
+ }
3182
+ const rulesDir = join4(apmDir, "rules");
3183
+ mkdirSync4(toFsPath(rulesDir), { recursive: true });
3184
+ writeFileSync3(
3185
+ toFsPath(join4(apmDir, "AGENTS.md")),
3186
+ withTrailingNewline(bundle.guide ?? ""),
3187
+ "utf8"
3188
+ );
3189
+ for (const rule of bundle.rules ?? []) {
3190
+ const key = rule.key?.trim() ?? "";
3191
+ if (!RULE_KEY.test(key)) {
3192
+ throw new Error(`[apm] \u975E\u6CD5\u89C4\u5219\u540D: ${key || "(\u7A7A)"}`);
3193
+ }
3194
+ writeFileSync3(
3195
+ toFsPath(join4(rulesDir, `${key}.md`)),
3196
+ withTrailingNewline(rule.body ?? ""),
3197
+ "utf8"
3198
+ );
3199
+ }
3200
+ writeRevision(apmDir, revision);
3201
+ return {
3202
+ revision,
3203
+ wrote: true,
3204
+ ruleCount: bundle.rules?.length ?? 0
3205
+ };
3230
3206
  }
3207
+
3208
+ // src/commands/init.ts
3231
3209
  async function ensureWorkspaceInitialized(workdir) {
3232
3210
  if (isWorkspaceApmInitialized(workdir)) {
3233
3211
  return { didInit: false };
@@ -3235,19 +3213,21 @@ async function ensureWorkspaceInitialized(workdir) {
3235
3213
  console.log(
3236
3214
  `[apm] \u5DE5\u4F5C\u76EE\u5F55 ${workdir} \u672A\u68C0\u6D4B\u5230\u5DF2\u521D\u59CB\u5316\u7684 .apm\uFF0C\u6B63\u5728\u6309 WebIDE \u81EA\u52A8\u521D\u59CB\u5316\u2026`
3237
3215
  );
3238
- return initializeWorkspace(workdir);
3216
+ await ensureWorkspaceApmDirForInit(workdir);
3217
+ console.log(`[apm] \u5DF2\u521B\u5EFA\u5DE5\u4F5C\u533A\u76EE\u5F55\uFF1A${workspaceApmDir(workdir)}`);
3218
+ return { didInit: true };
3239
3219
  }
3240
3220
 
3241
3221
  // src/utils/project-documents.ts
3242
3222
  import {
3243
- existsSync as existsSync5,
3223
+ existsSync as existsSync6,
3244
3224
  readdirSync as readdirSync3,
3245
- readFileSync as readFileSync4,
3225
+ readFileSync as readFileSync5,
3246
3226
  rmSync,
3247
- writeFileSync as writeFileSync3
3227
+ writeFileSync as writeFileSync4
3248
3228
  } from "fs";
3249
3229
  import { createHash as createHash2 } from "crypto";
3250
- import { dirname as dirname3, join as join4, relative as relative4, sep } from "path";
3230
+ import { dirname as dirname2, join as join5, relative as relative4, sep } from "path";
3251
3231
  var MANIFEST_FILE = "manifest.json";
3252
3232
  function normalizeProjectIdForPath(projectId) {
3253
3233
  const id = projectId.trim();
@@ -3261,11 +3241,11 @@ function normalizeProjectIdForPath(projectId) {
3261
3241
  }
3262
3242
  function projectDocumentsDir(apmRoot, projectId) {
3263
3243
  const id = normalizeProjectIdForPath(projectId);
3264
- return join4(apmRoot ?? workspaceApmDir(), "project", id);
3244
+ return join5(apmRoot ?? workspaceApmDir(), "project", id);
3265
3245
  }
3266
3246
  function projectDocumentLocalPath(apmRoot, projectId, documentPath) {
3267
3247
  const normalized = normalizeLocalDocumentPath(documentPath);
3268
- return join4(
3248
+ return join5(
3269
3249
  projectDocumentsDir(apmRoot, projectId),
3270
3250
  ...normalized.split("/")
3271
3251
  );
@@ -3285,16 +3265,16 @@ function hashLocalFileContent(content) {
3285
3265
  return createHash2("sha256").update(content, "utf8").digest("hex");
3286
3266
  }
3287
3267
  function readLocalManifest(apmRoot, projectId) {
3288
- const manifestPath3 = join4(
3268
+ const manifestPath2 = join5(
3289
3269
  projectDocumentsDir(apmRoot, projectId),
3290
3270
  MANIFEST_FILE
3291
3271
  );
3292
- if (!existsSync5(manifestPath3)) {
3272
+ if (!existsSync6(manifestPath2)) {
3293
3273
  return null;
3294
3274
  }
3295
3275
  try {
3296
3276
  return JSON.parse(
3297
- readFileSync4(manifestPath3, "utf8")
3277
+ readFileSync5(manifestPath2, "utf8")
3298
3278
  );
3299
3279
  } catch {
3300
3280
  return null;
@@ -3302,13 +3282,13 @@ function readLocalManifest(apmRoot, projectId) {
3302
3282
  }
3303
3283
  function listLocalDocumentPaths(apmRoot, projectId) {
3304
3284
  const root = projectDocumentsDir(apmRoot, projectId);
3305
- if (!existsSync5(root)) {
3285
+ if (!existsSync6(root)) {
3306
3286
  return [];
3307
3287
  }
3308
3288
  const paths = [];
3309
3289
  const walk = (dir) => {
3310
3290
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
3311
- const abs = join4(dir, entry.name);
3291
+ const abs = join5(dir, entry.name);
3312
3292
  if (entry.isDirectory()) {
3313
3293
  walk(abs);
3314
3294
  continue;
@@ -3427,8 +3407,8 @@ ${diagnostic ?? ""}`);
3427
3407
  const absPath = toFsPath(
3428
3408
  projectDocumentLocalPath(targetApmDir, projectId, doc.path)
3429
3409
  );
3430
- await ensureDirExists(dirname3(absPath));
3431
- writeFileSync3(absPath, doc.content, "utf8");
3410
+ await ensureDirExists(dirname2(absPath));
3411
+ writeFileSync4(absPath, doc.content, "utf8");
3432
3412
  downloaded += 1;
3433
3413
  }
3434
3414
  }
@@ -3437,13 +3417,13 @@ ${diagnostic ?? ""}`);
3437
3417
  const absPath = toFsPath(
3438
3418
  projectDocumentLocalPath(targetApmDir, projectId, path3)
3439
3419
  );
3440
- if (existsSync5(absPath)) {
3420
+ if (existsSync6(absPath)) {
3441
3421
  rmSync(absPath, { force: true });
3442
3422
  deleted += 1;
3443
3423
  }
3444
3424
  }
3445
- writeFileSync3(
3446
- toFsPath(join4(docsDir, MANIFEST_FILE)),
3425
+ writeFileSync4(
3426
+ toFsPath(join5(docsDir, MANIFEST_FILE)),
3447
3427
  `${JSON.stringify(remoteManifest, null, 2)}
3448
3428
  `,
3449
3429
  "utf8"
@@ -3486,7 +3466,7 @@ async function syncProjectDocumentsPush(cfg2, workdirPath, apmRoot, options) {
3486
3466
  const absPath = toFsPath(
3487
3467
  projectDocumentLocalPath(targetApmDir, projectId, path3)
3488
3468
  );
3489
- const content = readFileSync4(absPath, "utf8");
3469
+ const content = readFileSync5(absPath, "utf8");
3490
3470
  const contentHash = hashLocalFileContent(content);
3491
3471
  if (remoteHashByPath.get(path3) === contentHash) {
3492
3472
  continue;
@@ -3506,71 +3486,6 @@ async function syncProjectDocumentsPush(cfg2, workdirPath, apmRoot, options) {
3506
3486
  return synced;
3507
3487
  }
3508
3488
 
3509
- // src/version.ts
3510
- import { readFileSync as readFileSync5 } from "fs";
3511
- import { dirname as dirname4, join as join5 } from "path";
3512
- import { fileURLToPath as fileURLToPath2 } from "url";
3513
- function readCliVersion() {
3514
- try {
3515
- const dir = dirname4(fileURLToPath2(import.meta.url));
3516
- const pkgPath = join5(dir, "..", "package.json");
3517
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
3518
- return pkg.version ?? "0.0.0";
3519
- } catch {
3520
- return "0.0.0";
3521
- }
3522
- }
3523
-
3524
- // src/commands/connect/cli-version-sync.ts
3525
- import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
3526
- import { join as join6 } from "path";
3527
- var CLI_VERSION_FILE = ".cli-version.json";
3528
- function manifestPath2(apmDir) {
3529
- return join6(apmDir, CLI_VERSION_FILE);
3530
- }
3531
- function loadManifest(apmDir) {
3532
- const path3 = toFsPath(manifestPath2(apmDir));
3533
- if (!existsSync6(path3)) {
3534
- return null;
3535
- }
3536
- try {
3537
- const parsed = JSON.parse(
3538
- readFileSync6(path3, "utf8")
3539
- );
3540
- if (parsed?.version === 1 && typeof parsed.cliVersion === "string" && parsed.cliVersion.trim()) {
3541
- return parsed;
3542
- }
3543
- } catch {
3544
- }
3545
- return null;
3546
- }
3547
- function saveManifest(apmDir, cliVersion) {
3548
- const manifest = { version: 1, cliVersion };
3549
- writeFileSync4(
3550
- toFsPath(manifestPath2(apmDir)),
3551
- `${JSON.stringify(manifest, null, 2)}
3552
- `,
3553
- "utf8"
3554
- );
3555
- }
3556
- var syncedInSession = /* @__PURE__ */ new Map();
3557
- function shouldSyncSkillsForCliVersion(workdir, currentVersion) {
3558
- const cached = syncedInSession.get(workdir);
3559
- if (cached === currentVersion) {
3560
- return false;
3561
- }
3562
- const stored = loadManifest(workspaceApmDir(workdir));
3563
- if (stored?.cliVersion === currentVersion) {
3564
- syncedInSession.set(workdir, currentVersion);
3565
- return false;
3566
- }
3567
- return true;
3568
- }
3569
- function markSkillsSyncedForCliVersion(workdir, cliVersion) {
3570
- saveManifest(workspaceApmDir(workdir), cliVersion);
3571
- syncedInSession.set(workdir, cliVersion);
3572
- }
3573
-
3574
3489
  // src/commands/connect/upload-package-artifact.ts
3575
3490
  import fs2 from "node:fs";
3576
3491
  import path2 from "node:path";
@@ -3690,26 +3605,12 @@ async function handleWebIdePackage(cfg2, msg2, signal) {
3690
3605
  },
3691
3606
  (didInit) => didInit ? "\u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A" : "\u5DE5\u4F5C\u533A\u5DF2\u5C31\u7EEA"
3692
3607
  );
3693
- const cliVersion = readCliVersion();
3694
- if (shouldSyncSkillsForCliVersion(workdir, cliVersion)) {
3695
- if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
3696
- await runPrepStep(
3697
- "\u540C\u6B65 WebIDE \u89C4\u5219",
3698
- async () => {
3699
- await copyWebIdeTemplateFiles(workspaceApmDir(workdir), workdir);
3700
- markSkillsSyncedForCliVersion(workdir, cliVersion);
3701
- return cliVersion;
3702
- },
3703
- (version) => `\u5DF2\u540C\u6B65\u81F3 CLI ${version}`
3704
- );
3705
- } else {
3706
- eventSession.addCliStep(
3707
- "\u540C\u6B65 WebIDE \u89C4\u5219",
3708
- `\u7248\u672C\u4E00\u81F4\uFF08${cliVersion}\uFF09\uFF0C\u8DF3\u8FC7`,
3709
- "skip"
3710
- );
3711
- await syncPrepLog();
3712
- }
3608
+ if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
3609
+ await runPrepStep(
3610
+ "\u540C\u6B65 WebIDE \u89C4\u5219",
3611
+ async () => syncWebIdeAgentFiles(workdir, cfg2),
3612
+ (result) => result.wrote ? `\u5DF2\u5199\u5165 ${result.ruleCount} \u6761\u89C4\u5219` : "\u89C4\u5219\u672A\u53D8\u5316\uFF0C\u8DF3\u8FC7"
3613
+ );
3713
3614
  await runPrepStep(
3714
3615
  "\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355",
3715
3616
  async () => {
@@ -3938,6 +3839,7 @@ async function handleStartProject(cfg2, msg2, signal) {
3938
3839
  try {
3939
3840
  if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
3940
3841
  await ensureWorkspaceInitialized(workdir);
3842
+ await syncWebIdeAgentFiles(workdir, cfg2);
3941
3843
  const api = createApmApiClient(cfg2);
3942
3844
  const outcome = await runCursorAgent(
3943
3845
  cfg2,
@@ -4049,8 +3951,8 @@ async function handleStartProject(cfg2, msg2, signal) {
4049
3951
  }
4050
3952
 
4051
3953
  // src/commands/connect/webide-agent-registry.ts
4052
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
4053
- import { dirname as dirname5, resolve as resolve6 } from "node:path";
3954
+ import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
3955
+ import { dirname as dirname3, resolve as resolve6 } from "node:path";
4054
3956
  function registryPath(workdir, taskId, fileName = "cursor-agent.json") {
4055
3957
  return resolve6(workdir, ".apm", "webide", taskId, fileName);
4056
3958
  }
@@ -4060,7 +3962,7 @@ function readRegistry(path3) {
4060
3962
  return {};
4061
3963
  }
4062
3964
  try {
4063
- const parsed = JSON.parse(readFileSync7(path3, "utf8"));
3965
+ const parsed = JSON.parse(readFileSync6(path3, "utf8"));
4064
3966
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4065
3967
  const raw = parsed;
4066
3968
  const state = {};
@@ -4089,7 +3991,7 @@ function readRegistry(path3) {
4089
3991
  return {};
4090
3992
  }
4091
3993
  function writeRegistry(path3, registry) {
4092
- mkdirSync4(dirname5(path3), { recursive: true });
3994
+ mkdirSync5(dirname3(path3), { recursive: true });
4093
3995
  writeFileSync5(path3, `${JSON.stringify(registry, null, 2)}
4094
3996
  `, "utf8");
4095
3997
  }
@@ -4541,8 +4443,8 @@ async function ensureWebIdePullRequests(cfg2, taskId, workdir) {
4541
4443
  }
4542
4444
 
4543
4445
  // src/commands/sync-webide-attachments.ts
4544
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
4545
- import { join as join7 } from "path";
4446
+ import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
4447
+ import { join as join6 } from "path";
4546
4448
  var MANIFEST_FILE2 = ".sync-manifest.json";
4547
4449
  async function downloadAttachment(cfg2, attachmentId) {
4548
4450
  const base = cfg2.baseUrl.trim().replace(/\/+$/, "");
@@ -4557,14 +4459,14 @@ async function downloadAttachment(cfg2, attachmentId) {
4557
4459
  }
4558
4460
  return Buffer.from(await res.arrayBuffer());
4559
4461
  }
4560
- function loadManifest2(dir) {
4561
- const path3 = join7(dir, MANIFEST_FILE2);
4462
+ function loadManifest(dir) {
4463
+ const path3 = join6(dir, MANIFEST_FILE2);
4562
4464
  if (!existsSync9(path3)) {
4563
4465
  return { version: 1, attachments: {} };
4564
4466
  }
4565
4467
  try {
4566
4468
  const parsed = JSON.parse(
4567
- readFileSync8(path3, "utf8")
4469
+ readFileSync7(path3, "utf8")
4568
4470
  );
4569
4471
  if (parsed?.version === 1 && parsed.attachments && typeof parsed.attachments === "object") {
4570
4472
  return parsed;
@@ -4573,9 +4475,9 @@ function loadManifest2(dir) {
4573
4475
  }
4574
4476
  return { version: 1, attachments: {} };
4575
4477
  }
4576
- function saveManifest2(dir, manifest) {
4478
+ function saveManifest(dir, manifest) {
4577
4479
  writeFileSync6(
4578
- join7(dir, MANIFEST_FILE2),
4480
+ join6(dir, MANIFEST_FILE2),
4579
4481
  `${JSON.stringify(manifest, null, 2)}
4580
4482
  `,
4581
4483
  "utf8"
@@ -4590,14 +4492,14 @@ function isAttachmentUpToDate(entry, item, dest) {
4590
4492
  async function syncAttachmentsToDirectory(cfg2, attachments, dir, logLabel) {
4591
4493
  await ensureDirExists(dir);
4592
4494
  if (attachments.length === 0) {
4593
- saveManifest2(dir, { version: 1, attachments: {} });
4495
+ saveManifest(dir, { version: 1, attachments: {} });
4594
4496
  return [];
4595
4497
  }
4596
- const manifest = loadManifest2(dir);
4498
+ const manifest = loadManifest(dir);
4597
4499
  const nextManifest = { version: 1, attachments: {} };
4598
4500
  const names = [];
4599
4501
  for (const item of attachments) {
4600
- const dest = join7(dir, item.name);
4502
+ const dest = join6(dir, item.name);
4601
4503
  const entry = manifest.attachments[item.id];
4602
4504
  const createdAt = item.createdAt ?? "";
4603
4505
  names.push(item.name);
@@ -4614,7 +4516,7 @@ async function syncAttachmentsToDirectory(cfg2, attachments, dir, logLabel) {
4614
4516
  };
4615
4517
  console.log(`[apm] \u5DF2\u4E0B\u8F7D\u9644\u4EF6: ${logLabel}/${item.name}`);
4616
4518
  }
4617
- saveManifest2(dir, nextManifest);
4519
+ saveManifest(dir, nextManifest);
4618
4520
  return names;
4619
4521
  }
4620
4522
  async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
@@ -4629,19 +4531,34 @@ async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
4629
4531
 
4630
4532
  // src/commands/sync-webide-design.ts
4631
4533
  import { createHash as createHash3 } from "crypto";
4632
- import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
4633
- import { join as join8 } from "path";
4534
+ import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
4535
+ import { join as join7 } from "path";
4536
+
4537
+ // src/opc-shared-types.ts
4538
+ function webIdeDesignObjectKey(taskId, fileName) {
4539
+ const safe = fileName.replace(/[/\\:*?"<>|]/g, "_").trim() || "index.html";
4540
+ return `tasks/${taskId.trim()}/design/${safe}`;
4541
+ }
4542
+ function isWebIdeDesignArtifactName(name) {
4543
+ const lower = name.trim().toLowerCase();
4544
+ return lower.endsWith(".html") || lower.endsWith(".css");
4545
+ }
4546
+ function webIdeDesignArtifactContentType(name) {
4547
+ return name.trim().toLowerCase().endsWith(".css") ? "text/css; charset=utf-8" : "text/html; charset=utf-8";
4548
+ }
4549
+
4550
+ // src/commands/sync-webide-design.ts
4634
4551
  var MANIFEST_FILE3 = ".sync-manifest.json";
4635
4552
  function hashBuffer(buf) {
4636
4553
  return createHash3("sha256").update(buf).digest("hex");
4637
4554
  }
4638
- function loadManifest3(dir) {
4639
- const path3 = join8(dir, MANIFEST_FILE3);
4555
+ function loadManifest2(dir) {
4556
+ const path3 = join7(dir, MANIFEST_FILE3);
4640
4557
  if (!existsSync10(path3)) {
4641
4558
  return { version: 1, files: {} };
4642
4559
  }
4643
4560
  try {
4644
- const parsed = JSON.parse(readFileSync9(path3, "utf8"));
4561
+ const parsed = JSON.parse(readFileSync8(path3, "utf8"));
4645
4562
  if (parsed?.version === 1 && parsed.files && typeof parsed.files === "object") {
4646
4563
  return parsed;
4647
4564
  }
@@ -4649,9 +4566,9 @@ function loadManifest3(dir) {
4649
4566
  }
4650
4567
  return { version: 1, files: {} };
4651
4568
  }
4652
- function saveManifest3(dir, manifest) {
4569
+ function saveManifest2(dir, manifest) {
4653
4570
  writeFileSync7(
4654
- join8(dir, MANIFEST_FILE3),
4571
+ join7(dir, MANIFEST_FILE3),
4655
4572
  `${JSON.stringify(manifest, null, 2)}
4656
4573
  `,
4657
4574
  "utf8"
@@ -4674,12 +4591,12 @@ async function downloadDesignFile(cfg2, taskId, name) {
4674
4591
  async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
4675
4592
  const dir = webideDesignDir(taskId, workdir);
4676
4593
  await ensureDirExists(dir);
4677
- const manifest = loadManifest3(dir);
4594
+ const manifest = loadManifest2(dir);
4678
4595
  const synced = [];
4679
4596
  for (const art of artifacts) {
4680
4597
  const name = art.name?.trim();
4681
- if (!name || !name.toLowerCase().endsWith(".html")) continue;
4682
- const localPath = join8(dir, name);
4598
+ if (!name || !isWebIdeDesignArtifactName(name)) continue;
4599
+ const localPath = join7(dir, name);
4683
4600
  const entry = manifest.files[name];
4684
4601
  if (entry?.contentHash === art.contentHash && existsSync10(localPath)) {
4685
4602
  continue;
@@ -4689,42 +4606,35 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
4689
4606
  manifest.files[name] = { contentHash: hashBuffer(buf) };
4690
4607
  synced.push(name);
4691
4608
  }
4692
- saveManifest3(dir, manifest);
4609
+ saveManifest2(dir, manifest);
4693
4610
  return synced;
4694
4611
  }
4695
- function listLocalDesignHtmlFiles(taskId, workdir) {
4612
+ function listLocalDesignArtifactFiles(taskId, workdir) {
4696
4613
  const dir = webideDesignDir(taskId, workdir);
4697
4614
  if (!existsSync10(dir)) return [];
4698
4615
  const out = [];
4699
4616
  for (const name of readdirSync4(dir)) {
4700
- if (!name.toLowerCase().endsWith(".html")) continue;
4701
- const absPath = join8(dir, name);
4702
- const buf = readFileSync9(absPath);
4617
+ if (!isWebIdeDesignArtifactName(name)) continue;
4618
+ const absPath = join7(dir, name);
4619
+ if (!statSync5(absPath).isFile()) continue;
4620
+ const buf = readFileSync8(absPath);
4703
4621
  if (buf.length === 0) continue;
4704
4622
  out.push({ name, absPath, contentHash: hashBuffer(buf) });
4705
4623
  }
4706
4624
  return out;
4707
4625
  }
4708
4626
 
4709
- // src/opc-shared-types.ts
4710
- function webIdeDesignObjectKey(taskId, fileName) {
4711
- const safe = fileName.replace(/[/\\:*?"<>|]/g, "_").trim() || "index.html";
4712
- return `tasks/${taskId.trim()}/design/${safe}`;
4713
- }
4714
-
4715
4627
  // src/commands/connect/upload-webide-design.ts
4716
4628
  async function uploadWebIdeDesignArtifacts(cfg2, taskId, workdir) {
4717
- const locals = listLocalDesignHtmlFiles(taskId, workdir);
4718
- if (locals.length === 0) {
4629
+ const locals = listLocalDesignArtifactFiles(taskId, workdir);
4630
+ if (!locals.some((file) => file.name.toLowerCase().endsWith(".html"))) {
4719
4631
  throw new Error(
4720
4632
  `\u8BBE\u8BA1\u76EE\u5F55\u65E0 HTML \u4EA7\u7269\uFF1A.apm/webide/${taskId}/design/\uFF08\u8BF7\u5199\u5165\u81F3\u5C11\u4E00\u4EFD .html\uFF09`
4721
4633
  );
4722
4634
  }
4723
4635
  const api = createApmApiClient(cfg2);
4724
4636
  const remote = await api.cli.webideListDesignArtifacts({ taskId }) ?? [];
4725
- const remoteByName = new Map(
4726
- remote.map((r) => [r.name, r])
4727
- );
4637
+ const remoteByName = new Map(remote.map((r) => [r.name, r]));
4728
4638
  const { client, bucket } = await createApmLogMinioClient(cfg2);
4729
4639
  await client.ensureBucket(bucket);
4730
4640
  let uploaded = 0;
@@ -4743,7 +4653,7 @@ async function uploadWebIdeDesignArtifacts(cfg2, taskId, workdir) {
4743
4653
  continue;
4744
4654
  }
4745
4655
  await client.fPutObject(bucket, objectKey, file.absPath, {
4746
- "Content-Type": "text/html; charset=utf-8"
4656
+ "Content-Type": webIdeDesignArtifactContentType(file.name)
4747
4657
  });
4748
4658
  uploaded += 1;
4749
4659
  artifacts.push({
@@ -4982,26 +4892,12 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
4982
4892
  },
4983
4893
  (didInit) => didInit ? "\u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A" : "\u5DE5\u4F5C\u533A\u5DF2\u5C31\u7EEA"
4984
4894
  );
4985
- const cliVersion = readCliVersion();
4986
- if (shouldSyncSkillsForCliVersion(workdir, cliVersion)) {
4987
- if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
4988
- await runPrepStep(
4989
- "\u540C\u6B65 WebIDE \u89C4\u5219",
4990
- async () => {
4991
- await copyWebIdeTemplateFiles(workspaceApmDir(workdir), workdir);
4992
- markSkillsSyncedForCliVersion(workdir, cliVersion);
4993
- return cliVersion;
4994
- },
4995
- (version) => `\u5DF2\u540C\u6B65\u81F3 CLI ${version}`
4996
- );
4997
- } else {
4998
- eventSession.addCliStep(
4999
- "\u540C\u6B65 WebIDE \u89C4\u5219",
5000
- `\u7248\u672C\u4E00\u81F4\uFF08${cliVersion}\uFF09\uFF0C\u8DF3\u8FC7`,
5001
- "skip"
5002
- );
5003
- await syncPrepLog();
5004
- }
4895
+ if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
4896
+ await runPrepStep(
4897
+ "\u540C\u6B65 WebIDE \u89C4\u5219",
4898
+ async () => syncWebIdeAgentFiles(workdir, cfg2),
4899
+ (result) => result.wrote ? `\u5DF2\u5199\u5165 ${result.ruleCount} \u6761\u89C4\u5219` : "\u89C4\u5219\u672A\u53D8\u5316\uFF0C\u8DF3\u8FC7"
4900
+ );
5005
4901
  await runPrepStep(
5006
4902
  "\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355",
5007
4903
  async () => {