fix(code-queue): return terminal read summaries
Merge PR #92 after rebasing onto current master and validating focused Code Queue CLI contracts. Adds bounded terminal review data to codex read without prompt/tool log disclosure.
This commit is contained in:
+177
-4
@@ -3415,19 +3415,192 @@ export function compactSubmitSuccessResponseForTest(body: Record<string, unknown
|
||||
return compactSubmitSuccessResponse(body, upstream, lock);
|
||||
}
|
||||
|
||||
function codexReadTask(taskId: string): unknown {
|
||||
const response = unwrapCodexResponse(coreInternalFetch(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/read`), { method: "POST", body: {} }));
|
||||
function compactTerminalReadAttempt(value: unknown): Record<string, unknown> | null {
|
||||
const record = asRecord(value);
|
||||
if (record === null) return null;
|
||||
return {
|
||||
upstream: response.upstream,
|
||||
task: compactTaskMutationResponse(response.body.task),
|
||||
index: record.index ?? null,
|
||||
synthetic: record.synthetic ?? false,
|
||||
label: record.label ?? null,
|
||||
mode: record.mode ?? null,
|
||||
terminalStatus: record.terminalStatus ?? null,
|
||||
appServerExitCode: record.appServerExitCode ?? null,
|
||||
appServerSignal: record.appServerSignal ?? null,
|
||||
transportClosedBeforeTerminal: record.transportClosedBeforeTerminal ?? null,
|
||||
error: record.error ?? null,
|
||||
stderrTail: textView(asString(record.stderrTail), false, 1200),
|
||||
startedAt: record.startedAt ?? null,
|
||||
finishedAt: record.finishedAt ?? null,
|
||||
startSeq: record.startSeq ?? record.outputStartSeq ?? null,
|
||||
endSeq: record.endSeq ?? record.outputEndSeq ?? null,
|
||||
execution: record.execution ?? null,
|
||||
finalResponse: textView(asString(record.finalResponsePreview ?? record.finalResponse), false, 3000),
|
||||
judge: record.judge ?? null,
|
||||
runnerErrorClassification: record.runnerErrorClassification ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function compactTerminalReadFinalResponse(summary: Record<string, unknown>, readTask: Record<string, unknown>): Record<string, unknown> {
|
||||
const lastAssistantMessage = asRecord(summary.lastAssistantMessage);
|
||||
const text = asString(lastAssistantMessage?.text ?? summary.finalResponse ?? readTask.finalResponse);
|
||||
return {
|
||||
at: lastAssistantMessage?.at ?? summary.finishedAt ?? readTask.finishedAt ?? null,
|
||||
seq: lastAssistantMessage?.seq ?? null,
|
||||
source: lastAssistantMessage?.source ?? (text.trim().length > 0 ? "finalResponse" : "none"),
|
||||
...textView(text, false, 6000),
|
||||
};
|
||||
}
|
||||
|
||||
function compactReadReferenceInjection(value: unknown): Record<string, unknown> | null {
|
||||
const record = asRecord(value);
|
||||
if (record === null) return null;
|
||||
const items = asArray(record.items);
|
||||
const returnedItems = items.slice(0, 12);
|
||||
return {
|
||||
version: record.version ?? null,
|
||||
injectedAt: record.injectedAt ?? null,
|
||||
itemCount: record.itemCount ?? null,
|
||||
directReferenceTaskIds: record.directReferenceTaskIds ?? [],
|
||||
maxRounds: record.maxRounds ?? null,
|
||||
truncated: record.truncated ?? null,
|
||||
itemsReturned: returnedItems.length,
|
||||
itemsTruncated: items.length > returnedItems.length,
|
||||
items: returnedItems.map((item) => {
|
||||
const itemRecord = asRecord(item) ?? {};
|
||||
return {
|
||||
round: itemRecord.round ?? null,
|
||||
roundIndex: itemRecord.roundIndex ?? null,
|
||||
taskId: itemRecord.taskId ?? null,
|
||||
viaTaskId: itemRecord.viaTaskId ?? null,
|
||||
status: itemRecord.status ?? null,
|
||||
providerId: itemRecord.providerId ?? null,
|
||||
executionMode: itemRecord.executionMode ?? null,
|
||||
model: itemRecord.model ?? null,
|
||||
cwd: itemRecord.cwd ?? null,
|
||||
createdAt: itemRecord.createdAt ?? null,
|
||||
updatedAt: itemRecord.updatedAt ?? null,
|
||||
promptChars: itemRecord.promptChars ?? null,
|
||||
finalResponseChars: itemRecord.finalResponseChars ?? null,
|
||||
finalResponseAt: itemRecord.finalResponseAt ?? null,
|
||||
finalResponseSource: itemRecord.finalResponseSource ?? null,
|
||||
referenceTaskIds: itemRecord.referenceTaskIds ?? [],
|
||||
cliHint: itemRecord.cliHint ?? null,
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function compactTerminalReadTask(summary: unknown, readTask: unknown, taskId: string): Record<string, unknown> {
|
||||
const summaryRecord = asRecord(summary) ?? {};
|
||||
const readRecord = asRecord(readTask) ?? {};
|
||||
const id = asString(summaryRecord.id ?? readRecord.id) || taskId;
|
||||
const attempts = asArray(summaryRecord.attempts);
|
||||
const lastAttempt = compactTerminalReadAttempt(attempts.at(-1));
|
||||
const toolSummary = asRecord(summaryRecord.toolSummary) ?? {};
|
||||
const readAt = readRecord.readAt ?? summaryRecord.readAt ?? null;
|
||||
const referenceInjection = compactReadReferenceInjection(summaryRecord.referenceInjection ?? readRecord.referenceInjectionSummary);
|
||||
return {
|
||||
id,
|
||||
queueId: summaryRecord.queueId ?? readRecord.queueId ?? null,
|
||||
status: summaryRecord.status ?? readRecord.status ?? null,
|
||||
terminalUnread: false,
|
||||
readAt,
|
||||
providerId: summaryRecord.providerId ?? readRecord.providerId ?? null,
|
||||
executionMode: summaryRecord.executionMode ?? readRecord.executionMode ?? null,
|
||||
executionModeInfo: summaryRecord.executionModeInfo ?? readRecord.executionModeInfo ?? null,
|
||||
model: summaryRecord.model ?? readRecord.model ?? null,
|
||||
agentPort: summaryRecord.agentPort ?? readRecord.agentPort ?? null,
|
||||
agentPortInfo: summaryRecord.agentPortInfo ?? readRecord.agentPortInfo ?? null,
|
||||
cwd: summaryRecord.cwd ?? readRecord.cwd ?? null,
|
||||
reasoningEffort: summaryRecord.reasoningEffort ?? readRecord.reasoningEffort ?? null,
|
||||
maxAttempts: summaryRecord.maxAttempts ?? readRecord.maxAttempts ?? null,
|
||||
attempts: {
|
||||
currentAttempt: summaryRecord.currentAttempt ?? readRecord.currentAttempt ?? null,
|
||||
maxAttempts: summaryRecord.maxAttempts ?? readRecord.maxAttempts ?? null,
|
||||
currentMode: summaryRecord.currentMode ?? readRecord.currentMode ?? null,
|
||||
judgeFailCount: summaryRecord.judgeFailCount ?? readRecord.judgeFailCount ?? null,
|
||||
judgeFailRetryLimit: summaryRecord.judgeFailRetryLimit ?? readRecord.judgeFailRetryLimit ?? null,
|
||||
count: attempts.length,
|
||||
lastAttempt,
|
||||
},
|
||||
thread: {
|
||||
codexThreadId: summaryRecord.codexThreadId ?? readRecord.codexThreadId ?? null,
|
||||
activeTurnId: summaryRecord.activeTurnId ?? readRecord.activeTurnId ?? null,
|
||||
cancelRequested: summaryRecord.cancelRequested ?? readRecord.cancelRequested ?? null,
|
||||
},
|
||||
timing: summaryRecord.timing ?? readRecord.timing ?? null,
|
||||
createdAt: summaryRecord.createdAt ?? readRecord.createdAt ?? null,
|
||||
startedAt: summaryRecord.startedAt ?? readRecord.startedAt ?? null,
|
||||
updatedAt: summaryRecord.updatedAt ?? readRecord.updatedAt ?? null,
|
||||
finishedAt: summaryRecord.finishedAt ?? readRecord.finishedAt ?? null,
|
||||
referenceTaskIds: summaryRecord.referenceTaskIds ?? readRecord.referenceTaskIds ?? [],
|
||||
referenceInjection,
|
||||
finalResponse: compactTerminalReadFinalResponse(summaryRecord, readRecord),
|
||||
lastError: summaryRecord.lastError ?? readRecord.lastError ?? lastAttempt?.error ?? null,
|
||||
lastJudge: summaryRecord.lastJudge ?? readRecord.lastJudge ?? null,
|
||||
counts: {
|
||||
transcript: summaryRecord.transcriptCount ?? readRecord.transcriptCount ?? null,
|
||||
transcriptMaxSeq: summaryRecord.transcriptMaxSeq ?? readRecord.transcriptMaxSeq ?? null,
|
||||
output: summaryRecord.outputCount ?? readRecord.outputCount ?? null,
|
||||
retainedOutput: summaryRecord.retainedOutputCount ?? readRecord.retainedOutputCount ?? null,
|
||||
outputMaxSeq: summaryRecord.outputMaxSeq ?? readRecord.outputMaxSeq ?? null,
|
||||
events: summaryRecord.eventCount ?? readRecord.eventCount ?? null,
|
||||
tools: toolSummary.count ?? null,
|
||||
},
|
||||
disclosure: {
|
||||
mode: "terminal-read",
|
||||
promptIncluded: false,
|
||||
toolLogsIncluded: false,
|
||||
finalResponseIncluded: true,
|
||||
promptChars: asString(summaryRecord.initialPrompt ?? summaryRecord.prompt).length || (summaryRecord.promptChars ?? null),
|
||||
toolCount: toolSummary.count ?? null,
|
||||
policy: "read returns terminal metadata and final response; prompt and tool logs remain behind explicit progressive drill-down commands",
|
||||
},
|
||||
commands: {
|
||||
show: `bun scripts/cli.ts codex task ${id}`,
|
||||
detail: `bun scripts/cli.ts codex task ${id} --detail`,
|
||||
full: `bun scripts/cli.ts codex task ${id} --full`,
|
||||
trace: `bun scripts/cli.ts codex task ${id} --trace --tail --limit ${defaultTraceLimit}`,
|
||||
output: `bun scripts/cli.ts codex output ${id} --tail --limit ${defaultOutputLimit}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function codexReadTaskWithFetcher(taskId: string, fetcher: CodexResponseFetcher): unknown {
|
||||
const summaryResponse = unwrapCodexResponse(fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/summary${queryString({ toolLimit: defaultToolLimit })}`)));
|
||||
const response = unwrapCodexResponse(fetcher(codeQueueProxyPath(`/api/tasks/${encodeURIComponent(taskId)}/read`), { method: "POST", body: {} }));
|
||||
const readTask = asRecord(response.body.task) ?? {};
|
||||
const terminalUnread = readTask.terminalUnread ?? readTask.unreadTerminal ?? false;
|
||||
return {
|
||||
upstream: {
|
||||
summary: summaryResponse.upstream,
|
||||
read: response.upstream,
|
||||
},
|
||||
read: {
|
||||
marked: true,
|
||||
readAt: readTask.readAt ?? null,
|
||||
terminalUnread,
|
||||
},
|
||||
task: compactTerminalReadTask(summaryResponse.body.summary, response.body.task, taskId),
|
||||
queue: compactQueueMutationSummary(response.body.queue),
|
||||
commands: {
|
||||
show: `bun scripts/cli.ts codex task ${taskId}`,
|
||||
detail: `bun scripts/cli.ts codex task ${taskId} --detail`,
|
||||
trace: `bun scripts/cli.ts codex task ${taskId} --trace --tail --limit ${defaultTraceLimit}`,
|
||||
output: `bun scripts/cli.ts codex output ${taskId} --tail --limit ${defaultOutputLimit}`,
|
||||
unread: `bun scripts/cli.ts codex tasks --unread --limit ${defaultTasksLimit}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function codexReadTask(taskId: string): unknown {
|
||||
return codexReadTaskWithFetcher(taskId, coreInternalFetch);
|
||||
}
|
||||
|
||||
export function codexReadTaskForTest(taskId: string, fetcher: CodexResponseFetcher): unknown {
|
||||
return codexReadTaskWithFetcher(taskId, fetcher);
|
||||
}
|
||||
|
||||
function compactQueueMutationSummary(value: unknown): Record<string, unknown> | null {
|
||||
const record = asRecord(value);
|
||||
if (record === null) return null;
|
||||
|
||||
Reference in New Issue
Block a user