ai-project-manage-cli 7.1.4 → 7.1.6

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
@@ -465,6 +465,10 @@ var requestConfig = {
465
465
  method: "PUT",
466
466
  path: "/cli/webide/plan"
467
467
  }),
468
+ webideReplaceTestCases: defineEndpoint({
469
+ method: "PUT",
470
+ path: "/cli/webide/test-cases"
471
+ }),
468
472
  branchBaseline: defineEndpoint({
469
473
  method: "GET",
470
474
  path: "/cli/tasks/branch-baseline"
@@ -497,6 +501,10 @@ var requestConfig = {
497
501
  method: "POST",
498
502
  path: "/cli/pull-requests"
499
503
  }),
504
+ createWebIdeDraftPullRequest: defineEndpoint({
505
+ method: "POST",
506
+ path: "/cli/webide/draft-pull-requests"
507
+ }),
500
508
  getRepositoryProjectDocumentManifest: defineEndpoint({
501
509
  method: "GET",
502
510
  path: "/cli/repository-project-documents/manifest"
@@ -6342,16 +6350,16 @@ var EventSession = class {
6342
6350
  return;
6343
6351
  }
6344
6352
  if (formatedEvent.type === "tool_call") {
6345
- const existingIndex = this.events.findIndex(
6346
- (e) => e.type === "tool_call" && e.call_id === formatedEvent.call_id
6347
- );
6348
- if (existingIndex >= 0) {
6349
- const existingToolCall = this.events[existingIndex];
6350
- existingToolCall.args = formatedEvent.args;
6351
- existingToolCall.result = formatedEvent.result;
6352
- existingToolCall.status = formatedEvent.status;
6353
- this.markDirty(existingIndex);
6354
- return;
6353
+ const callId = typeof formatedEvent.call_id === "string" ? formatedEvent.call_id.trim() : "";
6354
+ if (callId) {
6355
+ const existingIndex = this.events.findIndex(
6356
+ (e) => e.type === "tool_call" && typeof e.call_id === "string" && e.call_id === callId
6357
+ );
6358
+ if (existingIndex >= 0) {
6359
+ mergeToolCallEvent(this.events[existingIndex], formatedEvent);
6360
+ this.markDirty(existingIndex);
6361
+ return;
6362
+ }
6355
6363
  }
6356
6364
  this.events.push(formatedEvent);
6357
6365
  this.markDirty(this.events.length - 1);
@@ -6413,15 +6421,18 @@ var EventSession = class {
6413
6421
  type: "thinking",
6414
6422
  content: event.text || event.content || ""
6415
6423
  };
6416
- case "tool_call":
6424
+ case "tool_call": {
6425
+ const raw = event;
6426
+ const callId = String(raw.call_id ?? raw.callId ?? "").trim();
6417
6427
  return {
6418
6428
  type: "tool_call",
6419
6429
  args: event.args,
6420
6430
  result: event.result,
6421
6431
  status: event.status,
6422
- call_id: event.call_id,
6432
+ call_id: callId,
6423
6433
  name: event.name
6424
6434
  };
6435
+ }
6425
6436
  case "task":
6426
6437
  return {
6427
6438
  type: "task",
@@ -6486,6 +6497,24 @@ var EventSession = class {
6486
6497
  return this.events.map((event) => formatLogEvent(event.type, event)).join("\n");
6487
6498
  }
6488
6499
  };
6500
+ function mergeToolCallEvent(existing, incoming) {
6501
+ if (incoming.name) {
6502
+ existing.name = incoming.name;
6503
+ }
6504
+ if (incoming.status) {
6505
+ existing.status = incoming.status;
6506
+ }
6507
+ if (incoming.args != null && typeof incoming.args === "object" && !Array.isArray(incoming.args) && Object.keys(incoming.args).length > 0) {
6508
+ existing.args = { ...existing.args ?? {}, ...incoming.args };
6509
+ }
6510
+ if (incoming.result != null) {
6511
+ if (typeof incoming.result === "object" && !Array.isArray(incoming.result) && typeof existing.result === "object" && existing.result != null && !Array.isArray(existing.result)) {
6512
+ existing.result = { ...existing.result, ...incoming.result };
6513
+ } else {
6514
+ existing.result = incoming.result;
6515
+ }
6516
+ }
6517
+ }
6489
6518
  function formatLogEvent(type, event) {
6490
6519
  if (type === "input") {
6491
6520
  return `## \u7528\u6237\u8F93\u5165
@@ -6814,11 +6843,99 @@ function createUpsertWebIdePlanTool(options) {
6814
6843
  };
6815
6844
  }
6816
6845
 
6846
+ // src/commands/connect/webide-test-case-tools.ts
6847
+ function asString2(value) {
6848
+ return typeof value === "string" ? value.trim() : "";
6849
+ }
6850
+ function asStringArray(value) {
6851
+ if (!Array.isArray(value)) return [];
6852
+ return value.map((item) => typeof item === "string" ? item.trim() : String(item)).filter(Boolean);
6853
+ }
6854
+ function parseCases(raw) {
6855
+ if (!Array.isArray(raw)) return [];
6856
+ const cases = [];
6857
+ for (const [index, item] of raw.entries()) {
6858
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
6859
+ const row = item;
6860
+ const name = asString2(row.name);
6861
+ if (!name) continue;
6862
+ const steps = asStringArray(row.steps);
6863
+ if (steps.length === 0) continue;
6864
+ cases.push({
6865
+ name,
6866
+ description: asString2(row.description),
6867
+ steps,
6868
+ sortOrder: typeof row.sortOrder === "number" && Number.isFinite(row.sortOrder) ? row.sortOrder : index
6869
+ });
6870
+ }
6871
+ return cases;
6872
+ }
6873
+ function createUpsertWebIdeTestCasesTool(options) {
6874
+ const { cfg, taskId } = options;
6875
+ return {
6876
+ description: "Persist generated automated test cases for this WebIDE task (full replace) and mark the workflow TEST_READY. Call once with the complete case list after reviewing the task and code changes.",
6877
+ inputSchema: {
6878
+ type: "object",
6879
+ properties: {
6880
+ cases: {
6881
+ type: "array",
6882
+ description: "Complete list of test cases to store on the platform",
6883
+ items: {
6884
+ type: "object",
6885
+ properties: {
6886
+ name: {
6887
+ type: "string",
6888
+ description: "Short stable case id / name"
6889
+ },
6890
+ description: {
6891
+ type: "string",
6892
+ description: "What this case verifies (Chinese ok)"
6893
+ },
6894
+ steps: {
6895
+ type: "array",
6896
+ items: { type: "string" },
6897
+ description: "Ordered human-readable steps"
6898
+ },
6899
+ sortOrder: {
6900
+ type: "number",
6901
+ description: "Optional display order (0-based)"
6902
+ }
6903
+ },
6904
+ required: ["name", "description", "steps"]
6905
+ }
6906
+ }
6907
+ },
6908
+ required: ["cases"]
6909
+ },
6910
+ execute: async (args) => {
6911
+ const cases = parseCases(args.cases);
6912
+ if (cases.length === 0) {
6913
+ throw new Error(
6914
+ "UpsertWebIdeTestCases \u7F3A\u5C11\u6709\u6548 cases\uFF08\u6BCF\u6761\u9700 name \u4E0E\u975E\u7A7A steps\uFF09"
6915
+ );
6916
+ }
6917
+ const api = createApmApiClient(cfg);
6918
+ const result = await api.cli.webideReplaceTestCases({ taskId, cases });
6919
+ console.log(
6920
+ `[apm] UpsertWebIdeTestCases taskId=${taskId} count=${cases.length}`
6921
+ );
6922
+ return JSON.stringify(
6923
+ { ok: true, count: result.count ?? cases.length },
6924
+ null,
6925
+ 2
6926
+ );
6927
+ }
6928
+ };
6929
+ }
6930
+
6817
6931
  // src/commands/connect/cursor-custom-tools.ts
6818
6932
  var PLAN_MODE_ASK_QUESTION_HINT = `[SDK \u73AF\u5883\u8BF4\u660E]
6819
6933
  AskQuestion \u5DF2\u901A\u8FC7 MCP \u670D\u52A1\u5668 custom-user-tools \u6CE8\u518C\uFF0C\u5DE5\u5177\u540D\u4E3A AskQuestion\u3002
6820
6934
  \u9700\u8981\u5411\u7528\u6237\u786E\u8BA4\u65F6\uFF0C\u8BF7\u8C03\u7528 AskQuestion\uFF08\u7ECF CallMcpTool / custom-user-tools\uFF09\uFF0C\u4E0D\u8981\u5047\u8BBE IDE \u5185\u7F6E AskQuestion \u4E0D\u53EF\u7528\u3002
6821
6935
  \u975E\u5FC5\u987B\u7684\u95EE\u9898\u53EF\u8DF3\u8FC7\uFF0C\u76F4\u63A5\u5B8C\u6210 createPlan\u3002`;
6936
+ var WORKSPACE_BOUNDARY_HINT = `[\u5DE5\u4F5C\u533A\u8FB9\u754C]
6937
+ \u6240\u6709\u6587\u4EF6\u8BFB\u5199\u3001\u641C\u7D22\uFF08Grep/Glob/Read\uFF09\u3001Shell \u5FC5\u987B\u4E25\u683C\u9650\u5236\u5728\u5F53\u524D\u5DE5\u4F5C\u533A cwd \u5185\u3002
6938
+ \u7981\u6B62\u8BBF\u95EE\u5DE5\u4F5C\u533A\u5916\u8DEF\u5F84\uFF08\u5982\u5176\u5B83\u9879\u76EE\u3001~/.cursor\u3001agent-transcripts\u3001\u7CFB\u7EDF\u76EE\u5F55\u7B49\uFF09\u3002`;
6822
6939
  function createCursorCustomTools(cfg, messageId, options) {
6823
6940
  const tools = {
6824
6941
  ...createAppendMessageCustomTools(
@@ -6840,6 +6957,10 @@ function createCursorCustomTools(cfg, messageId, options) {
6840
6957
  cfg,
6841
6958
  taskId: options.taskId
6842
6959
  });
6960
+ tools.UpsertWebIdeTestCases = createUpsertWebIdeTestCasesTool({
6961
+ cfg,
6962
+ taskId: options.taskId
6963
+ });
6843
6964
  }
6844
6965
  return tools;
6845
6966
  }
@@ -6851,6 +6972,11 @@ function withPlanModeToolHint(prompt, mode) {
6851
6972
 
6852
6973
  ${PLAN_MODE_ASK_QUESTION_HINT}`;
6853
6974
  }
6975
+ function withWorkspaceBoundaryHint(prompt) {
6976
+ return `${prompt.trim()}
6977
+
6978
+ ${WORKSPACE_BOUNDARY_HINT}`;
6979
+ }
6854
6980
 
6855
6981
  // src/commands/connect/local-agent-store.ts
6856
6982
  import { mkdirSync as mkdirSync10 } from "node:fs";
@@ -6896,7 +7022,8 @@ async function obtainAgent(ctx) {
6896
7022
  local: {
6897
7023
  cwd: ctx.cwd,
6898
7024
  store: createWorkspaceLocalAgentStore(ctx.workdir),
6899
- ...ctx.customTools ? { customTools: ctx.customTools } : {}
7025
+ ...ctx.customTools ? { customTools: ctx.customTools } : {},
7026
+ ...ctx.enableSandbox ? { sandboxOptions: { enabled: true } } : {}
6900
7027
  },
6901
7028
  ...ctx.mode ? { mode: ctx.mode } : {}
6902
7029
  // mcpServers: createPlaywrightMcpServers(),
@@ -6905,14 +7032,14 @@ async function obtainAgent(ctx) {
6905
7032
  const savedAgentId = explicitAgentId || (ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0);
6906
7033
  if (savedAgentId) {
6907
7034
  try {
6908
- const agent2 = await Agent.resume(savedAgentId, agentOptions);
7035
+ const agent = await Agent.resume(savedAgentId, agentOptions);
6909
7036
  console.log(
6910
7037
  `[apm] \u590D\u7528 Agent user=${ctx.user} agentId=${savedAgentId}${explicitAgentId ? "\uFF08\u53C2\u6570\u6307\u5B9A\uFF09" : ""}`
6911
7038
  );
6912
7039
  if (ctx.user) {
6913
- saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent2.agentId);
7040
+ saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
6914
7041
  }
6915
- return { agent: agent2, resumed: true };
7042
+ return { agent, resumed: true };
6916
7043
  } catch (err) {
6917
7044
  console.warn(
6918
7045
  `[apm] \u590D\u7528 Agent \u5931\u8D25\uFF08agentId=${savedAgentId}\uFF09\uFF0C\u56DE\u9000\u4E3A\u65B0\u5EFA:`,
@@ -6923,11 +7050,19 @@ async function obtainAgent(ctx) {
6923
7050
  }
6924
7051
  }
6925
7052
  }
6926
- const agent = await Agent.create(agentOptions);
6927
- if (ctx.user) {
6928
- saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
7053
+ try {
7054
+ const agent = await Agent.create(agentOptions);
7055
+ if (ctx.user) {
7056
+ saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
7057
+ }
7058
+ return { agent, resumed: false };
7059
+ } catch (err) {
7060
+ if (ctx.enableSandbox && err instanceof Error && /sandbox/i.test(err.message)) {
7061
+ console.warn("[apm] sandbox \u4E0D\u53EF\u7528\uFF0C\u56DE\u9000\u4E3A\u65E0 sandbox:", err.message);
7062
+ return obtainAgent({ ...ctx, enableSandbox: false });
7063
+ }
7064
+ throw err;
6929
7065
  }
6930
- return { agent, resumed: false };
6931
7066
  }
6932
7067
  async function runCursorAgent(cfg, ctx, options) {
6933
7068
  const signal = options?.signal;
@@ -6947,9 +7082,13 @@ async function runCursorAgent(cfg, ctx, options) {
6947
7082
  enableWebIdePlanTools: options?.enableWebIdePlanTools,
6948
7083
  taskId: options?.taskId
6949
7084
  });
6950
- const prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
7085
+ const enableSandbox = Boolean(options?.enableSandbox);
7086
+ let prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
7087
+ if (enableSandbox) {
7088
+ prompt = withWorkspaceBoundaryHint(prompt);
7089
+ }
6951
7090
  console.log(
6952
- `[apm] Cursor Agent \u5F00\u59CB messageId=${ctx.messageId} sessionId=${ctx.sessionId} cwd=${workdir}`
7091
+ `[apm] Cursor Agent \u5F00\u59CB messageId=${ctx.messageId} sessionId=${ctx.sessionId} cwd=${workdir} sandbox=${enableSandbox}`
6953
7092
  );
6954
7093
  const { agent, resumed } = await obtainAgent({
6955
7094
  apiKey,
@@ -6960,7 +7099,8 @@ async function runCursorAgent(cfg, ctx, options) {
6960
7099
  user: ctx.user,
6961
7100
  mode: ctx.mode,
6962
7101
  resumeAgentId: ctx.resumeAgentId,
6963
- customTools
7102
+ customTools,
7103
+ enableSandbox
6964
7104
  });
6965
7105
  const eventSession = new EventSession(prompt);
6966
7106
  const syncRemoteLog = options?.createRemoteLogSync ? options.createRemoteLogSync(agent.agentId) : options?.skipRemoteLogSync ? noopRemoteLogSync : createThrottledCursorMessageLogSync(