ai-project-manage-cli 7.1.1 → 7.1.2
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 +155 -87
- package/dist/webide-message-worker.js +153 -43
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -449,6 +449,14 @@ var requestConfig = {
|
|
|
449
449
|
method: "PUT",
|
|
450
450
|
path: "/cli/webide/message-logs"
|
|
451
451
|
}),
|
|
452
|
+
webideReplaceAssumptions: defineEndpoint({
|
|
453
|
+
method: "PUT",
|
|
454
|
+
path: "/cli/webide/assumptions"
|
|
455
|
+
}),
|
|
456
|
+
webideListAssumptions: defineEndpoint({
|
|
457
|
+
method: "GET",
|
|
458
|
+
path: "/cli/webide/assumptions"
|
|
459
|
+
}),
|
|
452
460
|
branchBaseline: defineEndpoint({
|
|
453
461
|
method: "GET",
|
|
454
462
|
path: "/cli/tasks/branch-baseline"
|
|
@@ -2719,13 +2727,32 @@ function validateSessionCacheCleanupPush(o) {
|
|
|
2719
2727
|
}
|
|
2720
2728
|
};
|
|
2721
2729
|
}
|
|
2730
|
+
function validateWebIdeCacheCleanupPush(o) {
|
|
2731
|
+
if (o.type !== "webide-cache-cleanup") {
|
|
2732
|
+
return { ok: false, reason: "\u671F\u671B webide-cache-cleanup" };
|
|
2733
|
+
}
|
|
2734
|
+
if (!nonEmptyString(o.taskId)) {
|
|
2735
|
+
return { ok: false, reason: "webide-cache-cleanup \u7F3A\u5C11 taskId" };
|
|
2736
|
+
}
|
|
2737
|
+
if (!nonEmptyString(o.workdir)) {
|
|
2738
|
+
return { ok: false, reason: "webide-cache-cleanup \u7F3A\u5C11 workdir" };
|
|
2739
|
+
}
|
|
2740
|
+
return {
|
|
2741
|
+
ok: true,
|
|
2742
|
+
data: {
|
|
2743
|
+
type: "webide-cache-cleanup",
|
|
2744
|
+
taskId: o.taskId.trim(),
|
|
2745
|
+
workdir: o.workdir.trim()
|
|
2746
|
+
}
|
|
2747
|
+
};
|
|
2748
|
+
}
|
|
2722
2749
|
function validateAgentWsMessage(value, kind) {
|
|
2723
2750
|
if (typeof value !== "object" || value === null) {
|
|
2724
2751
|
return { ok: false, reason: "\u6D88\u606F\u4F53\u4E0D\u662F JSON \u5BF9\u8C61" };
|
|
2725
2752
|
}
|
|
2726
2753
|
const o = value;
|
|
2727
2754
|
const type = o.type;
|
|
2728
|
-
if (type !== "heartbeat" && type !== "message" && type !== "webide-message" && type !== "cancel" && type !== "deploy" && type !== "session-cache-cleanup") {
|
|
2755
|
+
if (type !== "heartbeat" && type !== "message" && type !== "webide-message" && type !== "cancel" && type !== "deploy" && type !== "session-cache-cleanup" && type !== "webide-cache-cleanup") {
|
|
2729
2756
|
return { ok: false, reason: `\u672A\u77E5 type: ${String(type)}` };
|
|
2730
2757
|
}
|
|
2731
2758
|
if (kind === "heartbeat" || type === "heartbeat") {
|
|
@@ -2740,6 +2767,9 @@ function validateAgentWsMessage(value, kind) {
|
|
|
2740
2767
|
if (type === "session-cache-cleanup") {
|
|
2741
2768
|
return validateSessionCacheCleanupPush(o);
|
|
2742
2769
|
}
|
|
2770
|
+
if (type === "webide-cache-cleanup") {
|
|
2771
|
+
return validateWebIdeCacheCleanupPush(o);
|
|
2772
|
+
}
|
|
2743
2773
|
if (type === "webide-message") {
|
|
2744
2774
|
return validateWebIdeMessagePush(o);
|
|
2745
2775
|
}
|
|
@@ -3194,14 +3224,14 @@ var MinioClient = class {
|
|
|
3194
3224
|
async deleteObjectsByPrefix(bucket, prefix) {
|
|
3195
3225
|
const objectsStream = this.inner.listObjectsV2(bucket, prefix, true);
|
|
3196
3226
|
const keys = [];
|
|
3197
|
-
await new Promise((
|
|
3227
|
+
await new Promise((resolve7, reject) => {
|
|
3198
3228
|
objectsStream.on("data", (obj) => {
|
|
3199
3229
|
if (obj.name) {
|
|
3200
3230
|
keys.push(obj.name);
|
|
3201
3231
|
}
|
|
3202
3232
|
});
|
|
3203
3233
|
objectsStream.on("error", reject);
|
|
3204
|
-
objectsStream.on("end",
|
|
3234
|
+
objectsStream.on("end", resolve7);
|
|
3205
3235
|
});
|
|
3206
3236
|
const chunkSize = 500;
|
|
3207
3237
|
for (let i = 0; i < keys.length; i += chunkSize) {
|
|
@@ -4661,7 +4691,7 @@ function buildSftpConnectOptions(settings) {
|
|
|
4661
4691
|
};
|
|
4662
4692
|
}
|
|
4663
4693
|
async function sleep(ms) {
|
|
4664
|
-
await new Promise((
|
|
4694
|
+
await new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
4665
4695
|
}
|
|
4666
4696
|
async function uploadZipWithRetry(settings, localZip, remoteZipPath) {
|
|
4667
4697
|
let lastError;
|
|
@@ -4705,7 +4735,7 @@ async function ensureRemoteDir(sftp, dir) {
|
|
|
4705
4735
|
}
|
|
4706
4736
|
}
|
|
4707
4737
|
function execCommand(client, command) {
|
|
4708
|
-
return new Promise((
|
|
4738
|
+
return new Promise((resolve7, reject) => {
|
|
4709
4739
|
client.exec(command, (err, stream) => {
|
|
4710
4740
|
if (err) return reject(err);
|
|
4711
4741
|
let stdout = "";
|
|
@@ -4715,7 +4745,7 @@ function execCommand(client, command) {
|
|
|
4715
4745
|
reject(new Error(`\u8FDC\u7A0B\u547D\u4EE4\u5931\u8D25 (${code}): ${stderr || stdout}`));
|
|
4716
4746
|
return;
|
|
4717
4747
|
}
|
|
4718
|
-
|
|
4748
|
+
resolve7(stdout);
|
|
4719
4749
|
}).on("data", (data) => {
|
|
4720
4750
|
stdout += data.toString();
|
|
4721
4751
|
});
|
|
@@ -5190,8 +5220,8 @@ function springbootOutputIndicatesSuccess(action, combined) {
|
|
|
5190
5220
|
async function connectSsh(config) {
|
|
5191
5221
|
const client = new Client2();
|
|
5192
5222
|
log(`\u8FDE\u63A5\u670D\u52A1\u5668 ${config.username}@${config.host}:${config.port}`);
|
|
5193
|
-
await new Promise((
|
|
5194
|
-
client.on("ready", () =>
|
|
5223
|
+
await new Promise((resolve7, reject) => {
|
|
5224
|
+
client.on("ready", () => resolve7()).on("error", (err) => reject(err)).connect({
|
|
5195
5225
|
host: config.host,
|
|
5196
5226
|
port: config.port,
|
|
5197
5227
|
username: config.username,
|
|
@@ -5259,7 +5289,7 @@ async function runRemoteCommand(client, command, options) {
|
|
|
5259
5289
|
const check = options?.check ?? true;
|
|
5260
5290
|
const stream = options?.stream ?? false;
|
|
5261
5291
|
const label = options?.label ?? "\u8FDC\u7A0B\u547D\u4EE4";
|
|
5262
|
-
return new Promise((
|
|
5292
|
+
return new Promise((resolve7, reject) => {
|
|
5263
5293
|
client.exec(command, (err, execStream) => {
|
|
5264
5294
|
if (err) {
|
|
5265
5295
|
reject(err);
|
|
@@ -5289,7 +5319,7 @@ ${errText}`.trim();
|
|
|
5289
5319
|
\u8F93\u51FA: ${combined}` : "")
|
|
5290
5320
|
);
|
|
5291
5321
|
}
|
|
5292
|
-
|
|
5322
|
+
resolve7({ exitCode: code, out: out.trim(), err: errText.trim() });
|
|
5293
5323
|
});
|
|
5294
5324
|
});
|
|
5295
5325
|
});
|
|
@@ -6164,6 +6194,24 @@ function cleanSessionWorkspaceCache(sessionId, workdir) {
|
|
|
6164
6194
|
clearPreStepCacheForSession(trimmedSessionId, trimmedWorkdir);
|
|
6165
6195
|
}
|
|
6166
6196
|
|
|
6197
|
+
// src/commands/clean-webide-cache.ts
|
|
6198
|
+
import { existsSync as existsSync22, rmSync as rmSync5 } from "node:fs";
|
|
6199
|
+
import { resolve as resolve5 } from "node:path";
|
|
6200
|
+
function cleanWebIdeWorkspaceCache(taskId, workdir) {
|
|
6201
|
+
const trimmedTaskId = taskId.trim();
|
|
6202
|
+
const trimmedWorkdir = workdir.trim();
|
|
6203
|
+
if (!trimmedTaskId || !trimmedWorkdir) {
|
|
6204
|
+
return;
|
|
6205
|
+
}
|
|
6206
|
+
const dir = resolve5(trimmedWorkdir, ".apm", "webide", trimmedTaskId);
|
|
6207
|
+
if (existsSync22(dir)) {
|
|
6208
|
+
rmSync5(dir, { recursive: true, force: true });
|
|
6209
|
+
console.log(`[apm] \u5DF2\u6E05\u7406 WebIDE \u7F13\u5B58 ${dir}`);
|
|
6210
|
+
} else {
|
|
6211
|
+
console.log(`[apm] WebIDE \u7F13\u5B58\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7 ${dir}`);
|
|
6212
|
+
}
|
|
6213
|
+
}
|
|
6214
|
+
|
|
6167
6215
|
// src/commands/connect/abort-signal-debug.ts
|
|
6168
6216
|
import {
|
|
6169
6217
|
getEventListeners,
|
|
@@ -6434,13 +6482,13 @@ ${JSON.stringify(event, null, 2)}
|
|
|
6434
6482
|
}
|
|
6435
6483
|
|
|
6436
6484
|
// src/commands/connect/agent-session-registry.ts
|
|
6437
|
-
import { existsSync as
|
|
6438
|
-
import { dirname as dirname6, resolve as
|
|
6485
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
|
|
6486
|
+
import { dirname as dirname6, resolve as resolve6 } from "node:path";
|
|
6439
6487
|
function registryPath(workdir, sessionId) {
|
|
6440
|
-
return
|
|
6488
|
+
return resolve6(workdir, ".apm", "sessions", sessionId, "cursor-agents.json");
|
|
6441
6489
|
}
|
|
6442
6490
|
function readRegistry(path19) {
|
|
6443
|
-
if (!
|
|
6491
|
+
if (!existsSync23(path19)) {
|
|
6444
6492
|
return {};
|
|
6445
6493
|
}
|
|
6446
6494
|
try {
|
|
@@ -6600,50 +6648,54 @@ function createAppendMessageCustomTools(cfg, messageId, appendContent) {
|
|
|
6600
6648
|
}
|
|
6601
6649
|
|
|
6602
6650
|
// src/commands/connect/ask-question-tool.ts
|
|
6603
|
-
|
|
6651
|
+
var INPUT_SCHEMA = {
|
|
6652
|
+
type: "object",
|
|
6653
|
+
properties: {
|
|
6654
|
+
title: {
|
|
6655
|
+
type: "string",
|
|
6656
|
+
description: "Optional title for the questions form"
|
|
6657
|
+
},
|
|
6658
|
+
questions: {
|
|
6659
|
+
type: "array",
|
|
6660
|
+
minItems: 1,
|
|
6661
|
+
items: {
|
|
6662
|
+
type: "object",
|
|
6663
|
+
properties: {
|
|
6664
|
+
id: { type: "string" },
|
|
6665
|
+
prompt: { type: "string" },
|
|
6666
|
+
allow_multiple: { type: "boolean" },
|
|
6667
|
+
options: {
|
|
6668
|
+
type: "array",
|
|
6669
|
+
minItems: 2,
|
|
6670
|
+
items: {
|
|
6671
|
+
type: "object",
|
|
6672
|
+
properties: {
|
|
6673
|
+
id: { type: "string" },
|
|
6674
|
+
label: { type: "string" }
|
|
6675
|
+
},
|
|
6676
|
+
required: ["id", "label"]
|
|
6677
|
+
}
|
|
6678
|
+
}
|
|
6679
|
+
},
|
|
6680
|
+
required: ["id", "prompt", "options"]
|
|
6681
|
+
}
|
|
6682
|
+
}
|
|
6683
|
+
},
|
|
6684
|
+
required: ["questions"]
|
|
6685
|
+
};
|
|
6686
|
+
function createAskQuestionTool(options) {
|
|
6604
6687
|
return {
|
|
6605
6688
|
description: "Collect structured multiple-choice answers from the user. Use when blocked on a decision that is genuinely the user's to make.",
|
|
6606
|
-
inputSchema:
|
|
6607
|
-
type: "object",
|
|
6608
|
-
properties: {
|
|
6609
|
-
title: {
|
|
6610
|
-
type: "string",
|
|
6611
|
-
description: "Optional title for the questions form"
|
|
6612
|
-
},
|
|
6613
|
-
questions: {
|
|
6614
|
-
type: "array",
|
|
6615
|
-
minItems: 1,
|
|
6616
|
-
items: {
|
|
6617
|
-
type: "object",
|
|
6618
|
-
properties: {
|
|
6619
|
-
id: { type: "string" },
|
|
6620
|
-
prompt: { type: "string" },
|
|
6621
|
-
allow_multiple: { type: "boolean" },
|
|
6622
|
-
options: {
|
|
6623
|
-
type: "array",
|
|
6624
|
-
minItems: 2,
|
|
6625
|
-
items: {
|
|
6626
|
-
type: "object",
|
|
6627
|
-
properties: {
|
|
6628
|
-
id: { type: "string" },
|
|
6629
|
-
label: { type: "string" }
|
|
6630
|
-
},
|
|
6631
|
-
required: ["id", "label"]
|
|
6632
|
-
}
|
|
6633
|
-
}
|
|
6634
|
-
},
|
|
6635
|
-
required: ["id", "prompt", "options"]
|
|
6636
|
-
}
|
|
6637
|
-
}
|
|
6638
|
-
},
|
|
6639
|
-
required: ["questions"]
|
|
6640
|
-
},
|
|
6689
|
+
inputSchema: INPUT_SCHEMA,
|
|
6641
6690
|
execute: async (args) => {
|
|
6691
|
+
options?.onInvoke?.(args);
|
|
6692
|
+
if (options?.execute) {
|
|
6693
|
+
return options.execute(args);
|
|
6694
|
+
}
|
|
6642
6695
|
const payload = JSON.stringify(args, null, 2);
|
|
6643
|
-
console.log(`[apm] AskQuestion
|
|
6696
|
+
console.log(`[apm] AskQuestion\uFF08\u672C\u5730\u5360\u4F4D\uFF0C\u672A\u7B49\u5F85\u7528\u6237\uFF09:
|
|
6644
6697
|
${payload}`);
|
|
6645
|
-
|
|
6646
|
-
return `[mock] AskQuestion \u5DF2\u8BB0\u5F55\uFF08\u672A\u521B\u5EFA\u4EFB\u52A1\u95EE\u9898\u3001\u672A\u7B49\u5F85\u7528\u6237\u56DE\u7B54\uFF09\u3002\u53C2\u6570:
|
|
6698
|
+
return `[local] AskQuestion \u5DF2\u8BB0\u5F55\uFF08\u672A\u521B\u5EFA\u4EFB\u52A1\u95EE\u9898\u3001\u672A\u7B49\u5F85\u7528\u6237\u56DE\u7B54\uFF09\u3002\u53C2\u6570:
|
|
6647
6699
|
${payload}`;
|
|
6648
6700
|
}
|
|
6649
6701
|
};
|
|
@@ -6661,8 +6713,9 @@ function createCursorCustomTools(cfg, messageId, options) {
|
|
|
6661
6713
|
messageId,
|
|
6662
6714
|
options?.appendMessageContent
|
|
6663
6715
|
),
|
|
6664
|
-
AskQuestion:
|
|
6665
|
-
onInvoke: options?.onAskQuestion
|
|
6716
|
+
AskQuestion: createAskQuestionTool({
|
|
6717
|
+
onInvoke: options?.onAskQuestion,
|
|
6718
|
+
execute: options?.askQuestionExecute
|
|
6666
6719
|
})
|
|
6667
6720
|
};
|
|
6668
6721
|
}
|
|
@@ -6676,7 +6729,7 @@ ${PLAN_MODE_ASK_QUESTION_HINT}`;
|
|
|
6676
6729
|
}
|
|
6677
6730
|
|
|
6678
6731
|
// src/commands/connect/cursor-agent.ts
|
|
6679
|
-
setMaxListeners2(
|
|
6732
|
+
setMaxListeners2(100);
|
|
6680
6733
|
installAbortSignalDebug();
|
|
6681
6734
|
var noopRemoteLogSync = {
|
|
6682
6735
|
schedule(_session) {
|
|
@@ -6754,7 +6807,8 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
6754
6807
|
const workdir = resolveWorkdirPath(ctx.workdir);
|
|
6755
6808
|
const customTools = createCursorCustomTools(cfg, ctx.messageId, {
|
|
6756
6809
|
onAskQuestion: options?.onAskQuestion,
|
|
6757
|
-
appendMessageContent: options?.appendMessageContent
|
|
6810
|
+
appendMessageContent: options?.appendMessageContent,
|
|
6811
|
+
askQuestionExecute: options?.askQuestionExecute
|
|
6758
6812
|
});
|
|
6759
6813
|
const prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
6760
6814
|
console.log(
|
|
@@ -6919,7 +6973,7 @@ async function ensureMessageHasReply(cfg, sessionId, messageId, fallback) {
|
|
|
6919
6973
|
}
|
|
6920
6974
|
|
|
6921
6975
|
// src/commands/connect/cli-version-sync.ts
|
|
6922
|
-
import { existsSync as
|
|
6976
|
+
import { existsSync as existsSync24, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
6923
6977
|
import { join as join18 } from "path";
|
|
6924
6978
|
var CLI_VERSION_FILE = ".cli-version.json";
|
|
6925
6979
|
function manifestPath(apmDir) {
|
|
@@ -6927,7 +6981,7 @@ function manifestPath(apmDir) {
|
|
|
6927
6981
|
}
|
|
6928
6982
|
function loadManifest4(apmDir) {
|
|
6929
6983
|
const path19 = toFsPath(manifestPath(apmDir));
|
|
6930
|
-
if (!
|
|
6984
|
+
if (!existsSync24(path19)) {
|
|
6931
6985
|
return null;
|
|
6932
6986
|
}
|
|
6933
6987
|
try {
|
|
@@ -6997,7 +7051,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
6997
7051
|
);
|
|
6998
7052
|
}
|
|
6999
7053
|
const queuedAt = Date.now();
|
|
7000
|
-
return new Promise((
|
|
7054
|
+
return new Promise((resolve7) => {
|
|
7001
7055
|
waiters.push(() => {
|
|
7002
7056
|
active += 1;
|
|
7003
7057
|
const waitedMs = Date.now() - queuedAt;
|
|
@@ -7008,7 +7062,7 @@ function createRunSlotPool(maxConcurrent = DEFAULT_MAX_CONCURRENT, options = {})
|
|
|
7008
7062
|
)}s\uFF0C\u5F53\u524D\u5360\u7528 ${active}/${maxConcurrent}`
|
|
7009
7063
|
);
|
|
7010
7064
|
}
|
|
7011
|
-
|
|
7065
|
+
resolve7();
|
|
7012
7066
|
});
|
|
7013
7067
|
});
|
|
7014
7068
|
};
|
|
@@ -7038,19 +7092,22 @@ function spawnWebIdeMessageWorker(cfg, msg) {
|
|
|
7038
7092
|
workerData: { cfg, msg }
|
|
7039
7093
|
});
|
|
7040
7094
|
let resolveDone;
|
|
7041
|
-
const done = new Promise((
|
|
7042
|
-
resolveDone =
|
|
7095
|
+
const done = new Promise((resolve7) => {
|
|
7096
|
+
resolveDone = resolve7;
|
|
7043
7097
|
});
|
|
7044
|
-
worker.on(
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7098
|
+
worker.on(
|
|
7099
|
+
"message",
|
|
7100
|
+
(m) => {
|
|
7101
|
+
if (m?.type === "done" || m?.type === "error") {
|
|
7102
|
+
if (m.type === "error") {
|
|
7103
|
+
console.error(
|
|
7104
|
+
`[apm] webide worker error messageId=${m.messageId}: ${m.error}`
|
|
7105
|
+
);
|
|
7106
|
+
}
|
|
7107
|
+
void worker.terminate().finally(() => resolveDone());
|
|
7050
7108
|
}
|
|
7051
|
-
void worker.terminate().finally(() => resolveDone());
|
|
7052
7109
|
}
|
|
7053
|
-
|
|
7110
|
+
);
|
|
7054
7111
|
worker.on("error", (err) => {
|
|
7055
7112
|
console.error("[apm] webide worker crashed:", err);
|
|
7056
7113
|
resolveDone();
|
|
@@ -7061,7 +7118,6 @@ function spawnWebIdeMessageWorker(cfg, msg) {
|
|
|
7061
7118
|
}
|
|
7062
7119
|
resolveDone();
|
|
7063
7120
|
});
|
|
7064
|
-
worker.postMessage({ type: "run", cfg, msg });
|
|
7065
7121
|
return {
|
|
7066
7122
|
cancel(messageId) {
|
|
7067
7123
|
worker.postMessage({ type: "cancel", messageId });
|
|
@@ -7228,11 +7284,11 @@ async function handleInboundMessage(cfg, msg, signal, ctx) {
|
|
|
7228
7284
|
}
|
|
7229
7285
|
function interruptibleSleep(ms, signal) {
|
|
7230
7286
|
if (signal.aborted) return Promise.resolve();
|
|
7231
|
-
return new Promise((
|
|
7232
|
-
const timer = setTimeout(
|
|
7287
|
+
return new Promise((resolve7) => {
|
|
7288
|
+
const timer = setTimeout(resolve7, ms);
|
|
7233
7289
|
const onAbort = () => {
|
|
7234
7290
|
clearTimeout(timer);
|
|
7235
|
-
|
|
7291
|
+
resolve7();
|
|
7236
7292
|
};
|
|
7237
7293
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
7238
7294
|
});
|
|
@@ -7324,6 +7380,18 @@ function attachWsHandlers(ws, ctx, onOpen) {
|
|
|
7324
7380
|
});
|
|
7325
7381
|
return;
|
|
7326
7382
|
}
|
|
7383
|
+
if (validated.data.type === "webide-cache-cleanup") {
|
|
7384
|
+
const msg2 = validated.data;
|
|
7385
|
+
const task2 = (async () => {
|
|
7386
|
+
const workdir = requireRemoteWorkdir(msg2.workdir);
|
|
7387
|
+
cleanWebIdeWorkspaceCache(msg2.taskId, workdir);
|
|
7388
|
+
})();
|
|
7389
|
+
activeTasks.add(task2);
|
|
7390
|
+
void task2.finally(() => {
|
|
7391
|
+
activeTasks.delete(task2);
|
|
7392
|
+
});
|
|
7393
|
+
return;
|
|
7394
|
+
}
|
|
7327
7395
|
if (validated.data.type === "webide-message") {
|
|
7328
7396
|
const msg2 = validated.data;
|
|
7329
7397
|
const perMessageController2 = new AbortController();
|
|
@@ -7412,7 +7480,7 @@ function attachWsHandlers(ws, ctx, onOpen) {
|
|
|
7412
7480
|
});
|
|
7413
7481
|
}
|
|
7414
7482
|
function connectOnce(url, ctx, connectionAbort, onConnected) {
|
|
7415
|
-
return new Promise((
|
|
7483
|
+
return new Promise((resolve7, reject) => {
|
|
7416
7484
|
const ws = new WebSocket(url);
|
|
7417
7485
|
let stopHeartbeat;
|
|
7418
7486
|
let settled = false;
|
|
@@ -7441,7 +7509,7 @@ function connectOnce(url, ctx, connectionAbort, onConnected) {
|
|
|
7441
7509
|
finish(() => reject(new Error("shutdown")));
|
|
7442
7510
|
return;
|
|
7443
7511
|
}
|
|
7444
|
-
finish(
|
|
7512
|
+
finish(resolve7);
|
|
7445
7513
|
});
|
|
7446
7514
|
ws.on("error", (err) => {
|
|
7447
7515
|
console.error("[apm] WebSocket \u9519\u8BEF:", err.message);
|
|
@@ -7838,7 +7906,7 @@ import path15 from "node:path";
|
|
|
7838
7906
|
import Docker from "dockerode";
|
|
7839
7907
|
|
|
7840
7908
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/connection-options.ts
|
|
7841
|
-
import { existsSync as
|
|
7909
|
+
import { existsSync as existsSync25, readFileSync as readFileSync18 } from "node:fs";
|
|
7842
7910
|
import path12 from "node:path";
|
|
7843
7911
|
function asOptionalTlsBuffer(value) {
|
|
7844
7912
|
if (typeof value !== "string") {
|
|
@@ -7850,7 +7918,7 @@ function asOptionalTlsBuffer(value) {
|
|
|
7850
7918
|
if (normalized === "") {
|
|
7851
7919
|
return void 0;
|
|
7852
7920
|
}
|
|
7853
|
-
if (
|
|
7921
|
+
if (existsSync25(normalized)) {
|
|
7854
7922
|
return readFileSync18(normalized);
|
|
7855
7923
|
}
|
|
7856
7924
|
const looksLikePath = /[\\/]/.test(normalized) || normalized.endsWith(".pem");
|
|
@@ -7976,17 +8044,17 @@ var DockerodeClient = class {
|
|
|
7976
8044
|
await this.client.getImage(image).remove({ force: true });
|
|
7977
8045
|
}
|
|
7978
8046
|
async pullImage(image, auth) {
|
|
7979
|
-
const stream = await new Promise((
|
|
8047
|
+
const stream = await new Promise((resolve7, reject) => {
|
|
7980
8048
|
const pullOptions = auth ? { authconfig: auth } : void 0;
|
|
7981
8049
|
this.client.pull(image, pullOptions, (err, output) => {
|
|
7982
8050
|
if (err || !output) {
|
|
7983
8051
|
reject(err ?? new Error("docker pull \u8FD4\u56DE\u7A7A\u8F93\u51FA"));
|
|
7984
8052
|
return;
|
|
7985
8053
|
}
|
|
7986
|
-
|
|
8054
|
+
resolve7(output);
|
|
7987
8055
|
});
|
|
7988
8056
|
});
|
|
7989
|
-
await new Promise((
|
|
8057
|
+
await new Promise((resolve7, reject) => {
|
|
7990
8058
|
this.client.modem.followProgress(
|
|
7991
8059
|
stream,
|
|
7992
8060
|
(err) => {
|
|
@@ -7994,7 +8062,7 @@ var DockerodeClient = class {
|
|
|
7994
8062
|
reject(err);
|
|
7995
8063
|
return;
|
|
7996
8064
|
}
|
|
7997
|
-
|
|
8065
|
+
resolve7();
|
|
7998
8066
|
},
|
|
7999
8067
|
() => void 0
|
|
8000
8068
|
);
|
|
@@ -8061,7 +8129,7 @@ var DockerodeClient = class {
|
|
|
8061
8129
|
var createDockerodeClient = (config) => new DockerodeClient(config);
|
|
8062
8130
|
|
|
8063
8131
|
// src/commands/deploy/internal/backend-deploy/dockerode-client/env.ts
|
|
8064
|
-
import { existsSync as
|
|
8132
|
+
import { existsSync as existsSync26, readFileSync as readFileSync19, statSync as statSync10 } from "node:fs";
|
|
8065
8133
|
import path13 from "node:path";
|
|
8066
8134
|
function stripSurroundingQuotes(value) {
|
|
8067
8135
|
const t = value.trim();
|
|
@@ -8078,7 +8146,7 @@ function loadEnvFromFile(envFilePath) {
|
|
|
8078
8146
|
return {};
|
|
8079
8147
|
}
|
|
8080
8148
|
const targetPath = path13.resolve(envFilePath);
|
|
8081
|
-
if (!
|
|
8149
|
+
if (!existsSync26(targetPath) || !statSync10(targetPath).isFile()) {
|
|
8082
8150
|
return {};
|
|
8083
8151
|
}
|
|
8084
8152
|
const raw = readFileSync19(targetPath, "utf-8");
|
|
@@ -8252,12 +8320,12 @@ function dockerPushImage(params, cwd) {
|
|
|
8252
8320
|
}
|
|
8253
8321
|
|
|
8254
8322
|
// src/commands/deploy/internal/backend-deploy/resolve-dockerfile.ts
|
|
8255
|
-
import { existsSync as
|
|
8323
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
8256
8324
|
import path14 from "node:path";
|
|
8257
8325
|
function resolveDockerBuildPaths(cwd) {
|
|
8258
8326
|
const dockerfilePath = path14.join(cwd, "Dockerfile");
|
|
8259
8327
|
Logger.info(`\u67E5\u627EDockerfile\u6587\u4EF6\uFF0C\u8DEF\u5F84: ${dockerfilePath}`);
|
|
8260
|
-
if (!
|
|
8328
|
+
if (!existsSync27(dockerfilePath)) {
|
|
8261
8329
|
throw new Error(`Dockerfile \u4E0D\u5B58\u5728\uFF1A${dockerfilePath}`);
|
|
8262
8330
|
}
|
|
8263
8331
|
Logger.info("\u2713 Dockerfile \u5B58\u5728");
|
|
@@ -80,6 +80,14 @@ var requestConfig = {
|
|
|
80
80
|
method: "PUT",
|
|
81
81
|
path: "/cli/webide/message-logs"
|
|
82
82
|
}),
|
|
83
|
+
webideReplaceAssumptions: defineEndpoint({
|
|
84
|
+
method: "PUT",
|
|
85
|
+
path: "/cli/webide/assumptions"
|
|
86
|
+
}),
|
|
87
|
+
webideListAssumptions: defineEndpoint({
|
|
88
|
+
method: "GET",
|
|
89
|
+
path: "/cli/webide/assumptions"
|
|
90
|
+
}),
|
|
83
91
|
branchBaseline: defineEndpoint({
|
|
84
92
|
method: "GET",
|
|
85
93
|
path: "/cli/tasks/branch-baseline"
|
|
@@ -883,50 +891,54 @@ function createAppendMessageCustomTools(cfg, messageId, appendContent2) {
|
|
|
883
891
|
}
|
|
884
892
|
|
|
885
893
|
// src/commands/connect/ask-question-tool.ts
|
|
886
|
-
|
|
894
|
+
var INPUT_SCHEMA = {
|
|
895
|
+
type: "object",
|
|
896
|
+
properties: {
|
|
897
|
+
title: {
|
|
898
|
+
type: "string",
|
|
899
|
+
description: "Optional title for the questions form"
|
|
900
|
+
},
|
|
901
|
+
questions: {
|
|
902
|
+
type: "array",
|
|
903
|
+
minItems: 1,
|
|
904
|
+
items: {
|
|
905
|
+
type: "object",
|
|
906
|
+
properties: {
|
|
907
|
+
id: { type: "string" },
|
|
908
|
+
prompt: { type: "string" },
|
|
909
|
+
allow_multiple: { type: "boolean" },
|
|
910
|
+
options: {
|
|
911
|
+
type: "array",
|
|
912
|
+
minItems: 2,
|
|
913
|
+
items: {
|
|
914
|
+
type: "object",
|
|
915
|
+
properties: {
|
|
916
|
+
id: { type: "string" },
|
|
917
|
+
label: { type: "string" }
|
|
918
|
+
},
|
|
919
|
+
required: ["id", "label"]
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
},
|
|
923
|
+
required: ["id", "prompt", "options"]
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
},
|
|
927
|
+
required: ["questions"]
|
|
928
|
+
};
|
|
929
|
+
function createAskQuestionTool(options) {
|
|
887
930
|
return {
|
|
888
931
|
description: "Collect structured multiple-choice answers from the user. Use when blocked on a decision that is genuinely the user's to make.",
|
|
889
|
-
inputSchema:
|
|
890
|
-
type: "object",
|
|
891
|
-
properties: {
|
|
892
|
-
title: {
|
|
893
|
-
type: "string",
|
|
894
|
-
description: "Optional title for the questions form"
|
|
895
|
-
},
|
|
896
|
-
questions: {
|
|
897
|
-
type: "array",
|
|
898
|
-
minItems: 1,
|
|
899
|
-
items: {
|
|
900
|
-
type: "object",
|
|
901
|
-
properties: {
|
|
902
|
-
id: { type: "string" },
|
|
903
|
-
prompt: { type: "string" },
|
|
904
|
-
allow_multiple: { type: "boolean" },
|
|
905
|
-
options: {
|
|
906
|
-
type: "array",
|
|
907
|
-
minItems: 2,
|
|
908
|
-
items: {
|
|
909
|
-
type: "object",
|
|
910
|
-
properties: {
|
|
911
|
-
id: { type: "string" },
|
|
912
|
-
label: { type: "string" }
|
|
913
|
-
},
|
|
914
|
-
required: ["id", "label"]
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
},
|
|
918
|
-
required: ["id", "prompt", "options"]
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
},
|
|
922
|
-
required: ["questions"]
|
|
923
|
-
},
|
|
932
|
+
inputSchema: INPUT_SCHEMA,
|
|
924
933
|
execute: async (args) => {
|
|
934
|
+
options?.onInvoke?.(args);
|
|
935
|
+
if (options?.execute) {
|
|
936
|
+
return options.execute(args);
|
|
937
|
+
}
|
|
925
938
|
const payload = JSON.stringify(args, null, 2);
|
|
926
|
-
console.log(`[apm] AskQuestion
|
|
939
|
+
console.log(`[apm] AskQuestion\uFF08\u672C\u5730\u5360\u4F4D\uFF0C\u672A\u7B49\u5F85\u7528\u6237\uFF09:
|
|
927
940
|
${payload}`);
|
|
928
|
-
|
|
929
|
-
return `[mock] AskQuestion \u5DF2\u8BB0\u5F55\uFF08\u672A\u521B\u5EFA\u4EFB\u52A1\u95EE\u9898\u3001\u672A\u7B49\u5F85\u7528\u6237\u56DE\u7B54\uFF09\u3002\u53C2\u6570:
|
|
941
|
+
return `[local] AskQuestion \u5DF2\u8BB0\u5F55\uFF08\u672A\u521B\u5EFA\u4EFB\u52A1\u95EE\u9898\u3001\u672A\u7B49\u5F85\u7528\u6237\u56DE\u7B54\uFF09\u3002\u53C2\u6570:
|
|
930
942
|
${payload}`;
|
|
931
943
|
}
|
|
932
944
|
};
|
|
@@ -944,8 +956,9 @@ function createCursorCustomTools(cfg, messageId, options) {
|
|
|
944
956
|
messageId,
|
|
945
957
|
options?.appendMessageContent
|
|
946
958
|
),
|
|
947
|
-
AskQuestion:
|
|
948
|
-
onInvoke: options?.onAskQuestion
|
|
959
|
+
AskQuestion: createAskQuestionTool({
|
|
960
|
+
onInvoke: options?.onAskQuestion,
|
|
961
|
+
execute: options?.askQuestionExecute
|
|
949
962
|
})
|
|
950
963
|
};
|
|
951
964
|
}
|
|
@@ -959,7 +972,7 @@ ${PLAN_MODE_ASK_QUESTION_HINT}`;
|
|
|
959
972
|
}
|
|
960
973
|
|
|
961
974
|
// src/commands/connect/cursor-agent.ts
|
|
962
|
-
setMaxListeners2(
|
|
975
|
+
setMaxListeners2(100);
|
|
963
976
|
installAbortSignalDebug();
|
|
964
977
|
var noopRemoteLogSync = {
|
|
965
978
|
schedule(_session) {
|
|
@@ -1037,7 +1050,8 @@ async function runCursorAgent(cfg, ctx, options) {
|
|
|
1037
1050
|
const workdir = resolveWorkdirPath(ctx.workdir);
|
|
1038
1051
|
const customTools = createCursorCustomTools(cfg, ctx.messageId, {
|
|
1039
1052
|
onAskQuestion: options?.onAskQuestion,
|
|
1040
|
-
appendMessageContent: options?.appendMessageContent
|
|
1053
|
+
appendMessageContent: options?.appendMessageContent,
|
|
1054
|
+
askQuestionExecute: options?.askQuestionExecute
|
|
1041
1055
|
});
|
|
1042
1056
|
const prompt = withPlanModeToolHint(ctx.prompt, ctx.mode);
|
|
1043
1057
|
console.log(
|
|
@@ -1204,6 +1218,97 @@ function clearWebIdeAgentId(workdir, taskId) {
|
|
|
1204
1218
|
writeRegistry2(path, {});
|
|
1205
1219
|
}
|
|
1206
1220
|
|
|
1221
|
+
// src/commands/connect/webide-ask-question.ts
|
|
1222
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
1223
|
+
var POLL_INTERVAL_MS = 2e3;
|
|
1224
|
+
function asString(value) {
|
|
1225
|
+
return typeof value === "string" ? value.trim() : "";
|
|
1226
|
+
}
|
|
1227
|
+
function parseQuestions(args) {
|
|
1228
|
+
const title = asString(args.title) || void 0;
|
|
1229
|
+
const raw = args.questions;
|
|
1230
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
1231
|
+
throw new Error("AskQuestion \u7F3A\u5C11 questions");
|
|
1232
|
+
}
|
|
1233
|
+
const questions = [];
|
|
1234
|
+
for (const item of raw) {
|
|
1235
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
1236
|
+
const row = item;
|
|
1237
|
+
const id = asString(row.id);
|
|
1238
|
+
const prompt = asString(row.prompt);
|
|
1239
|
+
const optionsRaw = row.options;
|
|
1240
|
+
if (!id || !prompt || !Array.isArray(optionsRaw)) continue;
|
|
1241
|
+
const options = [];
|
|
1242
|
+
for (const opt of optionsRaw) {
|
|
1243
|
+
if (!opt || typeof opt !== "object" || Array.isArray(opt)) continue;
|
|
1244
|
+
const o = opt;
|
|
1245
|
+
const oid = asString(o.id);
|
|
1246
|
+
const label = asString(o.label);
|
|
1247
|
+
if (oid && label) options.push({ id: oid, label });
|
|
1248
|
+
}
|
|
1249
|
+
if (options.length < 2) {
|
|
1250
|
+
throw new Error(`AskQuestion \u95EE\u9898 ${id} \u81F3\u5C11\u9700\u8981 2 \u4E2A\u9009\u9879`);
|
|
1251
|
+
}
|
|
1252
|
+
questions.push({ id, prompt, options });
|
|
1253
|
+
}
|
|
1254
|
+
if (questions.length === 0) {
|
|
1255
|
+
throw new Error("AskQuestion \u65E0\u6709\u6548\u95EE\u9898");
|
|
1256
|
+
}
|
|
1257
|
+
return { title, questions };
|
|
1258
|
+
}
|
|
1259
|
+
function createWebIdeAskQuestionExecute(options) {
|
|
1260
|
+
const { cfg, taskId, signal } = options;
|
|
1261
|
+
return async (args) => {
|
|
1262
|
+
const parsed = parseQuestions(args);
|
|
1263
|
+
const api = createApmApiClient(cfg);
|
|
1264
|
+
console.log(
|
|
1265
|
+
`[apm] AskQuestion \u521B\u5EFA\u5F85\u786E\u8BA4\u9879 taskId=${taskId} count=${parsed.questions.length}`
|
|
1266
|
+
);
|
|
1267
|
+
await api.cli.webideReplaceAssumptions({
|
|
1268
|
+
taskId,
|
|
1269
|
+
title: parsed.title,
|
|
1270
|
+
questions: parsed.questions
|
|
1271
|
+
});
|
|
1272
|
+
while (true) {
|
|
1273
|
+
if (signal?.aborted) {
|
|
1274
|
+
throw new Error("AskQuestion \u5DF2\u53D6\u6D88");
|
|
1275
|
+
}
|
|
1276
|
+
const list = await api.cli.webideListAssumptions({ taskId });
|
|
1277
|
+
const byId = new Map(
|
|
1278
|
+
list.assumptions.map((a) => [a.questionId, a])
|
|
1279
|
+
);
|
|
1280
|
+
const pending = parsed.questions.filter((q) => {
|
|
1281
|
+
const row = byId.get(q.id);
|
|
1282
|
+
return !row || row.status !== "RESOLVED";
|
|
1283
|
+
});
|
|
1284
|
+
if (pending.length === 0) {
|
|
1285
|
+
const answers = parsed.questions.map((q) => {
|
|
1286
|
+
const row = byId.get(q.id);
|
|
1287
|
+
return {
|
|
1288
|
+
questionId: q.id,
|
|
1289
|
+
prompt: q.prompt,
|
|
1290
|
+
selectedOptionId: row.selectedOptionId,
|
|
1291
|
+
customAnswer: row.customAnswer,
|
|
1292
|
+
resolution: row.resolution
|
|
1293
|
+
};
|
|
1294
|
+
});
|
|
1295
|
+
console.log(
|
|
1296
|
+
`[apm] AskQuestion \u7528\u6237\u5DF2\u786E\u8BA4 taskId=${taskId} count=${answers.length}`
|
|
1297
|
+
);
|
|
1298
|
+
return JSON.stringify(
|
|
1299
|
+
{
|
|
1300
|
+
title: parsed.title,
|
|
1301
|
+
answers
|
|
1302
|
+
},
|
|
1303
|
+
null,
|
|
1304
|
+
2
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
await delay(POLL_INTERVAL_MS);
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1207
1312
|
// src/commands/deploy/internal/minio.ts
|
|
1208
1313
|
import * as Minio from "minio";
|
|
1209
1314
|
var MinioClient = class {
|
|
@@ -1824,6 +1929,11 @@ async function handleWebIdeInboundMessage(cfg, msg, signal) {
|
|
|
1824
1929
|
{
|
|
1825
1930
|
signal,
|
|
1826
1931
|
appendMessageContent: (content) => appendContent(cfg, messageId, content),
|
|
1932
|
+
askQuestionExecute: createWebIdeAskQuestionExecute({
|
|
1933
|
+
cfg,
|
|
1934
|
+
taskId,
|
|
1935
|
+
signal
|
|
1936
|
+
}),
|
|
1827
1937
|
createRemoteLogSync: (agentId) => {
|
|
1828
1938
|
saveWebIdeAgentId(workdir, taskId, agentId);
|
|
1829
1939
|
logSyncRef.current = createThrottledWebIdeMessageLogSync(
|