ai-project-manage-cli 8.1.7 → 8.1.8

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,19 @@ 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, writeFileSync as writeFileSync7 } from "fs";
4535
+ import { join as join7 } from "path";
4634
4536
  var MANIFEST_FILE3 = ".sync-manifest.json";
4635
4537
  function hashBuffer(buf) {
4636
4538
  return createHash3("sha256").update(buf).digest("hex");
4637
4539
  }
4638
- function loadManifest3(dir) {
4639
- const path3 = join8(dir, MANIFEST_FILE3);
4540
+ function loadManifest2(dir) {
4541
+ const path3 = join7(dir, MANIFEST_FILE3);
4640
4542
  if (!existsSync10(path3)) {
4641
4543
  return { version: 1, files: {} };
4642
4544
  }
4643
4545
  try {
4644
- const parsed = JSON.parse(readFileSync9(path3, "utf8"));
4546
+ const parsed = JSON.parse(readFileSync8(path3, "utf8"));
4645
4547
  if (parsed?.version === 1 && parsed.files && typeof parsed.files === "object") {
4646
4548
  return parsed;
4647
4549
  }
@@ -4649,9 +4551,9 @@ function loadManifest3(dir) {
4649
4551
  }
4650
4552
  return { version: 1, files: {} };
4651
4553
  }
4652
- function saveManifest3(dir, manifest) {
4554
+ function saveManifest2(dir, manifest) {
4653
4555
  writeFileSync7(
4654
- join8(dir, MANIFEST_FILE3),
4556
+ join7(dir, MANIFEST_FILE3),
4655
4557
  `${JSON.stringify(manifest, null, 2)}
4656
4558
  `,
4657
4559
  "utf8"
@@ -4674,12 +4576,12 @@ async function downloadDesignFile(cfg2, taskId, name) {
4674
4576
  async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
4675
4577
  const dir = webideDesignDir(taskId, workdir);
4676
4578
  await ensureDirExists(dir);
4677
- const manifest = loadManifest3(dir);
4579
+ const manifest = loadManifest2(dir);
4678
4580
  const synced = [];
4679
4581
  for (const art of artifacts) {
4680
4582
  const name = art.name?.trim();
4681
4583
  if (!name || !name.toLowerCase().endsWith(".html")) continue;
4682
- const localPath = join8(dir, name);
4584
+ const localPath = join7(dir, name);
4683
4585
  const entry = manifest.files[name];
4684
4586
  if (entry?.contentHash === art.contentHash && existsSync10(localPath)) {
4685
4587
  continue;
@@ -4689,7 +4591,7 @@ async function syncWebIdeDesign(cfg2, taskId, workdir, artifacts) {
4689
4591
  manifest.files[name] = { contentHash: hashBuffer(buf) };
4690
4592
  synced.push(name);
4691
4593
  }
4692
- saveManifest3(dir, manifest);
4594
+ saveManifest2(dir, manifest);
4693
4595
  return synced;
4694
4596
  }
4695
4597
  function listLocalDesignHtmlFiles(taskId, workdir) {
@@ -4698,8 +4600,8 @@ function listLocalDesignHtmlFiles(taskId, workdir) {
4698
4600
  const out = [];
4699
4601
  for (const name of readdirSync4(dir)) {
4700
4602
  if (!name.toLowerCase().endsWith(".html")) continue;
4701
- const absPath = join8(dir, name);
4702
- const buf = readFileSync9(absPath);
4603
+ const absPath = join7(dir, name);
4604
+ const buf = readFileSync8(absPath);
4703
4605
  if (buf.length === 0) continue;
4704
4606
  out.push({ name, absPath, contentHash: hashBuffer(buf) });
4705
4607
  }
@@ -4982,26 +4884,12 @@ async function handleWebIdeInboundMessage(cfg2, msg2, signal) {
4982
4884
  },
4983
4885
  (didInit) => didInit ? "\u5DF2\u521D\u59CB\u5316\u5DE5\u4F5C\u533A" : "\u5DE5\u4F5C\u533A\u5DF2\u5C31\u7EEA"
4984
4886
  );
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
- }
4887
+ if (signal.aborted) throw new Error("\u4EFB\u52A1\u5DF2\u53D6\u6D88");
4888
+ await runPrepStep(
4889
+ "\u540C\u6B65 WebIDE \u89C4\u5219",
4890
+ async () => syncWebIdeAgentFiles(workdir, cfg2),
4891
+ (result) => result.wrote ? `\u5DF2\u5199\u5165 ${result.ruleCount} \u6761\u89C4\u5219` : "\u89C4\u5219\u672A\u53D8\u5316\uFF0C\u8DF3\u8FC7"
4892
+ );
5005
4893
  await runPrepStep(
5006
4894
  "\u5DE5\u4F5C\u533A\u4ED3\u5E93\u6E05\u5355",
5007
4895
  async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "8.1.7",
3
+ "version": "8.1.8",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -1,28 +0,0 @@
1
- ## WebIDE 指南
2
-
3
- 你正在 WebIDE 工作区中处理任务。本轮要做什么以 prompt 里的 `action` 为准;先 Read 本文件和对应规则,再动手。
4
-
5
- ### 工作原则
6
-
7
- 1. **用户可见内容只走 `AppendMessage`**:进展、评估、改动说明、错误原因、下一步等,一律用 `AppendMessage` 写入(可多次追加)。细则见 `.apm/rules/webide_reply.md`。
8
- 2. **最终自然语言收尾极简**:最多 1 句状态确认(如「本轮已完成」)。禁止复述、扩写或总结 `AppendMessage` 已写内容。
9
- 3. **按本轮 `action` 执行**:不要自行跳阶段;未接到开发指令时不要改代码、不要写计划文档。
10
- 4. 文件读写、搜索与 Shell 必须限制在当前工作区 cwd 内。
11
-
12
- ### 规则(`.apm/rules/`,按需 Read,不要一次读完)
13
-
14
- - `webide_reply.md`:输出通道(每轮必守)
15
- - `webide_git_commit.md`:开发 / 修码时的 Git 提交与 push
16
- - `webide_sql_change.md`:有表结构或 SQL 变更时,须在 `AppendMessage` 中醒目提示
17
- - `webide_sql_execute.md`:execute-sql 轮次连库执行 SQL 时 Read
18
- - `webide_terminal.md`:长驻进程禁止用 Shell;本地服务由顶栏「启动项目」触发,开发任务不要自行起服务
19
- - `webide_testcase.md`:生成测试用例并调用 `UpsertWebIdeTestCases`
20
- - `webide_merge.md`:验收通过后先 `UpsertWebIdeChecklist` 写验收清单,再 `MergeWebIdePullRequests`
21
-
22
- ### 目录
23
-
24
- - 项目文档:`.apm/project/<项目ID>/`(索引 `manifest.json`;部署 / 本地 dev 命令以该目录下文件名或路径包含 `deploy` 的文档为准,不必恰好叫 `deploy.md`,禁止猜测)
25
- - 任务附件:`.apm/webide/<taskId>/attachments/`(prompt 出现「任务附件」时按路径查看)
26
- - 仓库清单:`.apm/workspace-repos.json`(先确认单仓 / 多仓;多仓必须写清改动范围并点名仓库)
27
-
28
- 计划、用例、验收清单、合并 PR 走 WebIDE 专用工具(`AskQuestion`、`RecommendPlan`、`UpsertWebIdePlan`、`UpsertWebIdeChecklist`、`GetWebIdeChecklist`、`UpsertWebIdeTestCases`、`MergeWebIdePullRequests` 等)。本地服务由用户在顶栏「启动项目」启动,开发任务不要自行起长驻进程。
@@ -1,16 +0,0 @@
1
- ## WebIDE Git 提交规范
2
-
3
- 适用场景:WebIDE 开发阶段(`skip-plan` / `start-develop`)及修码(`fix-and-retest` / `report-defect`)中涉及代码改动时。
4
-
5
- ### 分轮提交
6
-
7
- 1. 按需求点分轮实现:每完成一个可独立验收的需求点,立即 `git add` 并 commit,不要把多轮改动攒成一次提交。
8
- 2. commit message 用简短中文说明本轮改动(例:`feat: 实现登录表单校验`)。
9
- 3. 多仓工作区时,只在实际改动过的仓库提交。
10
-
11
- ### 结束前检查
12
-
13
- 本轮全部工作结束前:
14
-
15
- 1. 确认工作区干净(`git status` 无未提交变更);若仍有残留改动,补一次 commit。
16
- 2. 将当前分支推送到远程:已有 upstream 用 `git push`,否则 `git push -u origin HEAD`。多仓工作区时,只 push 实际有新 commit 的仓库。