ai-project-manage-cli 4.0.18 → 4.0.19
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 +209 -45
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -374,7 +374,7 @@ async function runComment(requirementId, file, options) {
|
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
// src/commands/connect.ts
|
|
377
|
-
import { randomUUID } from "crypto";
|
|
377
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
378
378
|
import WebSocket from "ws";
|
|
379
379
|
import { Agent } from "@cursor/sdk";
|
|
380
380
|
import { join as join6 } from "path";
|
|
@@ -781,11 +781,149 @@ async function runPull(requirementId, workspaceDir) {
|
|
|
781
781
|
return WORKITEMS_DIR;
|
|
782
782
|
}
|
|
783
783
|
|
|
784
|
+
// src/theater-job-report.ts
|
|
785
|
+
import { randomUUID } from "crypto";
|
|
786
|
+
function extractErrorMessage(err) {
|
|
787
|
+
if (err instanceof Error && err.message.trim()) {
|
|
788
|
+
return err.message.trim();
|
|
789
|
+
}
|
|
790
|
+
if (typeof err === "string" && err.trim()) {
|
|
791
|
+
return err.trim();
|
|
792
|
+
}
|
|
793
|
+
if (typeof err === "object" && err && "message" in err) {
|
|
794
|
+
const msg = err.message;
|
|
795
|
+
if (typeof msg === "string" && msg.trim()) return msg.trim();
|
|
796
|
+
if (Array.isArray(msg)) return msg.map(String).join("\uFF1B");
|
|
797
|
+
}
|
|
798
|
+
return "\u672A\u77E5\u9519\u8BEF";
|
|
799
|
+
}
|
|
800
|
+
function isUnauthorizedMessage(msg) {
|
|
801
|
+
return msg.includes("\u672A\u767B\u5F55") || /401/.test(msg);
|
|
802
|
+
}
|
|
803
|
+
function sendTheaterReportWs(ws, payload) {
|
|
804
|
+
return new Promise((resolve5, reject) => {
|
|
805
|
+
const msg_id = randomUUID();
|
|
806
|
+
const timer = setTimeout(() => {
|
|
807
|
+
ws.off("message", onMessage);
|
|
808
|
+
reject(new Error("WebSocket \u4E0A\u62A5\u8D85\u65F6"));
|
|
809
|
+
}, 3e4);
|
|
810
|
+
const onMessage = (data) => {
|
|
811
|
+
const text = typeof data === "string" ? data : data.toString();
|
|
812
|
+
let frame;
|
|
813
|
+
try {
|
|
814
|
+
frame = JSON.parse(text);
|
|
815
|
+
} catch {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
if (frame.msg_id !== msg_id) return;
|
|
819
|
+
clearTimeout(timer);
|
|
820
|
+
ws.off("message", onMessage);
|
|
821
|
+
if (frame.type === "ERROR") {
|
|
822
|
+
reject(
|
|
823
|
+
new Error(frame.payload?.message?.trim() || "WebSocket \u4E0A\u62A5\u5931\u8D25")
|
|
824
|
+
);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
if (frame.type === "ACK") {
|
|
828
|
+
resolve5();
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
ws.on("message", onMessage);
|
|
833
|
+
ws.send(
|
|
834
|
+
JSON.stringify({
|
|
835
|
+
type: "THEATER_REPORT",
|
|
836
|
+
msg_id,
|
|
837
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
838
|
+
payload
|
|
839
|
+
})
|
|
840
|
+
);
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
async function reportTheaterProgress(api, ws, params) {
|
|
844
|
+
const body = {
|
|
845
|
+
sessionId: params.sessionId,
|
|
846
|
+
memberKey: params.memberKey,
|
|
847
|
+
status: "IN_PROGRESS",
|
|
848
|
+
logId: params.logId
|
|
849
|
+
};
|
|
850
|
+
try {
|
|
851
|
+
await api.theater.reportMemberAgentProgress(body);
|
|
852
|
+
} catch (err) {
|
|
853
|
+
const msg = extractErrorMessage(err);
|
|
854
|
+
if (!isUnauthorizedMessage(msg)) throw err;
|
|
855
|
+
await sendTheaterReportWs(ws, { action: "progress", ...body });
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
async function submitTheaterResult(api, ws, params) {
|
|
859
|
+
const body = {
|
|
860
|
+
sessionId: params.sessionId,
|
|
861
|
+
memberKey: params.memberKey,
|
|
862
|
+
content: params.content,
|
|
863
|
+
agentId: params.agentId ?? "",
|
|
864
|
+
agentStatus: params.agentStatus,
|
|
865
|
+
logId: params.logId
|
|
866
|
+
};
|
|
867
|
+
try {
|
|
868
|
+
await api.theater.submitMemberResponse(body);
|
|
869
|
+
} catch (err) {
|
|
870
|
+
const msg = extractErrorMessage(err);
|
|
871
|
+
if (!isUnauthorizedMessage(msg)) throw err;
|
|
872
|
+
await sendTheaterReportWs(ws, {
|
|
873
|
+
action: "submit",
|
|
874
|
+
sessionId: params.sessionId,
|
|
875
|
+
memberKey: params.memberKey,
|
|
876
|
+
content: params.content,
|
|
877
|
+
agentId: params.agentId,
|
|
878
|
+
agentStatus: params.agentStatus,
|
|
879
|
+
logId: params.logId
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
async function submitTheaterFailure(api, ws, params) {
|
|
884
|
+
const content = `[${params.stage}] ${params.error}`;
|
|
885
|
+
try {
|
|
886
|
+
await submitTheaterResult(api, ws, {
|
|
887
|
+
sessionId: params.sessionId,
|
|
888
|
+
memberKey: params.memberKey,
|
|
889
|
+
content,
|
|
890
|
+
agentId: params.agentId,
|
|
891
|
+
agentStatus: "FAILED",
|
|
892
|
+
logId: params.logId
|
|
893
|
+
});
|
|
894
|
+
return true;
|
|
895
|
+
} catch (submitErr) {
|
|
896
|
+
console.error(
|
|
897
|
+
"[apm] \u65E0\u6CD5\u5C06\u5931\u8D25\u72B6\u6001\u5199\u5165\u5267\u573A\u4F1A\u8BDD:",
|
|
898
|
+
extractErrorMessage(submitErr)
|
|
899
|
+
);
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
function logTheaterJobError(stage, err, meta) {
|
|
904
|
+
const msg = extractErrorMessage(err);
|
|
905
|
+
const ctx = [
|
|
906
|
+
meta?.sessionId ? `session=${meta.sessionId}` : "",
|
|
907
|
+
meta?.memberKey ? `member=${meta.memberKey}` : ""
|
|
908
|
+
].filter(Boolean).join(" ");
|
|
909
|
+
console.error(
|
|
910
|
+
`[apm] \u5267\u573A THEATER_JOB \u5931\u8D25 \xB7 \u9636\u6BB5=${stage}${ctx ? ` \xB7 ${ctx}` : ""} \xB7 ${msg}`
|
|
911
|
+
);
|
|
912
|
+
if (isUnauthorizedMessage(msg)) {
|
|
913
|
+
console.error("[apm] \u63D0\u793A: \u8BF7\u6267\u884C apm login \u91CD\u65B0\u767B\u5F55\u540E\u518D\u8BD5");
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
784
917
|
// src/commands/connect.ts
|
|
918
|
+
var DEFAULT_AGENT_MODEL_ID = "default";
|
|
919
|
+
function resolveAgentModelId(model) {
|
|
920
|
+
const id = model?.trim();
|
|
921
|
+
return id || DEFAULT_AGENT_MODEL_ID;
|
|
922
|
+
}
|
|
785
923
|
async function createAgentForJob(payload) {
|
|
786
924
|
const options = {
|
|
787
925
|
apiKey: payload.apiKey,
|
|
788
|
-
model: { id: payload.model
|
|
926
|
+
model: { id: resolveAgentModelId(payload.model) },
|
|
789
927
|
local: { cwd: payload.cwd }
|
|
790
928
|
};
|
|
791
929
|
if (payload.agentId) {
|
|
@@ -839,9 +977,10 @@ async function runAgentStream(payload, session, agent) {
|
|
|
839
977
|
}
|
|
840
978
|
return { agentId: run.agentId, failed, failReason };
|
|
841
979
|
}
|
|
842
|
-
async function handleTheaterJob(api, payload) {
|
|
980
|
+
async function handleTheaterJob(api, ws, payload) {
|
|
843
981
|
const sessionId = payload.theaterSessionId.trim();
|
|
844
982
|
const memberKey = payload.memberKey.trim();
|
|
983
|
+
const logId = payload.logId?.trim() || void 0;
|
|
845
984
|
if (!sessionId) {
|
|
846
985
|
throw new Error("THEATER_JOB \u7F3A\u5C11 theaterSessionId");
|
|
847
986
|
}
|
|
@@ -849,36 +988,53 @@ async function handleTheaterJob(api, payload) {
|
|
|
849
988
|
throw new Error("THEATER_JOB \u7F3A\u5C11 memberKey");
|
|
850
989
|
}
|
|
851
990
|
console.log("[apm] \u5267\u573A\u4F1A\u8BDD:", sessionId, "\u6210\u5458:", memberKey);
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
memberKey,
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
agentId
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
991
|
+
let agentId = payload.agentId?.trim() || void 0;
|
|
992
|
+
try {
|
|
993
|
+
await reportTheaterProgress(api, ws, { sessionId, memberKey, logId });
|
|
994
|
+
} catch (err) {
|
|
995
|
+
logTheaterJobError("\u4E0A\u62A5\u6267\u884C\u8FDB\u5EA6", err, { sessionId, memberKey });
|
|
996
|
+
await submitTheaterFailure(api, ws, {
|
|
997
|
+
sessionId,
|
|
998
|
+
memberKey,
|
|
999
|
+
logId,
|
|
1000
|
+
agentId,
|
|
1001
|
+
stage: "\u4E0A\u62A5\u8FDB\u5EA6",
|
|
1002
|
+
error: extractErrorMessage(err)
|
|
1003
|
+
});
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
try {
|
|
1007
|
+
const eventSession = new EventSession(payload.prompt);
|
|
1008
|
+
const agent = await createAgentForJob(payload);
|
|
1009
|
+
const runResult = await runAgentStream(payload, eventSession, agent);
|
|
1010
|
+
agentId = runResult.agentId;
|
|
1011
|
+
const assistantText = eventSession.getAssistantText();
|
|
1012
|
+
const content = runResult.failed ? runResult.failReason || assistantText || "\u672A\u77E5\u9519\u8BEF" : assistantText || "[Agent \u672A\u4EA7\u751F\u6587\u672C\u8F93\u51FA]";
|
|
1013
|
+
await submitTheaterResult(api, ws, {
|
|
1014
|
+
sessionId,
|
|
1015
|
+
memberKey,
|
|
1016
|
+
content,
|
|
1017
|
+
agentId,
|
|
1018
|
+
agentStatus: runResult.failed ? "FAILED" : "SUCCESS",
|
|
1019
|
+
logId
|
|
1020
|
+
});
|
|
1021
|
+
console.log(
|
|
1022
|
+
"[apm] \u5267\u573A\u6210\u5458\u56DE\u590D\u5DF2\u63D0\u4EA4",
|
|
1023
|
+
runResult.failed ? "(\u6267\u884C\u5931\u8D25)" : ""
|
|
1024
|
+
);
|
|
1025
|
+
} catch (err) {
|
|
1026
|
+
logTheaterJobError("\u6267\u884C\u6216\u63D0\u4EA4\u56DE\u590D", err, { sessionId, memberKey });
|
|
1027
|
+
const reported = await submitTheaterFailure(api, ws, {
|
|
1028
|
+
sessionId,
|
|
1029
|
+
memberKey,
|
|
1030
|
+
logId,
|
|
1031
|
+
agentId,
|
|
1032
|
+
stage: "\u6267\u884C\u4EFB\u52A1",
|
|
1033
|
+
error: extractErrorMessage(err)
|
|
1034
|
+
});
|
|
1035
|
+
if (reported) {
|
|
1036
|
+
console.error("[apm] \u5DF2\u5C06\u5931\u8D25\u539F\u56E0\u5199\u5165\u5267\u573A\u4F1A\u8BDD\uFF0C\u53EF\u5728\u7F51\u9875\u67E5\u770B");
|
|
1037
|
+
}
|
|
882
1038
|
}
|
|
883
1039
|
}
|
|
884
1040
|
async function handleWorkflowJob(api, payload) {
|
|
@@ -958,7 +1114,7 @@ function runConnect(opts) {
|
|
|
958
1114
|
const sendHeartbeat = () => {
|
|
959
1115
|
const frame = {
|
|
960
1116
|
type: "HEARTBEAT",
|
|
961
|
-
msg_id:
|
|
1117
|
+
msg_id: randomUUID2(),
|
|
962
1118
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
963
1119
|
payload: {}
|
|
964
1120
|
};
|
|
@@ -970,22 +1126,31 @@ function runConnect(opts) {
|
|
|
970
1126
|
});
|
|
971
1127
|
ws.on("message", async (data) => {
|
|
972
1128
|
const text = typeof data === "string" ? data : data.toString();
|
|
1129
|
+
let msg;
|
|
973
1130
|
try {
|
|
974
|
-
|
|
975
|
-
if (msg.type === "THEATER_JOB") {
|
|
976
|
-
await handleTheaterJob(api, msg.payload);
|
|
977
|
-
return;
|
|
978
|
-
}
|
|
979
|
-
if (msg.type === "JOB") {
|
|
980
|
-
await handleWorkflowJob(api, msg.payload);
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
1131
|
+
msg = JSON.parse(text);
|
|
983
1132
|
} catch (err) {
|
|
984
1133
|
console.error(
|
|
985
1134
|
"[apm] \u65E0\u6CD5\u89E3\u6790 WebSocket \u6D88\u606F:",
|
|
986
1135
|
text,
|
|
987
1136
|
err.message
|
|
988
1137
|
);
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
try {
|
|
1141
|
+
const jobType = msg.type;
|
|
1142
|
+
if (jobType === "THEATER_JOB") {
|
|
1143
|
+
await handleTheaterJob(api, ws, msg.payload);
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
if (jobType === "JOB") {
|
|
1147
|
+
await handleWorkflowJob(api, msg.payload);
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
} catch (err) {
|
|
1151
|
+
const jobType = msg.type;
|
|
1152
|
+
const label = jobType === "THEATER_JOB" ? "\u5267\u573A THEATER_JOB" : jobType === "JOB" ? "\u5DE5\u4F5C\u6D41 JOB" : String(jobType);
|
|
1153
|
+
console.error(`[apm] ${label} \u5904\u7406\u5931\u8D25:`, extractErrorMessage(err));
|
|
989
1154
|
}
|
|
990
1155
|
});
|
|
991
1156
|
ws.on("error", (err) => {
|
|
@@ -2044,7 +2209,7 @@ function loadApmDotEnvIfPresent() {
|
|
|
2044
2209
|
|
|
2045
2210
|
// src/commands/deploy/internal/minio.ts
|
|
2046
2211
|
import { statSync as statSync5 } from "node:fs";
|
|
2047
|
-
import { readdir } from "node:fs/promises";
|
|
2212
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2048
2213
|
import path6 from "node:path";
|
|
2049
2214
|
import * as Minio from "minio";
|
|
2050
2215
|
var DEFAULT_MAX_FILE_SIZE_MB = 50;
|
|
@@ -2094,7 +2259,6 @@ async function collectFiles(root) {
|
|
|
2094
2259
|
return out;
|
|
2095
2260
|
}
|
|
2096
2261
|
async function readArtifactFile(absPath) {
|
|
2097
|
-
const { readFile } = await import("node:fs/promises");
|
|
2098
2262
|
return readFile(absPath);
|
|
2099
2263
|
}
|
|
2100
2264
|
function toMB(bytes) {
|