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