ai-project-manage-cli 7.1.5 → 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"
@@ -6835,11 +6843,99 @@ function createUpsertWebIdePlanTool(options) {
6835
6843
  };
6836
6844
  }
6837
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
+
6838
6931
  // src/commands/connect/cursor-custom-tools.ts
6839
6932
  var PLAN_MODE_ASK_QUESTION_HINT = `[SDK \u73AF\u5883\u8BF4\u660E]
6840
6933
  AskQuestion \u5DF2\u901A\u8FC7 MCP \u670D\u52A1\u5668 custom-user-tools \u6CE8\u518C\uFF0C\u5DE5\u5177\u540D\u4E3A AskQuestion\u3002
6841
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
6842
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`;
6843
6939
  function createCursorCustomTools(cfg, messageId, options) {
6844
6940
  const tools = {
6845
6941
  ...createAppendMessageCustomTools(
@@ -6861,6 +6957,10 @@ function createCursorCustomTools(cfg, messageId, options) {
6861
6957
  cfg,
6862
6958
  taskId: options.taskId
6863
6959
  });
6960
+ tools.UpsertWebIdeTestCases = createUpsertWebIdeTestCasesTool({
6961
+ cfg,
6962
+ taskId: options.taskId
6963
+ });
6864
6964
  }
6865
6965
  return tools;
6866
6966
  }
@@ -6872,6 +6972,11 @@ function withPlanModeToolHint(prompt, mode) {
6872
6972
 
6873
6973
  ${PLAN_MODE_ASK_QUESTION_HINT}`;
6874
6974
  }
6975
+ function withWorkspaceBoundaryHint(prompt) {
6976
+ return `${prompt.trim()}
6977
+
6978
+ ${WORKSPACE_BOUNDARY_HINT}`;
6979
+ }
6875
6980
 
6876
6981
  // src/commands/connect/local-agent-store.ts
6877
6982
  import { mkdirSync as mkdirSync10 } from "node:fs";
@@ -6917,7 +7022,8 @@ async function obtainAgent(ctx) {
6917
7022
  local: {
6918
7023
  cwd: ctx.cwd,
6919
7024
  store: createWorkspaceLocalAgentStore(ctx.workdir),
6920
- ...ctx.customTools ? { customTools: ctx.customTools } : {}
7025
+ ...ctx.customTools ? { customTools: ctx.customTools } : {},
7026
+ ...ctx.enableSandbox ? { sandboxOptions: { enabled: true } } : {}
6921
7027
  },
6922
7028
  ...ctx.mode ? { mode: ctx.mode } : {}
6923
7029
  // mcpServers: createPlaywrightMcpServers(),
@@ -6926,14 +7032,14 @@ async function obtainAgent(ctx) {
6926
7032
  const savedAgentId = explicitAgentId || (ctx.user ? loadSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user) : void 0);
6927
7033
  if (savedAgentId) {
6928
7034
  try {
6929
- const agent2 = await Agent.resume(savedAgentId, agentOptions);
7035
+ const agent = await Agent.resume(savedAgentId, agentOptions);
6930
7036
  console.log(
6931
7037
  `[apm] \u590D\u7528 Agent user=${ctx.user} agentId=${savedAgentId}${explicitAgentId ? "\uFF08\u53C2\u6570\u6307\u5B9A\uFF09" : ""}`
6932
7038
  );
6933
7039
  if (ctx.user) {
6934
- saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent2.agentId);
7040
+ saveSessionAgentId(ctx.workdir, ctx.sessionId, ctx.user, agent.agentId);
6935
7041
  }
6936
- return { agent: agent2, resumed: true };
7042
+ return { agent, resumed: true };
6937
7043
  } catch (err) {
6938
7044
  console.warn(
6939
7045
  `[apm] \u590D\u7528 Agent \u5931\u8D25\uFF08agentId=${savedAgentId}\uFF09\uFF0C\u56DE\u9000\u4E3A\u65B0\u5EFA:`,
@@ -6944,11 +7050,19 @@ async function obtainAgent(ctx) {
6944
7050
  }
6945
7051
  }
6946
7052
  }
6947
- const agent = await Agent.create(agentOptions);
6948
- if (ctx.user) {
6949
- 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;
6950
7065
  }
6951
- return { agent, resumed: false };
6952
7066
  }
6953
7067
  async function runCursorAgent(cfg, ctx, options) {
6954
7068
  const signal = options?.signal;
@@ -6968,9 +7082,13 @@ async function runCursorAgent(cfg, ctx, options) {
6968
7082
  enableWebIdePlanTools: options?.enableWebIdePlanTools,
6969
7083
  taskId: options?.taskId
6970
7084
  });
6971
- 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
+ }
6972
7090
  console.log(
6973
- `[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}`
6974
7092
  );
6975
7093
  const { agent, resumed } = await obtainAgent({
6976
7094
  apiKey,
@@ -6981,7 +7099,8 @@ async function runCursorAgent(cfg, ctx, options) {
6981
7099
  user: ctx.user,
6982
7100
  mode: ctx.mode,
6983
7101
  resumeAgentId: ctx.resumeAgentId,
6984
- customTools
7102
+ customTools,
7103
+ enableSandbox
6985
7104
  });
6986
7105
  const eventSession = new EventSession(prompt);
6987
7106
  const syncRemoteLog = options?.createRemoteLogSync ? options.createRemoteLogSync(agent.agentId) : options?.skipRemoteLogSync ? noopRemoteLogSync : createThrottledCursorMessageLogSync(