chore: update live chat and work server changes

This commit is contained in:
2026-04-26 16:37:06 +09:00
parent 63e5d263a7
commit 20a6333ed2
38 changed files with 2078 additions and 2281 deletions

View File

@@ -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,

View File

@@ -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) {