fix: compact noisy cli health outputs
This commit is contained in:
+115
-17
@@ -11,6 +11,7 @@ const maxTraceLimit = 500;
|
||||
const defaultOutputLimit = 20;
|
||||
const defaultTextPreviewChars = 12_000;
|
||||
const defaultTasksLimit = 20;
|
||||
const defaultQueuesLimit = 8;
|
||||
const maxTasksLimit = 100;
|
||||
const supervisorSectionReturnedLimit = 5;
|
||||
const supervisorRecentCompletedLimit = 5;
|
||||
@@ -255,7 +256,8 @@ interface CodexTasksDegraded {
|
||||
interface CodexQueuesOptions {
|
||||
full: boolean;
|
||||
limit: number;
|
||||
limitExplicit: boolean;
|
||||
offset: number;
|
||||
page: number;
|
||||
}
|
||||
|
||||
interface CodexPrPreflightOptions {
|
||||
@@ -593,6 +595,18 @@ function nonNegativeNumberOption(args: string[], names: string[], defaultValue:
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
function nonNegativeIntegerOption(args: string[], names: string[], defaultValue: number, maxValue = Number.MAX_SAFE_INTEGER): number {
|
||||
for (const name of names) {
|
||||
const index = args.indexOf(name);
|
||||
if (index === -1) continue;
|
||||
const raw = args[index + 1];
|
||||
const value = Number(raw);
|
||||
if (!Number.isInteger(value) || value < 0) throw new Error(`${name} must be a non-negative integer`);
|
||||
return Math.min(value, maxValue);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
function nullablePositiveNumberOption(args: string[], names: string[]): number | null {
|
||||
for (const name of names) {
|
||||
const index = args.indexOf(name);
|
||||
@@ -1176,6 +1190,42 @@ function compactExecutionDiagnostics(value: unknown): Record<string, unknown> |
|
||||
};
|
||||
}
|
||||
|
||||
function compactQueueExecutionDiagnostics(value: unknown): Record<string, unknown> | null {
|
||||
const diagnostics = compactExecutionDiagnostics(value);
|
||||
if (diagnostics === null) return null;
|
||||
const listBudget = asRecord(diagnostics.listBudget) ?? {};
|
||||
const omittedCounts = asRecord(listBudget.omittedCounts) ?? {};
|
||||
return {
|
||||
state: diagnostics.state ?? null,
|
||||
degraded: diagnostics.degraded ?? null,
|
||||
splitBrain: diagnostics.splitBrain ?? null,
|
||||
splitBrainLive: diagnostics.splitBrainLive ?? null,
|
||||
effectiveLiveness: diagnostics.effectiveLiveness ?? null,
|
||||
recommendedAction: diagnostics.recommendedAction ?? null,
|
||||
liveness: diagnostics.liveness ?? null,
|
||||
executionStateSource: diagnostics.executionStateSource ?? null,
|
||||
controlPlane: diagnostics.controlPlane ?? null,
|
||||
databaseActiveTaskCount: diagnostics.databaseActiveTaskCount ?? null,
|
||||
schedulerActiveRunSlotCount: diagnostics.schedulerActiveRunSlotCount ?? null,
|
||||
activeHeartbeatCount: diagnostics.activeHeartbeatCount ?? null,
|
||||
lastSchedulerHeartbeatAt: diagnostics.lastSchedulerHeartbeatAt ?? null,
|
||||
lastObservedAgentEventAt: diagnostics.lastObservedAgentEventAt ?? null,
|
||||
lastPersistedTraceAt: diagnostics.lastPersistedTraceAt ?? null,
|
||||
reasons: diagnostics.reasons ?? [],
|
||||
listBudget: {
|
||||
truncated: listBudget.truncated ?? false,
|
||||
omittedCounts: {
|
||||
databaseActiveTaskIds: omittedCounts.databaseActiveTaskIds ?? 0,
|
||||
activeHeartbeatTaskIds: omittedCounts.activeHeartbeatTaskIds ?? 0,
|
||||
heartbeatFreshTaskIds: omittedCounts.heartbeatFreshTaskIds ?? 0,
|
||||
heartbeatRiskTaskIds: omittedCounts.heartbeatRiskTaskIds ?? 0,
|
||||
reasons: omittedCounts.reasons ?? 0,
|
||||
},
|
||||
rawCommand: listBudget.rawCommand ?? "bun scripts/cli.ts microservice proxy code-queue /api/tasks/overview?limit=30 --raw --full",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function supervisorExecutionDiagnostics(value: unknown): Record<string, unknown> | null {
|
||||
const diagnostics = compactExecutionDiagnostics(value);
|
||||
if (diagnostics === null) return null;
|
||||
@@ -1577,12 +1627,17 @@ function parseTasksOptions(args: string[]): CodexTasksOptions {
|
||||
function parseQueuesOptions(args: string[]): CodexQueuesOptions {
|
||||
assertKnownOptions(args, {
|
||||
flags: ["--full", "--all"],
|
||||
valueOptions: ["--limit"],
|
||||
valueOptions: ["--limit", "--offset", "--page"],
|
||||
}, "codex queues");
|
||||
const limit = positiveIntegerOption(args, ["--limit"], defaultQueuesLimit, maxTasksLimit);
|
||||
const page = positiveIntegerOption(args, ["--page"], 1);
|
||||
const offsetExplicit = args.includes("--offset");
|
||||
const offset = offsetExplicit ? nonNegativeIntegerOption(args, ["--offset"], 0) : (page - 1) * limit;
|
||||
return {
|
||||
full: hasFlag(args, "--full") || hasFlag(args, "--all"),
|
||||
limit: positiveIntegerOption(args, ["--limit"], defaultTasksLimit, maxTasksLimit),
|
||||
limitExplicit: args.includes("--limit"),
|
||||
limit,
|
||||
offset,
|
||||
page: Math.floor(offset / limit) + 1,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2430,13 +2485,23 @@ function requireMergeTargetQueueId(args: string[], command: string): string {
|
||||
return raw.trim();
|
||||
}
|
||||
|
||||
function compactCounts(value: unknown): Record<string, unknown> {
|
||||
const counts = asRecord(value) ?? {};
|
||||
const compact: Record<string, unknown> = {};
|
||||
for (const [key, count] of Object.entries(counts)) {
|
||||
if (typeof count === "number" && count === 0) continue;
|
||||
compact[key] = count;
|
||||
}
|
||||
return compact;
|
||||
}
|
||||
|
||||
function compactQueueRow(value: unknown): Record<string, unknown> {
|
||||
const record = asRecord(value) ?? {};
|
||||
return {
|
||||
id: record.id ?? null,
|
||||
name: record.name ?? null,
|
||||
total: record.total ?? null,
|
||||
counts: record.counts ?? {},
|
||||
counts: compactCounts(record.counts),
|
||||
unreadTerminal: record.unreadTerminal ?? 0,
|
||||
activeTaskId: record.activeTaskId ?? null,
|
||||
runnableTaskId: record.runnableTaskId ?? null,
|
||||
@@ -2449,6 +2514,18 @@ function compactQueueRow(value: unknown): Record<string, unknown> {
|
||||
};
|
||||
}
|
||||
|
||||
function queueListCommand(options: Partial<CodexQueuesOptions> = {}): string {
|
||||
const full = options.full === true;
|
||||
const limit = options.limit ?? defaultQueuesLimit;
|
||||
const offset = options.offset ?? 0;
|
||||
return [
|
||||
"bun scripts/cli.ts codex queues",
|
||||
full ? "--full" : "",
|
||||
limit === defaultQueuesLimit ? "" : `--limit ${limit}`,
|
||||
offset > 0 ? `--offset ${offset}` : "",
|
||||
].filter(Boolean).join(" ");
|
||||
}
|
||||
|
||||
function compactQueuesResponse(body: Record<string, unknown>, options: CodexQueuesOptions, upstream: { ok: unknown; status: unknown }): Record<string, unknown> {
|
||||
const queue = asRecord(body.queue) ?? asRecord(body.summary) ?? {};
|
||||
const queues = asArray(body.queues).map(compactQueueRow);
|
||||
@@ -2458,17 +2535,31 @@ function compactQueuesResponse(body: Record<string, unknown>, options: CodexQueu
|
||||
const runnableQueues = queues.filter((row) => row.runnableTaskId !== null && row.runnableTaskId !== undefined);
|
||||
const activeQueues = queues.filter((row) => typeof row.id === "string" && activeIds.includes(row.id));
|
||||
const selected = options.full ? queues : Array.from(new Map([...activeQueues, ...unreadQueues, ...runnableQueues, ...nonemptyQueues].map((row) => [String(row.id), row])).values());
|
||||
const limitApplied = !options.full || options.limitExplicit;
|
||||
const visible = limitApplied ? selected.slice(0, options.limit) : selected;
|
||||
const diagnostics = compactExecutionDiagnostics(queue.executionDiagnostics);
|
||||
const visible = selected.slice(options.offset, options.offset + options.limit);
|
||||
const diagnostics = compactQueueExecutionDiagnostics(queue.executionDiagnostics);
|
||||
const activeTaskIds = boundedUniqueStringList(queue.activeTaskIds, Math.min(options.limit, maxTasksLimit));
|
||||
const queuedTaskIds = boundedUniqueStringList(queue.queuedTaskIds, Math.min(options.limit, maxTasksLimit));
|
||||
const nextOffset = options.offset + visible.length;
|
||||
const previousOffset = Math.max(0, options.offset - options.limit);
|
||||
const hasMore = nextOffset < selected.length;
|
||||
const hasPrevious = options.offset > 0;
|
||||
return {
|
||||
upstream,
|
||||
queues: {
|
||||
view: options.full ? "full" : "summary",
|
||||
bounded: limitApplied,
|
||||
bounded: true,
|
||||
outputPolicy: {
|
||||
default: "paged-low-noise",
|
||||
stableItemsPath: "data.queues.items[]",
|
||||
rawFullCommand: "bun scripts/cli.ts microservice proxy code-queue /api/queues --raw --full",
|
||||
},
|
||||
count: selected.length,
|
||||
returned: visible.length,
|
||||
hasMore: selected.length > visible.length,
|
||||
limit: options.limit,
|
||||
offset: options.offset,
|
||||
page: options.page,
|
||||
hasMore,
|
||||
hasPrevious,
|
||||
totals: {
|
||||
totalTasks: queue.total ?? null,
|
||||
queueCount: queue.queueCount ?? queues.length,
|
||||
@@ -2478,29 +2569,36 @@ function compactQueuesResponse(body: Record<string, unknown>, options: CodexQueu
|
||||
runnableQueueCount: runnableQueues.length,
|
||||
},
|
||||
activeQueueIds: queue.activeQueueIds ?? [],
|
||||
activeTaskIds: queue.activeTaskIds ?? [],
|
||||
queuedTaskIds: queue.queuedTaskIds ?? [],
|
||||
activeTaskIds: activeTaskIds.items,
|
||||
activeTaskIdsCount: activeTaskIds.count,
|
||||
activeTaskIdsTruncated: activeTaskIds.truncated,
|
||||
queuedTaskIds: queuedTaskIds.items,
|
||||
queuedTaskIdsCount: queuedTaskIds.count,
|
||||
queuedTaskIdsTruncated: queuedTaskIds.truncated,
|
||||
counts: queue.counts ?? {},
|
||||
unreadTerminal: queue.unreadTerminal ?? 0,
|
||||
executionDiagnostics: diagnostics,
|
||||
items: visible,
|
||||
...(options.full
|
||||
? {
|
||||
deprecatedFullArray: asArray(body.queues),
|
||||
compatibility: {
|
||||
deprecated: true,
|
||||
deprecatedPath: "data.queues.deprecatedFullArray[]",
|
||||
stablePath: "data.queues.items[]",
|
||||
message: "Use data.queues.items[] for both codex queues and codex queues --full.",
|
||||
deprecatedFullArrayOmitted: true,
|
||||
message: "Use data.queues.items[] for both codex queues and codex queues --full; raw full upstream is available only through the explicit raw command.",
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
commands: {
|
||||
refresh: `bun scripts/cli.ts codex queues${options.limit === defaultTasksLimit ? "" : ` --limit ${options.limit}`}`,
|
||||
full: `bun scripts/cli.ts codex queues --full${options.limit === defaultTasksLimit ? "" : ` --limit ${options.limit}`}`,
|
||||
refresh: queueListCommand({ full: options.full, limit: options.limit, offset: options.offset }),
|
||||
next: hasMore ? queueListCommand({ full: options.full, limit: options.limit, offset: nextOffset }) : null,
|
||||
previous: hasPrevious ? queueListCommand({ full: options.full, limit: options.limit, offset: previousOffset }) : null,
|
||||
first: queueListCommand({ full: options.full, limit: options.limit, offset: 0 }),
|
||||
full: queueListCommand({ full: true, limit: options.limit, offset: 0 }),
|
||||
tasks: `bun scripts/cli.ts codex tasks --view supervisor --limit ${Math.min(options.limit, defaultTasksLimit)}`,
|
||||
unread: `bun scripts/cli.ts codex tasks --unread --limit ${Math.min(options.limit, defaultTasksLimit)}`,
|
||||
raw: "bun scripts/cli.ts microservice proxy code-queue /api/queues --raw",
|
||||
raw: "bun scripts/cli.ts microservice proxy code-queue /api/queues --raw --full",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user