修正 Codex Action 重複輸出最後回答 #3
+18
-4
@@ -183,11 +183,13 @@ function readExecutionConfig() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function codexExecArgs(model, prompt) {
|
function codexExecArgs(model, prompt, lastMessageFile) {
|
||||||
return [
|
return [
|
||||||
"exec",
|
"exec",
|
||||||
"--dangerously-bypass-approvals-and-sandbox",
|
"--dangerously-bypass-approvals-and-sandbox",
|
||||||
"--skip-git-repo-check",
|
"--skip-git-repo-check",
|
||||||
|
"--output-last-message",
|
||||||
|
lastMessageFile,
|
||||||
"--model",
|
"--model",
|
||||||
model,
|
model,
|
||||||
prompt,
|
prompt,
|
||||||
@@ -197,7 +199,10 @@ function codexExecArgs(model, prompt) {
|
|||||||
function runCodex(model, prompt) {
|
function runCodex(model, prompt) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
Ghost marked this conversation as resolved
|
|||||||
const { timeoutMs, outputLimitBytes, workspace } = readExecutionConfig();
|
const { timeoutMs, outputLimitBytes, workspace } = readExecutionConfig();
|
||||||
const args = codexExecArgs(model, prompt);
|
const tempDir = makeTempDir(process.env.CODEX_HOME || "/root/.codex");
|
||||||
|
const lastMessageFile = path.join(tempDir, "last-message.txt");
|
||||||
|
tempFiles.trackFile(lastMessageFile);
|
||||||
|
const args = codexExecArgs(model, prompt, lastMessageFile);
|
||||||
|
|
||||||
// This Docker Action runs inside an ephemeral CI container where Codex must be
|
// This Docker Action runs inside an ephemeral CI container where Codex must be
|
||||||
// able to edit the checked-out workspace without interactive approvals.
|
// able to edit the checked-out workspace without interactive approvals.
|
||||||
@@ -210,7 +215,6 @@ function runCodex(model, prompt) {
|
|||||||
output.append(Buffer.from(`Codex execution timed out after ${timeoutMs} ms.\n`));
|
output.append(Buffer.from(`Codex execution timed out after ${timeoutMs} ms.\n`));
|
||||||
}, timeoutMs);
|
}, timeoutMs);
|
||||||
|
|
||||||
child.stdout.pipe(process.stdout);
|
|
||||||
child.stderr.pipe(process.stdout);
|
child.stderr.pipe(process.stdout);
|
||||||
|
|
||||||
child.stdout.on("data", (chunk) => {
|
child.stdout.on("data", (chunk) => {
|
||||||
@@ -235,7 +239,14 @@ function runCodex(model, prompt) {
|
|||||||
output.append(Buffer.from(`Codex process terminated by signal ${signal}.\n`));
|
output.append(Buffer.from(`Codex process terminated by signal ${signal}.\n`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gitea-actions
commented
嚴重等級:🟡 警告 **嚴重等級**:🟡 警告
**審查員**:Bard
**問題**:`runCodex` 中 `resultOutput` 的計算邏輯過於緊湊且不易維護,且直接進行檔案同步讀取,若檔案過大可能阻塞 Node.js 事件循環。
**建議**:建議拆解複雜的邏輯為獨立的輔助函數,並改用非同步的檔案讀取方式。
|
|||||||
resolve({ status: code ?? 1, output: output.toString() });
|
let lastMessage = "";
|
||||||
|
try {
|
||||||
|
lastMessage = fs.readFileSync(lastMessageFile, "utf8");
|
||||||
|
} catch {
|
||||||
|
Ghost marked this conversation as resolved
Outdated
gitea-actions
commented
嚴重等級:🟡 警告 **嚴重等級**:🟡 警告
**審查員**:Bard
**問題**:在 `runCodex` 函式中,對 `lastMessageFile` 的讀取缺乏明確的錯誤處理策略,直接將錯誤靜默處理並初始化為空字串,可能掩蓋真正的檔案系統問題,且導致邏輯錯誤。
**建議**:建議在 `catch` 區塊中至少加入簡單的日誌記錄(如 `console.error`),並明確區分錯誤類型(如檔案不存在 vs 權限問題),給予清晰的回饋。
|
|||||||
|
lastMessage = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Ghost marked this conversation as resolved
Outdated
gitea-actions
commented
嚴重等級:🔵 建議 **嚴重等級**:🔵 建議
**審查員**:Bard
**問題**:在 `resolve` 函式的回傳值邏輯中使用了 `lastMessage || output.toString()`,這種基於真值判斷(truthiness)的邏輯若 `lastMessage` 為空字串但 `output` 亦為空,會導致語意不明,且與前面處理錯誤的情境交織,增加閱讀複雜度。
**建議**:建議明確區分 `lastMessage` 的來源,若確定檔案應存在,請使用更明確的判斷方式(如檢查檔案是否存在或長度),提升程式碼的可預測性。
|
|||||||
|
resolve({ status: code ?? 1, output: lastMessage || output.toString() });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -312,6 +323,9 @@ function setupAuth(oauth, codexHome) {
|
|||||||
async function runCodexAction({ oauth, model, codexHome, prompt }) {
|
async function runCodexAction({ oauth, model, codexHome, prompt }) {
|
||||||
const lockHandle = setupAuth(oauth, codexHome);
|
const lockHandle = setupAuth(oauth, codexHome);
|
||||||
const result = await runCodex(model, prompt);
|
const result = await runCodex(model, prompt);
|
||||||
|
if (result.output) {
|
||||||
|
process.stdout.write(result.output.endsWith("\n") ? result.output : `${result.output}\n`);
|
||||||
|
}
|
||||||
appendGithubOutput(result.status === 0 ? "completed" : "failed", result.output);
|
appendGithubOutput(result.status === 0 ? "completed" : "failed", result.output);
|
||||||
|
|
||||||
if (lockHandle !== undefined) {
|
if (lockHandle !== undefined) {
|
||||||
|
|||||||
Reference in New Issue
Block a user
嚴重等級:🔵 建議
審查員:Rogue
問題:每次執行 runCodex 都在建立新的 temp 目錄與追蹤檔案,這種重複性的檔案系統配置開銷對於高頻率呼叫來說是完全浪費的資源。
建議:如果執行環境是持續存在的,應快取 tempDir 路徑或使用預設的共享路徑,避免頻繁的檔案系統建立與追蹤開銷。