chore: update live chat and work server changes
This commit is contained in:
@@ -13,6 +13,7 @@ const apiBaseUrl = process.env.PLAN_API_BASE_URL ?? 'http://127.0.0.1:3100/api';
|
||||
const accessToken = process.env.PLAN_ACCESS_TOKEN?.trim() ?? '';
|
||||
const planItemId = process.env.PLAN_ITEM_ID ? Number(process.env.PLAN_ITEM_ID) : null;
|
||||
const codexBin = process.env.PLAN_CODEX_BIN ?? 'codex';
|
||||
const codexModel = process.env.PLAN_CODEX_MODEL?.trim() || process.env.SERVER_COMMAND_RUNNER_CODEX_MODEL?.trim() || 'gpt-5.4';
|
||||
const localMainMode = process.env.PLAN_LOCAL_MAIN_MODE === 'true';
|
||||
const skipWorkComplete = process.env.PLAN_SKIP_WORK_COMPLETE === 'true';
|
||||
const gitUserName = process.env.PLAN_GIT_USER_NAME ?? 'how2ice';
|
||||
@@ -1124,6 +1125,8 @@ async function runCodexForPlan(item) {
|
||||
codexBin,
|
||||
[
|
||||
'exec',
|
||||
'--model',
|
||||
codexModel,
|
||||
'--dangerously-bypass-approvals-and-sandbox',
|
||||
'-C',
|
||||
repoPath,
|
||||
|
||||
@@ -31,12 +31,16 @@ const runnerLogTrimIntervalMs = Math.max(
|
||||
const STREAM_CAPTURE_LIMIT = 256 * 1024;
|
||||
const CODEX_LIVE_IDLE_TIMEOUT_MS = Math.max(
|
||||
30_000,
|
||||
Number(process.env.SERVER_COMMAND_RUNNER_CODEX_IDLE_TIMEOUT_MS?.trim() || '90000'),
|
||||
Number(process.env.SERVER_COMMAND_RUNNER_CODEX_IDLE_TIMEOUT_MS?.trim() || '180000'),
|
||||
);
|
||||
const CODEX_LIVE_MAX_EXECUTION_MS = Math.max(
|
||||
CODEX_LIVE_IDLE_TIMEOUT_MS,
|
||||
Number(process.env.SERVER_COMMAND_RUNNER_CODEX_MAX_EXECUTION_MS?.trim() || `${10 * 60 * 1000}`),
|
||||
);
|
||||
const CODEX_LIVE_MODEL =
|
||||
process.env.SERVER_COMMAND_RUNNER_CODEX_MODEL?.trim() ||
|
||||
process.env.PLAN_CODEX_MODEL?.trim() ||
|
||||
'gpt-5.4';
|
||||
const CODEX_HOME_RUNTIME_PATHS = [
|
||||
'auth.json',
|
||||
'config.toml',
|
||||
@@ -206,6 +210,25 @@ function sendJsonLine(response, payload) {
|
||||
response.write(`${JSON.stringify(payload)}\n`);
|
||||
}
|
||||
|
||||
function normalizeNumericSeconds(value) {
|
||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim();
|
||||
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parsed = Number(trimmed);
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function readRequestBody(request, maxBytes = 4 * 1024 * 1024) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let total = 0;
|
||||
@@ -505,7 +528,8 @@ async function runCodexLiveExecution(payload, response) {
|
||||
const resourceDir = path.join(repoPath, 'public', '.codex_chat', sessionId, 'resource');
|
||||
const uploadDir = path.join(resourceDir, 'uploads');
|
||||
const codexBin = process.env.SERVER_COMMAND_RUNNER_CODEX_BIN?.trim() || process.env.PLAN_CODEX_BIN?.trim() || 'codex';
|
||||
const configuredMaxExecutionMs = resolveCodexLiveMaxExecutionMs(payload?.maxExecutionSeconds);
|
||||
const configuredIdleTimeoutMs = resolveCodexLiveIdleTimeoutMs(payload?.idleTimeoutSeconds);
|
||||
const configuredMaxExecutionMs = resolveCodexLiveMaxExecutionMs(payload?.maxExecutionSeconds, configuredIdleTimeoutMs);
|
||||
|
||||
if (!requestId || !sessionId || !prompt.trim()) {
|
||||
sendJson(response, 400, {
|
||||
@@ -536,7 +560,7 @@ async function runCodexLiveExecution(payload, response) {
|
||||
|
||||
const child = spawn(
|
||||
codexBin,
|
||||
['exec', '--json', '--dangerously-bypass-approvals-and-sandbox', '-C', repoPath, '-'],
|
||||
['exec', '--model', CODEX_LIVE_MODEL, '--json', '--dangerously-bypass-approvals-and-sandbox', '-C', repoPath, '-'],
|
||||
{
|
||||
cwd: repoPath,
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
@@ -557,6 +581,8 @@ async function runCodexLiveExecution(payload, response) {
|
||||
sendJsonLine(response, {
|
||||
type: 'started',
|
||||
pid: child.pid ?? null,
|
||||
configuredIdleTimeoutSeconds: Math.round(configuredIdleTimeoutMs / 1000),
|
||||
configuredMaxExecutionSeconds: Math.round(configuredMaxExecutionMs / 1000),
|
||||
});
|
||||
|
||||
const cleanup = async () => {
|
||||
@@ -612,9 +638,9 @@ async function runCodexLiveExecution(payload, response) {
|
||||
|
||||
idleTimer = setTimeout(() => {
|
||||
requestTermination(
|
||||
`Codex Live 실행이 ${Math.round(CODEX_LIVE_IDLE_TIMEOUT_MS / 1000)}초 동안 출력이 없어 중단되었습니다.`,
|
||||
`Codex Live 실행이 ${Math.round(configuredIdleTimeoutMs / 1000)}초 동안 출력이 없어 중단되었습니다.`,
|
||||
);
|
||||
}, CODEX_LIVE_IDLE_TIMEOUT_MS);
|
||||
}, configuredIdleTimeoutMs);
|
||||
idleTimer.unref?.();
|
||||
};
|
||||
|
||||
@@ -759,12 +785,24 @@ async function runCodexLiveExecution(payload, response) {
|
||||
child.stdin?.end(prompt);
|
||||
}
|
||||
|
||||
function resolveCodexLiveMaxExecutionMs(value) {
|
||||
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
||||
return CODEX_LIVE_MAX_EXECUTION_MS;
|
||||
function resolveCodexLiveMaxExecutionMs(value, minimumMs = CODEX_LIVE_IDLE_TIMEOUT_MS) {
|
||||
const normalizedValue = normalizeNumericSeconds(value);
|
||||
|
||||
if (normalizedValue == null) {
|
||||
return Math.max(minimumMs, CODEX_LIVE_MAX_EXECUTION_MS);
|
||||
}
|
||||
|
||||
return Math.max(CODEX_LIVE_IDLE_TIMEOUT_MS, Math.min(7_200_000, Math.max(60_000, Math.round(value * 1000))));
|
||||
return Math.max(minimumMs, Math.min(7_200_000, Math.max(60_000, Math.round(normalizedValue * 1000))));
|
||||
}
|
||||
|
||||
function resolveCodexLiveIdleTimeoutMs(value) {
|
||||
const normalizedValue = normalizeNumericSeconds(value);
|
||||
|
||||
if (normalizedValue == null) {
|
||||
return CODEX_LIVE_IDLE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
return Math.min(3_600_000, Math.max(30_000, Math.round(normalizedValue * 1000)));
|
||||
}
|
||||
|
||||
function isAuthorized(request) {
|
||||
|
||||
Reference in New Issue
Block a user