feat: add decision center service and cli

This commit is contained in:
Codex
2026-05-17 06:49:42 +00:00
parent 2b2a327301
commit 4d9eed6513
32 changed files with 1758 additions and 48 deletions
+28 -17
View File
@@ -51,6 +51,13 @@ type CodexRequestInit = { method?: string; body?: unknown };
type CodexResponseFetcher = (path: string, init?: CodexRequestInit) => unknown;
type AsyncCodexResponseFetcher = (path: string, init?: CodexRequestInit) => Promise<unknown>;
const codeQueueProxyPrefix = "/api/microservices/code-queue/proxy";
function codeQueueProxyPath(path: string): string {
if (!path.startsWith("/")) throw new Error("Code Queue proxy path must start with /");
return `${codeQueueProxyPrefix}${path}`;
}
function requireTaskId(value: string | undefined, command: string): string {
if (value === undefined || value.trim().length === 0) throw new Error(`${command} requires task id`);
return value.trim();
@@ -105,7 +112,11 @@ function upstreamError(response: unknown): string {
if (record === null) return String(response);
const body = asRecord(record.body);
const bodyError = body?.error;
if (typeof bodyError === "string") return bodyError;
if (typeof bodyError === "string") {
const requestId = typeof body?.requestId === "string" ? ` requestId=${body.requestId}` : "";
const providerId = typeof body?.providerId === "string" ? ` providerId=${body.providerId}` : "";
return `${bodyError}${providerId}${requestId}`;
}
const status = typeof record.status === "number" ? `HTTP ${record.status}` : "upstream request failed";
return `${status}: ${JSON.stringify(response).slice(0, 1200)}`;
}
@@ -488,7 +499,7 @@ function queryString(params: Record<string, string | number | boolean | null | u
}
function codexTaskSummary(taskId: string, options: CodexTaskOptions, fetcher: CodexResponseFetcher): unknown {
const summaryPath = `/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/summary${queryString({ toolLimit: options.toolLimit })}`;
const summaryPath = codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/summary${queryString({ toolLimit: options.toolLimit })}`);
const summaryResponse = unwrapCodexResponse(fetcher(summaryPath));
const summary = summaryResponse.body.summary;
const result: Record<string, unknown> = {
@@ -501,8 +512,8 @@ function codexTaskSummary(taskId: string, options: CodexTaskOptions, fetcher: Co
if (options.traceMode === "tail") traceParams.tail = 1;
if (options.traceMode === "after") traceParams.afterSeq = options.afterSeq;
if (options.traceMode === "before") traceParams.beforeSeq = options.beforeSeq;
const traceSummaryResponse = unwrapCodexResponse(fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/trace-summary`));
const traceResponse = unwrapCodexResponse(fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/trace-steps${queryString(traceParams)}`));
const traceSummaryResponse = unwrapCodexResponse(fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/trace-summary`)));
const traceResponse = unwrapCodexResponse(fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/trace-steps${queryString(traceParams)}`)));
result.trace = compactTracePage(traceResponse.body, taskId, options.traceLimit, traceSummaryResponse.body, options);
}
return result;
@@ -548,7 +559,7 @@ function codexTaskOutput(taskId: string, options: CodexOutputOptions, fetcher: C
if (options.mode === "tail") params.tail = 1;
if (options.mode === "after") params.afterSeq = options.afterSeq;
if (options.mode === "before") params.beforeSeq = options.beforeSeq;
const response = unwrapCodexResponse(fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/output${queryString(params)}`));
const response = unwrapCodexResponse(fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/output${queryString(params)}`)));
return { upstream: response.upstream, outputPage: compactOutputPage(response.body, taskId, options.limit) };
}
@@ -558,7 +569,7 @@ function codexTaskJudge(taskId: string, options: CodexJudgeOptions, fetcher: Cod
dryRun: options.dryRun ? 1 : undefined,
includePrompt: options.includePrompt ? 1 : undefined,
});
const response = unwrapCodexResponse(fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/judge${params}`, { method: "POST" }));
const response = unwrapCodexResponse(fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/judge${params}`), { method: "POST" }));
return { upstream: response.upstream, judgeReplay: response.body };
}
@@ -575,7 +586,7 @@ export function codexJudgeQuery(taskId: string, optionArgs: string[], fetcher: C
}
async function codexTaskSummaryAsync(taskId: string, options: CodexTaskOptions, fetcher: AsyncCodexResponseFetcher): Promise<unknown> {
const summaryPath = `/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/summary${queryString({ toolLimit: options.toolLimit })}`;
const summaryPath = codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/summary${queryString({ toolLimit: options.toolLimit })}`);
const summaryResponse = unwrapCodexResponse(await fetcher(summaryPath));
const summary = summaryResponse.body.summary;
const result: Record<string, unknown> = {
@@ -588,8 +599,8 @@ async function codexTaskSummaryAsync(taskId: string, options: CodexTaskOptions,
if (options.traceMode === "tail") traceParams.tail = 1;
if (options.traceMode === "after") traceParams.afterSeq = options.afterSeq;
if (options.traceMode === "before") traceParams.beforeSeq = options.beforeSeq;
const traceSummaryResponse = unwrapCodexResponse(await fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/trace-summary`));
const traceResponse = unwrapCodexResponse(await fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/trace-steps${queryString(traceParams)}`));
const traceSummaryResponse = unwrapCodexResponse(await fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/trace-summary`)));
const traceResponse = unwrapCodexResponse(await fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/trace-steps${queryString(traceParams)}`)));
result.trace = compactTracePage(traceResponse.body, taskId, options.traceLimit, traceSummaryResponse.body, options);
}
return result;
@@ -604,7 +615,7 @@ async function codexTaskOutputAsync(taskId: string, options: CodexOutputOptions,
if (options.mode === "tail") params.tail = 1;
if (options.mode === "after") params.afterSeq = options.afterSeq;
if (options.mode === "before") params.beforeSeq = options.beforeSeq;
const response = unwrapCodexResponse(await fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/output${queryString(params)}`));
const response = unwrapCodexResponse(await fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/output${queryString(params)}`)));
return { upstream: response.upstream, outputPage: compactOutputPage(response.body, taskId, options.limit) };
}
@@ -614,7 +625,7 @@ async function codexTaskJudgeAsync(taskId: string, options: CodexJudgeOptions, f
dryRun: options.dryRun ? 1 : undefined,
includePrompt: options.includePrompt ? 1 : undefined,
});
const response = unwrapCodexResponse(await fetcher(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/judge${params}`, { method: "POST" }));
const response = unwrapCodexResponse(await fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/judge${params}`), { method: "POST" }));
return { upstream: response.upstream, judgeReplay: response.body };
}
@@ -700,19 +711,19 @@ function requireMergeTargetQueueId(args: string[], command: string): string {
}
function codeQueues(): unknown {
return unwrapCodexResponse(coreInternalFetch("/api/microservices/code-queue/proxy/api/queues"));
return unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath("/api/queues")));
}
function codexCreateQueue(queueId: string): unknown {
return unwrapCodexResponse(coreInternalFetch("/api/microservices/code-queue/proxy/api/queues", { method: "POST", body: { queueId } }));
return unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath("/api/queues"), { method: "POST", body: { queueId } }));
}
function codexMergeQueue(sourceQueueId: string, targetQueueId: string): unknown {
return unwrapCodexResponse(coreInternalFetch(`/api/microservices/code-queue/proxy/api/queues/${encodeURIComponent(targetQueueId)}/merge`, { method: "POST", body: { sourceQueueId } }));
return unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath(`/api/queues/${encodeURIComponent(targetQueueId)}/merge`), { method: "POST", body: { sourceQueueId } }));
}
function codexMoveTask(taskId: string, queueId: string): unknown {
return unwrapCodexResponse(coreInternalFetch(`/api/microservices/code-queue/proxy/api/tasks/${encodeURIComponent(taskId)}/move`, { method: "POST", body: { queueId } }));
return unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/move`), { method: "POST", body: { queueId } }));
}
function promptFromSubmitArgs(args: string[]): string {
@@ -845,7 +856,7 @@ function codexSubmitTask(args: string[]): unknown {
},
};
}
const response = unwrapCodexResponse(coreInternalFetch("/api/microservices/code-queue/proxy/api/tasks", { method: "POST", body: payload }));
const response = unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath("/api/tasks"), { method: "POST", body: payload }));
return {
upstream: response.upstream,
tasks: asArray(response.body.tasks).map(compactTaskMutationResponse),
@@ -854,7 +865,7 @@ function codexSubmitTask(args: string[]): unknown {
}
function codexInterruptTask(taskId: string): unknown {
const response = unwrapCodexResponse(coreInternalFetch(`/api/microservices/k3sctl-adapter/proxy/api/services/code-queue-scheduler/proxy/api/tasks/${encodeURIComponent(taskId)}/interrupt`, { method: "POST" }));
const response = unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/interrupt`), { method: "POST" }));
return {
upstream: response.upstream,
task: compactTaskMutationResponse(response.body.task),