ai-project-manage-cli 8.1.9 → 8.1.11

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
@@ -80,7 +80,14 @@ function buildAgentWsUrl(httpBase, apiKey) {
80
80
  }
81
81
 
82
82
  // src/commands/sync-webide-agent.ts
83
- import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
83
+ import {
84
+ existsSync as existsSync2,
85
+ mkdirSync as mkdirSync3,
86
+ readdirSync as readdirSync2,
87
+ readFileSync as readFileSync2,
88
+ unlinkSync,
89
+ writeFileSync as writeFileSync2
90
+ } from "fs";
84
91
  import { join as join3 } from "path";
85
92
 
86
93
  // src/api/client.ts
@@ -368,7 +375,7 @@ async function ensureWorkspaceApmDirForInit(cwd = resolveWorkdirPath()) {
368
375
 
369
376
  // src/commands/sync-webide-agent.ts
370
377
  var REVISION_FILE = ".webide-agent.json";
371
- var RULE_KEY = /^webide_[a-z0-9_]+$/;
378
+ var RULE_KEY = /^[a-z0-9_]+$/;
372
379
  function withTrailingNewline(text) {
373
380
  return text.endsWith("\n") ? text : `${text}
374
381
  `;
@@ -413,17 +420,24 @@ async function syncWebIdeAgentFiles(workdir, cfg) {
413
420
  withTrailingNewline(bundle.guide ?? ""),
414
421
  "utf8"
415
422
  );
423
+ const keep = /* @__PURE__ */ new Set();
416
424
  for (const rule of bundle.rules ?? []) {
417
425
  const key = rule.key?.trim() ?? "";
418
426
  if (!RULE_KEY.test(key)) {
419
427
  throw new Error(`[apm] \u975E\u6CD5\u89C4\u5219\u540D: ${key || "(\u7A7A)"}`);
420
428
  }
429
+ keep.add(`${key}.md`);
421
430
  writeFileSync2(
422
431
  toFsPath(join3(rulesDir, `${key}.md`)),
423
432
  withTrailingNewline(rule.body ?? ""),
424
433
  "utf8"
425
434
  );
426
435
  }
436
+ for (const name of readdirSync2(toFsPath(rulesDir))) {
437
+ if (!name.endsWith(".md")) continue;
438
+ if (keep.has(name)) continue;
439
+ unlinkSync(toFsPath(join3(rulesDir, name)));
440
+ }
427
441
  writeRevision(apmDir, revision);
428
442
  return {
429
443
  revision,
@@ -754,7 +768,7 @@ async function runUpdateSkills() {
754
768
  // src/utils/project-documents.ts
755
769
  import {
756
770
  existsSync as existsSync5,
757
- readdirSync as readdirSync2,
771
+ readdirSync as readdirSync3,
758
772
  readFileSync as readFileSync4,
759
773
  rmSync,
760
774
  writeFileSync as writeFileSync3
@@ -880,7 +894,7 @@ function listLocalDocumentPaths(apmRoot, projectId) {
880
894
  }
881
895
  const paths = [];
882
896
  const walk = (dir) => {
883
- for (const entry of readdirSync2(dir, { withFileTypes: true })) {
897
+ for (const entry of readdirSync3(dir, { withFileTypes: true })) {
884
898
  const abs = join6(dir, entry.name);
885
899
  if (entry.isDirectory()) {
886
900
  walk(abs);
@@ -1189,6 +1203,25 @@ function validateCancel(o) {
1189
1203
  data: { type: "cancel", messageId: o.messageId.trim() }
1190
1204
  };
1191
1205
  }
1206
+ function validateSteer(o) {
1207
+ if (o.type !== "steer") {
1208
+ return { ok: false, reason: "\u671F\u671B steer" };
1209
+ }
1210
+ if (!nonEmptyString(o.messageId)) {
1211
+ return { ok: false, reason: "steer \u7F3A\u5C11 messageId" };
1212
+ }
1213
+ if (!nonEmptyString(o.text)) {
1214
+ return { ok: false, reason: "steer \u7F3A\u5C11 text" };
1215
+ }
1216
+ return {
1217
+ ok: true,
1218
+ data: {
1219
+ type: "steer",
1220
+ messageId: o.messageId.trim(),
1221
+ text: o.text.trim()
1222
+ }
1223
+ };
1224
+ }
1192
1225
  function validateWebIdeStopTerminals(o) {
1193
1226
  if (o.type !== "webide-stop-terminals") {
1194
1227
  return { ok: false, reason: "\u671F\u671B webide-stop-terminals" };
@@ -1305,7 +1338,7 @@ function validateAgentWsMessage(value, kind) {
1305
1338
  }
1306
1339
  const o = value;
1307
1340
  const type = o.type;
1308
- if (type !== "heartbeat" && type !== "webide-message" && type !== "cancel" && type !== "webide-start-project" && type !== "webide-stop-terminals" && type !== "webide-package") {
1341
+ if (type !== "heartbeat" && type !== "webide-message" && type !== "cancel" && type !== "steer" && type !== "webide-start-project" && type !== "webide-stop-terminals" && type !== "webide-package") {
1309
1342
  return { ok: false, reason: `\u672A\u77E5 type: ${String(type)}` };
1310
1343
  }
1311
1344
  if (kind === "heartbeat" || type === "heartbeat") {
@@ -1314,6 +1347,9 @@ function validateAgentWsMessage(value, kind) {
1314
1347
  if (type === "cancel") {
1315
1348
  return validateCancel(o);
1316
1349
  }
1350
+ if (type === "steer") {
1351
+ return validateSteer(o);
1352
+ }
1317
1353
  if (type === "webide-start-project") {
1318
1354
  return validateWebIdeStartProjectPush(o);
1319
1355
  }
@@ -1333,6 +1369,29 @@ function handleCancelAction(payload, ctx) {
1333
1369
  ctx.activeRuns.get(messageId)?.abort();
1334
1370
  }
1335
1371
 
1372
+ // src/commands/connect/actions/steer.ts
1373
+ function registerRunSteer(ctx, messageId, target) {
1374
+ const send = (text) => target.steer(messageId, text);
1375
+ ctx.steerRuns.set(messageId, send);
1376
+ const queued = ctx.pendingSteers.get(messageId);
1377
+ if (!queued) return;
1378
+ ctx.pendingSteers.delete(messageId);
1379
+ send(queued);
1380
+ }
1381
+ function unregisterRunSteer(ctx, messageId) {
1382
+ ctx.steerRuns.delete(messageId);
1383
+ ctx.pendingSteers.delete(messageId);
1384
+ }
1385
+ function handleSteerAction(payload, ctx) {
1386
+ const send = ctx.steerRuns.get(payload.messageId);
1387
+ if (!send) {
1388
+ ctx.pendingSteers.set(payload.messageId, payload.text);
1389
+ console.log(`[apm] steer \u5DF2\u6392\u961F messageId=${payload.messageId}`);
1390
+ return;
1391
+ }
1392
+ send(payload.text);
1393
+ }
1394
+
1336
1395
  // src/commands/connect/core/worker/worker.ts
1337
1396
  import { dirname as dirname3, join as join7 } from "path";
1338
1397
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -1459,6 +1518,9 @@ var ActionWorker = class {
1459
1518
  cancel(msg_id) {
1460
1519
  this.worker.postMessage({ type: "cancel", messageId: msg_id });
1461
1520
  }
1521
+ steer(msg_id, text) {
1522
+ this.worker.postMessage({ type: "steer", messageId: msg_id, text });
1523
+ }
1462
1524
  get done() {
1463
1525
  return this.promise;
1464
1526
  }
@@ -1498,6 +1560,7 @@ function handleWebIdeMessageAction(payload, ctx) {
1498
1560
  }
1499
1561
  const task = (async () => {
1500
1562
  const handle = new ActionWorker(payload);
1563
+ registerRunSteer(ctx, payload.messageId, handle);
1501
1564
  const onAbort = () => handle.cancel(payload.messageId);
1502
1565
  perMessageController.signal.addEventListener("abort", onAbort, {
1503
1566
  once: true
@@ -1506,6 +1569,7 @@ function handleWebIdeMessageAction(payload, ctx) {
1506
1569
  await handle.done;
1507
1570
  } finally {
1508
1571
  perMessageController.signal.removeEventListener("abort", onAbort);
1572
+ unregisterRunSteer(ctx, payload.messageId);
1509
1573
  ctx.activeRuns.delete(payload.messageId);
1510
1574
  }
1511
1575
  })();
@@ -1538,6 +1602,7 @@ function handleStartProjectAction(payload, ctx) {
1538
1602
  }
1539
1603
  const task = (async () => {
1540
1604
  const handle = new ActionWorker(payload);
1605
+ registerRunSteer(ctx, payload.messageId, handle);
1541
1606
  const onAbort = () => handle.cancel(payload.messageId);
1542
1607
  perMessageController.signal.addEventListener("abort", onAbort, {
1543
1608
  once: true
@@ -1546,6 +1611,7 @@ function handleStartProjectAction(payload, ctx) {
1546
1611
  await handle.done;
1547
1612
  } finally {
1548
1613
  perMessageController.signal.removeEventListener("abort", onAbort);
1614
+ unregisterRunSteer(ctx, payload.messageId);
1549
1615
  ctx.activeRuns.delete(payload.messageId);
1550
1616
  }
1551
1617
  })();
@@ -1674,6 +1740,7 @@ function handleWebIdePackageAction(payload, ctx) {
1674
1740
  }
1675
1741
  const task = (async () => {
1676
1742
  const handle = new ActionWorker(payload);
1743
+ registerRunSteer(ctx, payload.messageId, handle);
1677
1744
  const onAbort = () => handle.cancel(payload.messageId);
1678
1745
  perMessageController.signal.addEventListener("abort", onAbort, {
1679
1746
  once: true
@@ -1682,6 +1749,7 @@ function handleWebIdePackageAction(payload, ctx) {
1682
1749
  await handle.done;
1683
1750
  } finally {
1684
1751
  perMessageController.signal.removeEventListener("abort", onAbort);
1752
+ unregisterRunSteer(ctx, payload.messageId);
1685
1753
  ctx.activeRuns.delete(payload.messageId);
1686
1754
  }
1687
1755
  })();
@@ -1696,6 +1764,9 @@ function dispatchConnectAction(payload, ctx) {
1696
1764
  case "cancel":
1697
1765
  handleCancelAction(payload, ctx);
1698
1766
  return;
1767
+ case "steer":
1768
+ handleSteerAction(payload, ctx);
1769
+ return;
1699
1770
  case "webide-message":
1700
1771
  handleWebIdeMessageAction(payload, ctx);
1701
1772
  return;
@@ -1716,7 +1787,7 @@ import {
1716
1787
  existsSync as existsSync6,
1717
1788
  mkdirSync as mkdirSync4,
1718
1789
  readFileSync as readFileSync5,
1719
- unlinkSync,
1790
+ unlinkSync as unlinkSync2,
1720
1791
  writeFileSync as writeFileSync4
1721
1792
  } from "fs";
1722
1793
  import { join as join8 } from "path";
@@ -1751,7 +1822,7 @@ function pruneStaleConnectLock() {
1751
1822
  if (!lock) return;
1752
1823
  if (isProcessAlive(lock.pid)) return;
1753
1824
  try {
1754
- unlinkSync(CONNECT_LOCK_PATH);
1825
+ unlinkSync2(CONNECT_LOCK_PATH);
1755
1826
  } catch {
1756
1827
  }
1757
1828
  }
@@ -1780,7 +1851,7 @@ function releaseConnectLock() {
1780
1851
  const lock = readConnectLock();
1781
1852
  if (lock?.pid !== process.pid) return;
1782
1853
  try {
1783
- unlinkSync(CONNECT_LOCK_PATH);
1854
+ unlinkSync2(CONNECT_LOCK_PATH);
1784
1855
  } catch {
1785
1856
  }
1786
1857
  }
@@ -1920,6 +1991,8 @@ async function runConnect(options) {
1920
1991
  const activeTasks = /* @__PURE__ */ new Set();
1921
1992
  const activeRuns = /* @__PURE__ */ new Map();
1922
1993
  const pendingCancels = /* @__PURE__ */ new Set();
1994
+ const steerRuns = /* @__PURE__ */ new Map();
1995
+ const pendingSteers = /* @__PURE__ */ new Map();
1923
1996
  let currentConnectionAbort = null;
1924
1997
  const connectCtx = {
1925
1998
  cfg,
@@ -1927,6 +2000,8 @@ async function runConnect(options) {
1927
2000
  activeTasks,
1928
2001
  activeRuns,
1929
2002
  pendingCancels,
2003
+ steerRuns,
2004
+ pendingSteers,
1930
2005
  isShuttingDown: () => shuttingDown
1931
2006
  };
1932
2007
  const drainAndExit = async (code = 0) => {
@@ -2783,6 +2783,30 @@ function createRemoteLocalAgentStore(cfg2) {
2783
2783
  };
2784
2784
  }
2785
2785
 
2786
+ // src/commands/connect/core/worker/run-steer.ts
2787
+ var impl = null;
2788
+ var pending = null;
2789
+ function bindRunSteer(fn) {
2790
+ impl = fn;
2791
+ if (!pending) return;
2792
+ const text = pending;
2793
+ pending = null;
2794
+ void fn(text);
2795
+ }
2796
+ function clearRunSteer() {
2797
+ impl = null;
2798
+ pending = null;
2799
+ }
2800
+ function deliverRunSteer(text) {
2801
+ const trimmed = text.trim();
2802
+ if (!trimmed) return;
2803
+ if (impl) {
2804
+ void impl(trimmed);
2805
+ return;
2806
+ }
2807
+ pending = trimmed;
2808
+ }
2809
+
2786
2810
  // src/commands/connect/cursor-agent.ts
2787
2811
  var noopRemoteLogSync = {
2788
2812
  schedule(_session) {
@@ -2914,6 +2938,22 @@ async function runCursorAgent(cfg2, ctx, options) {
2914
2938
  });
2915
2939
  activeRun = run;
2916
2940
  console.log(`[apm] Cursor run id=${run.id} agentId=${agent.agentId}`);
2941
+ bindRunSteer(async (text) => {
2942
+ const steer = run.steer;
2943
+ if (!steer) {
2944
+ console.warn(`[apm] \u5F53\u524D run \u4E0D\u652F\u6301 steer runId=${run.id}`);
2945
+ return;
2946
+ }
2947
+ try {
2948
+ const outcome = await steer(text);
2949
+ console.log(`[apm] steer outcome=${outcome} runId=${run.id}`);
2950
+ } catch (err) {
2951
+ console.error(
2952
+ `[apm] steer \u5931\u8D25 runId=${run.id}:`,
2953
+ err instanceof Error ? err.message : err
2954
+ );
2955
+ }
2956
+ });
2917
2957
  await options.onRunStarted?.({ agentId: agent.agentId, runId: run.id });
2918
2958
  let lastRunErrorStatus;
2919
2959
  for await (const event of run.stream()) {
@@ -2999,6 +3039,7 @@ async function runCursorAgent(cfg2, ctx, options) {
2999
3039
  }
3000
3040
  throw err;
3001
3041
  } finally {
3042
+ clearRunSteer();
3002
3043
  signal?.removeEventListener("abort", abortRun);
3003
3044
  await agent[Symbol.asyncDispose]();
3004
3045
  }
@@ -3138,10 +3179,17 @@ function createThrottledWebIdeMessageLogSync(cfg2, ctx, onError, options) {
3138
3179
  }
3139
3180
 
3140
3181
  // src/commands/sync-webide-agent.ts
3141
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
3182
+ import {
3183
+ existsSync as existsSync5,
3184
+ mkdirSync as mkdirSync4,
3185
+ readdirSync as readdirSync3,
3186
+ readFileSync as readFileSync4,
3187
+ unlinkSync,
3188
+ writeFileSync as writeFileSync3
3189
+ } from "fs";
3142
3190
  import { join as join4 } from "path";
3143
3191
  var REVISION_FILE = ".webide-agent.json";
3144
- var RULE_KEY = /^webide_[a-z0-9_]+$/;
3192
+ var RULE_KEY = /^[a-z0-9_]+$/;
3145
3193
  function withTrailingNewline(text) {
3146
3194
  return text.endsWith("\n") ? text : `${text}
3147
3195
  `;
@@ -3186,17 +3234,24 @@ async function syncWebIdeAgentFiles(workdir, cfg2) {
3186
3234
  withTrailingNewline(bundle.guide ?? ""),
3187
3235
  "utf8"
3188
3236
  );
3237
+ const keep = /* @__PURE__ */ new Set();
3189
3238
  for (const rule of bundle.rules ?? []) {
3190
3239
  const key = rule.key?.trim() ?? "";
3191
3240
  if (!RULE_KEY.test(key)) {
3192
3241
  throw new Error(`[apm] \u975E\u6CD5\u89C4\u5219\u540D: ${key || "(\u7A7A)"}`);
3193
3242
  }
3243
+ keep.add(`${key}.md`);
3194
3244
  writeFileSync3(
3195
3245
  toFsPath(join4(rulesDir, `${key}.md`)),
3196
3246
  withTrailingNewline(rule.body ?? ""),
3197
3247
  "utf8"
3198
3248
  );
3199
3249
  }
3250
+ for (const name of readdirSync3(toFsPath(rulesDir))) {
3251
+ if (!name.endsWith(".md")) continue;
3252
+ if (keep.has(name)) continue;
3253
+ unlinkSync(toFsPath(join4(rulesDir, name)));
3254
+ }
3200
3255
  writeRevision(apmDir, revision);
3201
3256
  return {
3202
3257
  revision,
@@ -3221,7 +3276,7 @@ async function ensureWorkspaceInitialized(workdir) {
3221
3276
  // src/utils/project-documents.ts
3222
3277
  import {
3223
3278
  existsSync as existsSync6,
3224
- readdirSync as readdirSync3,
3279
+ readdirSync as readdirSync4,
3225
3280
  readFileSync as readFileSync5,
3226
3281
  rmSync,
3227
3282
  writeFileSync as writeFileSync4
@@ -3287,7 +3342,7 @@ function listLocalDocumentPaths(apmRoot, projectId) {
3287
3342
  }
3288
3343
  const paths = [];
3289
3344
  const walk = (dir) => {
3290
- for (const entry of readdirSync3(dir, { withFileTypes: true })) {
3345
+ for (const entry of readdirSync4(dir, { withFileTypes: true })) {
3291
3346
  const abs = join5(dir, entry.name);
3292
3347
  if (entry.isDirectory()) {
3293
3348
  walk(abs);
@@ -4531,7 +4586,7 @@ async function syncWebIdeAttachments(cfg2, taskId, workdir, attachments) {
4531
4586
 
4532
4587
  // src/commands/sync-webide-design.ts
4533
4588
  import { createHash as createHash3 } from "crypto";
4534
- import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
4589
+ import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync5, writeFileSync as writeFileSync7 } from "fs";
4535
4590
  import { join as join7 } from "path";
4536
4591
 
4537
4592
  // src/opc-shared-types.ts
@@ -4613,7 +4668,7 @@ function listLocalDesignArtifactFiles(taskId, workdir) {
4613
4668
  const dir = webideDesignDir(taskId, workdir);
4614
4669
  if (!existsSync10(dir)) return [];
4615
4670
  const out = [];
4616
- for (const name of readdirSync4(dir)) {
4671
+ for (const name of readdirSync5(dir)) {
4617
4672
  if (!isWebIdeDesignArtifactName(name)) continue;
4618
4673
  const absPath = join7(dir, name);
4619
4674
  if (!statSync5(absPath).isFile()) continue;
@@ -5403,11 +5458,19 @@ var cfg = tryReadApmConfig();
5403
5458
  var { msg } = workerData;
5404
5459
  if (!cfg || !msg) throw new Error("worker-script \u7F3A\u5C11 workerData");
5405
5460
  var controller = new AbortController();
5406
- port.on("message", (raw) => {
5407
- if (raw?.type === "cancel" && raw.messageId === msg.messageId) {
5408
- controller.abort();
5461
+ port.on(
5462
+ "message",
5463
+ (raw) => {
5464
+ if (raw?.messageId !== msg.messageId) return;
5465
+ if (raw.type === "cancel") {
5466
+ controller.abort();
5467
+ return;
5468
+ }
5469
+ if (raw.type === "steer" && typeof raw.text === "string") {
5470
+ deliverRunSteer(raw.text);
5471
+ }
5409
5472
  }
5410
- });
5473
+ );
5411
5474
  var reply = (body) => port.postMessage(body);
5412
5475
  try {
5413
5476
  await dispatchWorkerJob(cfg, msg, controller.signal);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "8.1.9",
3
+ "version": "8.1.11",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -31,7 +31,7 @@
31
31
  "@bufbuild/protobuf": "1.10.0",
32
32
  "@connectrpc/connect": "~1.7.0",
33
33
  "@connectrpc/connect-node": "~1.7.0",
34
- "@cursor/sdk": "^1.0.22",
34
+ "@cursor/sdk": "^1.0.32",
35
35
  "commander": "~14.0.3",
36
36
  "listpage-http": "~0.0.318",
37
37
  "minio": "~8.0.7",