ai-project-manage-cli 7.1.2 → 7.1.3
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 +139 -3
- package/dist/webide-message-worker.js +160 -9
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -457,6 +457,14 @@ var requestConfig = {
|
|
|
457
457
|
method: "GET",
|
|
458
458
|
path: "/cli/webide/assumptions"
|
|
459
459
|
}),
|
|
460
|
+
webideRecommendPlan: defineEndpoint({
|
|
461
|
+
method: "PUT",
|
|
462
|
+
path: "/cli/webide/plan-recommendation"
|
|
463
|
+
}),
|
|
464
|
+
webideUpsertPlan: defineEndpoint({
|
|
465
|
+
method: "PUT",
|
|
466
|
+
path: "/cli/webide/plan"
|
|
467
|
+
}),
|
|
460
468
|
branchBaseline: defineEndpoint({
|
|
461
469
|
method: "GET",
|
|
462
470
|
path: "/cli/tasks/branch-baseline"
|
|
@@ -6304,6 +6312,16 @@ function formatPlanMarkdown(raw) {
|
|
|
6304
6312
|
}
|
|
6305
6313
|
|
|
6306
6314
|
// src/session-utils.ts
|
|
6315
|
+
function serializeTokenUsage(usage) {
|
|
6316
|
+
return {
|
|
6317
|
+
inputTokens: usage.inputTokens,
|
|
6318
|
+
outputTokens: usage.outputTokens,
|
|
6319
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
6320
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
6321
|
+
totalTokens: usage.totalTokens,
|
|
6322
|
+
...usage.reasoningTokens != null ? { reasoningTokens: usage.reasoningTokens } : {}
|
|
6323
|
+
};
|
|
6324
|
+
}
|
|
6307
6325
|
var EventSession = class {
|
|
6308
6326
|
events = [];
|
|
6309
6327
|
dirtyIndices = /* @__PURE__ */ new Set();
|
|
@@ -6342,7 +6360,7 @@ var EventSession = class {
|
|
|
6342
6360
|
if (formatedEvent.type === "status") {
|
|
6343
6361
|
return;
|
|
6344
6362
|
}
|
|
6345
|
-
if (formatedEvent.type === "request") {
|
|
6363
|
+
if (formatedEvent.type === "request" || formatedEvent.type === "usage") {
|
|
6346
6364
|
this.events.push(formatedEvent);
|
|
6347
6365
|
this.markDirty(this.events.length - 1);
|
|
6348
6366
|
return;
|
|
@@ -6366,6 +6384,16 @@ var EventSession = class {
|
|
|
6366
6384
|
this.events.push(formatedEvent);
|
|
6367
6385
|
this.markDirty(this.events.length - 1);
|
|
6368
6386
|
}
|
|
6387
|
+
/** 写入 run.wait() 返回的累计 TokenUsage(整次 run 汇总) */
|
|
6388
|
+
addRunUsage(usage, options) {
|
|
6389
|
+
this.events.push({
|
|
6390
|
+
type: "usage",
|
|
6391
|
+
scope: "run",
|
|
6392
|
+
usage: serializeTokenUsage(usage),
|
|
6393
|
+
...options?.durationMs != null ? { durationMs: options.durationMs } : {}
|
|
6394
|
+
});
|
|
6395
|
+
this.markDirty(this.events.length - 1);
|
|
6396
|
+
}
|
|
6369
6397
|
formatEvent(event) {
|
|
6370
6398
|
switch (event.type) {
|
|
6371
6399
|
case "assistant": {
|
|
@@ -6400,6 +6428,12 @@ var EventSession = class {
|
|
|
6400
6428
|
status: event.status,
|
|
6401
6429
|
text: event.text
|
|
6402
6430
|
};
|
|
6431
|
+
case "usage":
|
|
6432
|
+
return {
|
|
6433
|
+
type: "usage",
|
|
6434
|
+
scope: "turn",
|
|
6435
|
+
usage: serializeTokenUsage(event.usage)
|
|
6436
|
+
};
|
|
6403
6437
|
case "request":
|
|
6404
6438
|
return {
|
|
6405
6439
|
...event,
|
|
@@ -6474,6 +6508,16 @@ ${String(event.content ?? "")}
|
|
|
6474
6508
|
if (type === "tool_call") {
|
|
6475
6509
|
return "````toolcall\n" + JSON.stringify(event, null, 2) + "\n````\n";
|
|
6476
6510
|
}
|
|
6511
|
+
if (type === "usage") {
|
|
6512
|
+
const usage = event.usage;
|
|
6513
|
+
const scope = event.scope === "run" ? "\u7D2F\u8BA1" : "\u672C\u8F6E";
|
|
6514
|
+
return `## Token \u4F7F\u7528\u91CF\uFF08${scope}\uFF09
|
|
6515
|
+
|
|
6516
|
+
\`\`\`json
|
|
6517
|
+
${JSON.stringify(usage ?? event, null, 2)}
|
|
6518
|
+
\`\`\`
|
|
6519
|
+
`;
|
|
6520
|
+
}
|
|
6477
6521
|
return `## \u672A\u77E5\u4E8B\u4EF6\uFF1A${type}
|
|
6478
6522
|
|
|
6479
6523
|
\`\`\`json
|
|
@@ -6701,13 +6745,82 @@ ${payload}`;
|
|
|
6701
6745
|
};
|
|
6702
6746
|
}
|
|
6703
6747
|
|
|
6748
|
+
// src/commands/connect/webide-plan-tools.ts
|
|
6749
|
+
function asString(value) {
|
|
6750
|
+
return typeof value === "string" ? value.trim() : "";
|
|
6751
|
+
}
|
|
6752
|
+
function createRecommendPlanTool(options) {
|
|
6753
|
+
const { cfg, taskId } = options;
|
|
6754
|
+
return {
|
|
6755
|
+
description: "Recommend whether the human should write an implementation plan or skip it. Does not change workflow phase; the human decides in the WebIDE UI.",
|
|
6756
|
+
inputSchema: {
|
|
6757
|
+
type: "object",
|
|
6758
|
+
properties: {
|
|
6759
|
+
recommendation: {
|
|
6760
|
+
type: "string",
|
|
6761
|
+
enum: ["write", "skip", "unknown"],
|
|
6762
|
+
description: "write = suggest generating a plan; skip = plan optional/unnecessary; unknown = unsure"
|
|
6763
|
+
},
|
|
6764
|
+
reason: {
|
|
6765
|
+
type: "string",
|
|
6766
|
+
description: "Short Chinese reason for the recommendation"
|
|
6767
|
+
}
|
|
6768
|
+
},
|
|
6769
|
+
required: ["recommendation"]
|
|
6770
|
+
},
|
|
6771
|
+
execute: async (args) => {
|
|
6772
|
+
const raw = asString(args.recommendation);
|
|
6773
|
+
const recommendation = raw === "write" || raw === "skip" || raw === "unknown" ? raw : "unknown";
|
|
6774
|
+
const reason = asString(args.reason) || void 0;
|
|
6775
|
+
const api = createApmApiClient(cfg);
|
|
6776
|
+
await api.cli.webideRecommendPlan({
|
|
6777
|
+
taskId,
|
|
6778
|
+
recommendation,
|
|
6779
|
+
reason
|
|
6780
|
+
});
|
|
6781
|
+
console.log(
|
|
6782
|
+
`[apm] RecommendPlan taskId=${taskId} recommendation=${recommendation}`
|
|
6783
|
+
);
|
|
6784
|
+
return JSON.stringify({ ok: true, recommendation, reason }, null, 2);
|
|
6785
|
+
}
|
|
6786
|
+
};
|
|
6787
|
+
}
|
|
6788
|
+
function createUpsertWebIdePlanTool(options) {
|
|
6789
|
+
const { cfg, taskId } = options;
|
|
6790
|
+
return {
|
|
6791
|
+
description: "Persist the implementation plan markdown for this WebIDE task and mark the plan as ready for human confirmation. Call once with the full plan document.",
|
|
6792
|
+
inputSchema: {
|
|
6793
|
+
type: "object",
|
|
6794
|
+
properties: {
|
|
6795
|
+
content: {
|
|
6796
|
+
type: "string",
|
|
6797
|
+
description: "Full implementation plan in Markdown (Chinese)"
|
|
6798
|
+
}
|
|
6799
|
+
},
|
|
6800
|
+
required: ["content"]
|
|
6801
|
+
},
|
|
6802
|
+
execute: async (args) => {
|
|
6803
|
+
const content = asString(args.content);
|
|
6804
|
+
if (!content) {
|
|
6805
|
+
throw new Error("UpsertWebIdePlan \u7F3A\u5C11 content");
|
|
6806
|
+
}
|
|
6807
|
+
const api = createApmApiClient(cfg);
|
|
6808
|
+
await api.cli.webideUpsertPlan({ taskId, content });
|
|
6809
|
+
console.log(
|
|
6810
|
+
`[apm] UpsertWebIdePlan taskId=${taskId} chars=${content.length}`
|
|
6811
|
+
);
|
|
6812
|
+
return JSON.stringify({ ok: true, chars: content.length }, null, 2);
|
|
6813
|
+
}
|
|
6814
|
+
};
|
|
6815
|
+
}
|
|
6816
|
+
|
|
6704
6817
|
// src/commands/connect/cursor-custom-tools.ts
|
|
6705
6818
|
var PLAN_MODE_ASK_QUESTION_HINT = `[SDK \u73AF\u5883\u8BF4\u660E]
|
|
6706
6819
|
AskQuestion \u5DF2\u901A\u8FC7 MCP \u670D\u52A1\u5668 custom-user-tools \u6CE8\u518C\uFF0C\u5DE5\u5177\u540D\u4E3A AskQuestion\u3002
|
|
6707
6820
|
\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
|
|
6708
6821
|
\u975E\u5FC5\u987B\u7684\u95EE\u9898\u53EF\u8DF3\u8FC7\uFF0C\u76F4\u63A5\u5B8C\u6210 createPlan\u3002`;
|
|
6709
6822
|
function createCursorCustomTools(cfg, messageId, options) {
|
|
6710
|
-
|
|
6823
|
+
const tools = {
|
|
6711
6824
|
...createAppendMessageCustomTools(
|
|
6712
6825
|
cfg,
|
|
6713
6826
|
messageId,
|
|
@@ -6718,6 +6831,17 @@ function createCursorCustomTools(cfg, messageId, options) {
|
|
|
6718
6831
|
execute: options?.askQuestionExecute
|
|
6719
6832
|
})
|
|
6720
6833
|
};
|
|
6834
|
+
if (options?.enableWebIdePlanTools && options.taskId) {
|
|
6835
|
+
tools.RecommendPlan = createRecommendPlanTool({
|
|
6836
|
+
cfg,
|
|
6837
|
+
taskId: options.taskId
|
|
6838
|
+
});
|
|
6839
|
+
tools.UpsertWebIdePlan = createUpsertWebIdePlanTool({
|
|
6840
|
+
cfg,
|
|
6841
|
+
taskId: options.taskId
|
|
6842
|
+
});
|
|
6843
|
+
}
|
|
6844
|
+
return tools;
|
|
6721
6845
|
}
|
|
6722
6846
|
function withPlanModeToolHint(prompt, mode) {
|
|
6723
6847
|
if (mode !== "plan") {
|
|
@@ -6808,7 +6932,9 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
6808
6932
|
const customTools = createCursorCustomTools(cfg, ctx.messageId, {
|
|
6809
6933
|
onAskQuestion: options?.onAskQuestion,
|
|
6810
6934
|
appendMessageContent: options?.appendMessageContent,
|
|
6811
|
-
askQuestionExecute: options?.askQuestionExecute
|
|
6935
|
+
askQuestionExecute: options?.askQuestionExecute,
|
|
6936
|
+
enableWebIdePlanTools: options?.enableWebIdePlanTools,
|
|
6937
|
+
taskId: options?.taskId
|
|
6812
6938
|
});
|
|
6813
6939
|
const prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
6814
6940
|
console.log(
|
|
@@ -6877,6 +7003,15 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
6877
7003
|
}
|
|
6878
7004
|
await syncRemoteLog.flush(eventSession);
|
|
6879
7005
|
const result = await run.wait();
|
|
7006
|
+
if (result.usage) {
|
|
7007
|
+
eventSession.addRunUsage(result.usage, {
|
|
7008
|
+
durationMs: result.durationMs
|
|
7009
|
+
});
|
|
7010
|
+
await syncRemoteLog.flush(eventSession);
|
|
7011
|
+
console.log(
|
|
7012
|
+
`[apm] Cursor usage total=${result.usage.totalTokens} in=${result.usage.inputTokens} out=${result.usage.outputTokens} cache=${result.usage.cacheReadTokens}/${result.usage.cacheWriteTokens}`
|
|
7013
|
+
);
|
|
7014
|
+
}
|
|
6880
7015
|
if (result.status === "error") {
|
|
6881
7016
|
const failureMessage = formatCursorRunFailure(result.id, {
|
|
6882
7017
|
statusError: lastRunErrorStatus,
|
|
@@ -6913,6 +7048,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
6913
7048
|
status: result.status,
|
|
6914
7049
|
result: result.result,
|
|
6915
7050
|
durationMs: result.durationMs,
|
|
7051
|
+
usage: result.usage,
|
|
6916
7052
|
assistantText: eventSession.getAssistantText(),
|
|
6917
7053
|
createPlan: eventSession.getCreatePlanContent(),
|
|
6918
7054
|
artifacts,
|
|
@@ -88,6 +88,14 @@ var requestConfig = {
|
|
|
88
88
|
method: "GET",
|
|
89
89
|
path: "/cli/webide/assumptions"
|
|
90
90
|
}),
|
|
91
|
+
webideRecommendPlan: defineEndpoint({
|
|
92
|
+
method: "PUT",
|
|
93
|
+
path: "/cli/webide/plan-recommendation"
|
|
94
|
+
}),
|
|
95
|
+
webideUpsertPlan: defineEndpoint({
|
|
96
|
+
method: "PUT",
|
|
97
|
+
path: "/cli/webide/plan"
|
|
98
|
+
}),
|
|
91
99
|
branchBaseline: defineEndpoint({
|
|
92
100
|
method: "GET",
|
|
93
101
|
path: "/cli/tasks/branch-baseline"
|
|
@@ -289,6 +297,16 @@ function formatPlanMarkdown(raw) {
|
|
|
289
297
|
}
|
|
290
298
|
|
|
291
299
|
// src/session-utils.ts
|
|
300
|
+
function serializeTokenUsage(usage) {
|
|
301
|
+
return {
|
|
302
|
+
inputTokens: usage.inputTokens,
|
|
303
|
+
outputTokens: usage.outputTokens,
|
|
304
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
305
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
306
|
+
totalTokens: usage.totalTokens,
|
|
307
|
+
...usage.reasoningTokens != null ? { reasoningTokens: usage.reasoningTokens } : {}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
292
310
|
var EventSession = class {
|
|
293
311
|
events = [];
|
|
294
312
|
dirtyIndices = /* @__PURE__ */ new Set();
|
|
@@ -327,7 +345,7 @@ var EventSession = class {
|
|
|
327
345
|
if (formatedEvent.type === "status") {
|
|
328
346
|
return;
|
|
329
347
|
}
|
|
330
|
-
if (formatedEvent.type === "request") {
|
|
348
|
+
if (formatedEvent.type === "request" || formatedEvent.type === "usage") {
|
|
331
349
|
this.events.push(formatedEvent);
|
|
332
350
|
this.markDirty(this.events.length - 1);
|
|
333
351
|
return;
|
|
@@ -351,6 +369,16 @@ var EventSession = class {
|
|
|
351
369
|
this.events.push(formatedEvent);
|
|
352
370
|
this.markDirty(this.events.length - 1);
|
|
353
371
|
}
|
|
372
|
+
/** 写入 run.wait() 返回的累计 TokenUsage(整次 run 汇总) */
|
|
373
|
+
addRunUsage(usage, options) {
|
|
374
|
+
this.events.push({
|
|
375
|
+
type: "usage",
|
|
376
|
+
scope: "run",
|
|
377
|
+
usage: serializeTokenUsage(usage),
|
|
378
|
+
...options?.durationMs != null ? { durationMs: options.durationMs } : {}
|
|
379
|
+
});
|
|
380
|
+
this.markDirty(this.events.length - 1);
|
|
381
|
+
}
|
|
354
382
|
formatEvent(event) {
|
|
355
383
|
switch (event.type) {
|
|
356
384
|
case "assistant": {
|
|
@@ -385,6 +413,12 @@ var EventSession = class {
|
|
|
385
413
|
status: event.status,
|
|
386
414
|
text: event.text
|
|
387
415
|
};
|
|
416
|
+
case "usage":
|
|
417
|
+
return {
|
|
418
|
+
type: "usage",
|
|
419
|
+
scope: "turn",
|
|
420
|
+
usage: serializeTokenUsage(event.usage)
|
|
421
|
+
};
|
|
388
422
|
case "request":
|
|
389
423
|
return {
|
|
390
424
|
...event,
|
|
@@ -459,6 +493,16 @@ ${String(event.content ?? "")}
|
|
|
459
493
|
if (type === "tool_call") {
|
|
460
494
|
return "````toolcall\n" + JSON.stringify(event, null, 2) + "\n````\n";
|
|
461
495
|
}
|
|
496
|
+
if (type === "usage") {
|
|
497
|
+
const usage = event.usage;
|
|
498
|
+
const scope = event.scope === "run" ? "\u7D2F\u8BA1" : "\u672C\u8F6E";
|
|
499
|
+
return `## Token \u4F7F\u7528\u91CF\uFF08${scope}\uFF09
|
|
500
|
+
|
|
501
|
+
\`\`\`json
|
|
502
|
+
${JSON.stringify(usage ?? event, null, 2)}
|
|
503
|
+
\`\`\`
|
|
504
|
+
`;
|
|
505
|
+
}
|
|
462
506
|
return `## \u672A\u77E5\u4E8B\u4EF6\uFF1A${type}
|
|
463
507
|
|
|
464
508
|
\`\`\`json
|
|
@@ -944,13 +988,82 @@ ${payload}`;
|
|
|
944
988
|
};
|
|
945
989
|
}
|
|
946
990
|
|
|
991
|
+
// src/commands/connect/webide-plan-tools.ts
|
|
992
|
+
function asString(value) {
|
|
993
|
+
return typeof value === "string" ? value.trim() : "";
|
|
994
|
+
}
|
|
995
|
+
function createRecommendPlanTool(options) {
|
|
996
|
+
const { cfg, taskId } = options;
|
|
997
|
+
return {
|
|
998
|
+
description: "Recommend whether the human should write an implementation plan or skip it. Does not change workflow phase; the human decides in the WebIDE UI.",
|
|
999
|
+
inputSchema: {
|
|
1000
|
+
type: "object",
|
|
1001
|
+
properties: {
|
|
1002
|
+
recommendation: {
|
|
1003
|
+
type: "string",
|
|
1004
|
+
enum: ["write", "skip", "unknown"],
|
|
1005
|
+
description: "write = suggest generating a plan; skip = plan optional/unnecessary; unknown = unsure"
|
|
1006
|
+
},
|
|
1007
|
+
reason: {
|
|
1008
|
+
type: "string",
|
|
1009
|
+
description: "Short Chinese reason for the recommendation"
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
required: ["recommendation"]
|
|
1013
|
+
},
|
|
1014
|
+
execute: async (args) => {
|
|
1015
|
+
const raw = asString(args.recommendation);
|
|
1016
|
+
const recommendation = raw === "write" || raw === "skip" || raw === "unknown" ? raw : "unknown";
|
|
1017
|
+
const reason = asString(args.reason) || void 0;
|
|
1018
|
+
const api = createApmApiClient(cfg);
|
|
1019
|
+
await api.cli.webideRecommendPlan({
|
|
1020
|
+
taskId,
|
|
1021
|
+
recommendation,
|
|
1022
|
+
reason
|
|
1023
|
+
});
|
|
1024
|
+
console.log(
|
|
1025
|
+
`[apm] RecommendPlan taskId=${taskId} recommendation=${recommendation}`
|
|
1026
|
+
);
|
|
1027
|
+
return JSON.stringify({ ok: true, recommendation, reason }, null, 2);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
function createUpsertWebIdePlanTool(options) {
|
|
1032
|
+
const { cfg, taskId } = options;
|
|
1033
|
+
return {
|
|
1034
|
+
description: "Persist the implementation plan markdown for this WebIDE task and mark the plan as ready for human confirmation. Call once with the full plan document.",
|
|
1035
|
+
inputSchema: {
|
|
1036
|
+
type: "object",
|
|
1037
|
+
properties: {
|
|
1038
|
+
content: {
|
|
1039
|
+
type: "string",
|
|
1040
|
+
description: "Full implementation plan in Markdown (Chinese)"
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
required: ["content"]
|
|
1044
|
+
},
|
|
1045
|
+
execute: async (args) => {
|
|
1046
|
+
const content = asString(args.content);
|
|
1047
|
+
if (!content) {
|
|
1048
|
+
throw new Error("UpsertWebIdePlan \u7F3A\u5C11 content");
|
|
1049
|
+
}
|
|
1050
|
+
const api = createApmApiClient(cfg);
|
|
1051
|
+
await api.cli.webideUpsertPlan({ taskId, content });
|
|
1052
|
+
console.log(
|
|
1053
|
+
`[apm] UpsertWebIdePlan taskId=${taskId} chars=${content.length}`
|
|
1054
|
+
);
|
|
1055
|
+
return JSON.stringify({ ok: true, chars: content.length }, null, 2);
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
|
|
947
1060
|
// src/commands/connect/cursor-custom-tools.ts
|
|
948
1061
|
var PLAN_MODE_ASK_QUESTION_HINT = `[SDK \u73AF\u5883\u8BF4\u660E]
|
|
949
1062
|
AskQuestion \u5DF2\u901A\u8FC7 MCP \u670D\u52A1\u5668 custom-user-tools \u6CE8\u518C\uFF0C\u5DE5\u5177\u540D\u4E3A AskQuestion\u3002
|
|
950
1063
|
\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
|
|
951
1064
|
\u975E\u5FC5\u987B\u7684\u95EE\u9898\u53EF\u8DF3\u8FC7\uFF0C\u76F4\u63A5\u5B8C\u6210 createPlan\u3002`;
|
|
952
1065
|
function createCursorCustomTools(cfg, messageId, options) {
|
|
953
|
-
|
|
1066
|
+
const tools = {
|
|
954
1067
|
...createAppendMessageCustomTools(
|
|
955
1068
|
cfg,
|
|
956
1069
|
messageId,
|
|
@@ -961,6 +1074,17 @@ function createCursorCustomTools(cfg, messageId, options) {
|
|
|
961
1074
|
execute: options?.askQuestionExecute
|
|
962
1075
|
})
|
|
963
1076
|
};
|
|
1077
|
+
if (options?.enableWebIdePlanTools && options.taskId) {
|
|
1078
|
+
tools.RecommendPlan = createRecommendPlanTool({
|
|
1079
|
+
cfg,
|
|
1080
|
+
taskId: options.taskId
|
|
1081
|
+
});
|
|
1082
|
+
tools.UpsertWebIdePlan = createUpsertWebIdePlanTool({
|
|
1083
|
+
cfg,
|
|
1084
|
+
taskId: options.taskId
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
return tools;
|
|
964
1088
|
}
|
|
965
1089
|
function withPlanModeToolHint(prompt, mode) {
|
|
966
1090
|
if (mode !== "plan") {
|
|
@@ -1051,7 +1175,9 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1051
1175
|
const customTools = createCursorCustomTools(cfg, ctx.messageId, {
|
|
1052
1176
|
onAskQuestion: options?.onAskQuestion,
|
|
1053
1177
|
appendMessageContent: options?.appendMessageContent,
|
|
1054
|
-
askQuestionExecute: options?.askQuestionExecute
|
|
1178
|
+
askQuestionExecute: options?.askQuestionExecute,
|
|
1179
|
+
enableWebIdePlanTools: options?.enableWebIdePlanTools,
|
|
1180
|
+
taskId: options?.taskId
|
|
1055
1181
|
});
|
|
1056
1182
|
const prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
1057
1183
|
console.log(
|
|
@@ -1120,6 +1246,15 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1120
1246
|
}
|
|
1121
1247
|
await syncRemoteLog.flush(eventSession);
|
|
1122
1248
|
const result = await run.wait();
|
|
1249
|
+
if (result.usage) {
|
|
1250
|
+
eventSession.addRunUsage(result.usage, {
|
|
1251
|
+
durationMs: result.durationMs
|
|
1252
|
+
});
|
|
1253
|
+
await syncRemoteLog.flush(eventSession);
|
|
1254
|
+
console.log(
|
|
1255
|
+
`[apm] Cursor usage total=${result.usage.totalTokens} in=${result.usage.inputTokens} out=${result.usage.outputTokens} cache=${result.usage.cacheReadTokens}/${result.usage.cacheWriteTokens}`
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1123
1258
|
if (result.status === "error") {
|
|
1124
1259
|
const failureMessage = formatCursorRunFailure(result.id, {
|
|
1125
1260
|
statusError: lastRunErrorStatus,
|
|
@@ -1156,6 +1291,7 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1156
1291
|
status: result.status,
|
|
1157
1292
|
result: result.result,
|
|
1158
1293
|
durationMs: result.durationMs,
|
|
1294
|
+
usage: result.usage,
|
|
1159
1295
|
assistantText: eventSession.getAssistantText(),
|
|
1160
1296
|
createPlan: eventSession.getCreatePlanContent(),
|
|
1161
1297
|
artifacts,
|
|
@@ -1221,11 +1357,11 @@ function clearWebIdeAgentId(workdir, taskId) {
|
|
|
1221
1357
|
// src/commands/connect/webide-ask-question.ts
|
|
1222
1358
|
import { setTimeout as delay } from "node:timers/promises";
|
|
1223
1359
|
var POLL_INTERVAL_MS = 2e3;
|
|
1224
|
-
function
|
|
1360
|
+
function asString2(value) {
|
|
1225
1361
|
return typeof value === "string" ? value.trim() : "";
|
|
1226
1362
|
}
|
|
1227
1363
|
function parseQuestions(args) {
|
|
1228
|
-
const title =
|
|
1364
|
+
const title = asString2(args.title) || void 0;
|
|
1229
1365
|
const raw = args.questions;
|
|
1230
1366
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
1231
1367
|
throw new Error("AskQuestion \u7F3A\u5C11 questions");
|
|
@@ -1234,16 +1370,16 @@ function parseQuestions(args) {
|
|
|
1234
1370
|
for (const item of raw) {
|
|
1235
1371
|
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
1236
1372
|
const row = item;
|
|
1237
|
-
const id =
|
|
1238
|
-
const prompt =
|
|
1373
|
+
const id = asString2(row.id);
|
|
1374
|
+
const prompt = asString2(row.prompt);
|
|
1239
1375
|
const optionsRaw = row.options;
|
|
1240
1376
|
if (!id || !prompt || !Array.isArray(optionsRaw)) continue;
|
|
1241
1377
|
const options = [];
|
|
1242
1378
|
for (const opt of optionsRaw) {
|
|
1243
1379
|
if (!opt || typeof opt !== "object" || Array.isArray(opt)) continue;
|
|
1244
1380
|
const o = opt;
|
|
1245
|
-
const oid =
|
|
1246
|
-
const label =
|
|
1381
|
+
const oid = asString2(o.id);
|
|
1382
|
+
const label = asString2(o.label);
|
|
1247
1383
|
if (oid && label) options.push({ id: oid, label });
|
|
1248
1384
|
}
|
|
1249
1385
|
if (options.length < 2) {
|
|
@@ -1934,6 +2070,8 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
|
|
|
1934
2070
|
taskId,
|
|
1935
2071
|
signal
|
|
1936
2072
|
}),
|
|
2073
|
+
enableWebIdePlanTools: true,
|
|
2074
|
+
taskId,
|
|
1937
2075
|
createRemoteLogSync: (agentId) => {
|
|
1938
2076
|
saveWebIdeAgentId(workdir, taskId, agentId);
|
|
1939
2077
|
logSyncRef.current = createThrottledWebIdeMessageLogSync(
|
|
@@ -1978,6 +2116,19 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
|
|
|
1978
2116
|
id: messageId,
|
|
1979
2117
|
content: fallback
|
|
1980
2118
|
});
|
|
2119
|
+
if (msg.action === "write-plan" && outcome.createPlan && outcome.createPlan.trim()) {
|
|
2120
|
+
try {
|
|
2121
|
+
await api.cli.webideUpsertPlan({
|
|
2122
|
+
taskId,
|
|
2123
|
+
content: outcome.createPlan.trim()
|
|
2124
|
+
});
|
|
2125
|
+
} catch (err) {
|
|
2126
|
+
console.warn(
|
|
2127
|
+
"[apm] write-plan \u8865\u5199\u8BA1\u5212\u5931\u8D25:",
|
|
2128
|
+
err instanceof Error ? err.message : err
|
|
2129
|
+
);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
1981
2132
|
await logSyncRef.current?.markRun(outcome.runId, "finished");
|
|
1982
2133
|
await updateStatus(cfg, messageId, "SUCCESS");
|
|
1983
2134
|
console.log(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-project-manage-cli",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.3",
|
|
4
4
|
"description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@bufbuild/protobuf": "1.10.0",
|
|
36
36
|
"@connectrpc/connect": "~1.7.0",
|
|
37
37
|
"@connectrpc/connect-node": "~1.7.0",
|
|
38
|
-
"@cursor/sdk": "
|
|
38
|
+
"@cursor/sdk": "^1.0.22",
|
|
39
39
|
"ws": "~8.18.0",
|
|
40
40
|
"listpage-http": "~0.0.318",
|
|
41
41
|
"commander": "~14.0.3",
|