fix: make AgentRun log tail render-only
This commit is contained in:
@@ -117,8 +117,10 @@ assertCondition(
|
|||||||
|
|
||||||
assertCondition(
|
assertCondition(
|
||||||
agentRunSource.includes("const effectiveLimit = options.tail ?? options.limit;")
|
agentRunSource.includes("const effectiveLimit = options.tail ?? options.limit;")
|
||||||
|
&& agentRunSource.includes("resourceLogsTailResult(config, ref.name, effectiveLimit, options.fullText)")
|
||||||
|
&& agentRunSource.includes("clientTail: {")
|
||||||
&& agentRunSource.includes("return renderEventLike(command, result, { ...options, limit: effectiveLimit }, \"Log\""),
|
&& agentRunSource.includes("return renderEventLike(command, result, { ...options, limit: effectiveLimit }, \"Log\""),
|
||||||
"AgentRun logs must map --tail N into the low-noise page limit and preserve pagination commands",
|
"AgentRun logs must map --tail N into render-only client tailing for human and raw outputs",
|
||||||
);
|
);
|
||||||
|
|
||||||
assertCondition(
|
assertCondition(
|
||||||
@@ -143,7 +145,7 @@ console.log(JSON.stringify({
|
|||||||
"AgentRun resource parser supports apply -f -",
|
"AgentRun resource parser supports apply -f -",
|
||||||
"AgentRun resource task dispatch and active task list visibility",
|
"AgentRun resource task dispatch and active task list visibility",
|
||||||
"AgentRun resource failure output is visible in human mode",
|
"AgentRun resource failure output is visible in human mode",
|
||||||
"AgentRun logs tail controls page limit",
|
"AgentRun logs tail is enforced by the render-only client",
|
||||||
"AgentRun dry-run mutations keep resource-command follow-up",
|
"AgentRun dry-run mutations keep resource-command follow-up",
|
||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
|
|||||||
+50
-2
@@ -498,12 +498,54 @@ async function resourceLogs(config: UniDeskConfig | null, command: string, actio
|
|||||||
const effectiveLimit = options.tail ?? options.limit;
|
const effectiveLimit = options.tail ?? options.limit;
|
||||||
const logArgs = ["output", ref.name, "--limit", String(effectiveLimit)];
|
const logArgs = ["output", ref.name, "--limit", String(effectiveLimit)];
|
||||||
if (options.afterSeq !== null) logArgs.push("--after-seq", String(options.afterSeq));
|
if (options.afterSeq !== null) logArgs.push("--after-seq", String(options.afterSeq));
|
||||||
else logArgs.push("--tail");
|
|
||||||
if (options.fullText) logArgs.push("--full-text");
|
if (options.fullText) logArgs.push("--full-text");
|
||||||
const result = await runAgentRunRestCommand(config, "sessions", logArgs);
|
let result: Record<string, unknown>;
|
||||||
|
if (options.afterSeq === null && options.tail !== null) {
|
||||||
|
result = await resourceLogsTailResult(config, ref.name, effectiveLimit, options.fullText);
|
||||||
|
} else {
|
||||||
|
result = await runAgentRunRestCommand(config, "sessions", logArgs);
|
||||||
|
}
|
||||||
return renderEventLike(command, result, { ...options, limit: effectiveLimit }, "Log", normalizeLogItems(innerData(result)), ref.name);
|
return renderEventLike(command, result, { ...options, limit: effectiveLimit }, "Log", normalizeLogItems(innerData(result)), ref.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resourceLogsTailResult(config: UniDeskConfig | null, sessionId: string, limit: number, fullText: boolean): Promise<Record<string, unknown>> {
|
||||||
|
const session = record(innerData(await runAgentRunRestCommand(config, "sessions", ["show", sessionId])));
|
||||||
|
const lastSeq = nonNegativeIntegerOrNull(session.lastEventSeq) ?? 0;
|
||||||
|
let window = Math.max(limit * 4, 100);
|
||||||
|
let result: Record<string, unknown> | null = null;
|
||||||
|
let data: Record<string, unknown> = {};
|
||||||
|
for (let attempt = 0; attempt < 6; attempt += 1) {
|
||||||
|
const afterSeq = Math.max(0, lastSeq - window);
|
||||||
|
const queryLimit = Math.max(limit, Math.min(1000, window));
|
||||||
|
const args = ["output", sessionId, "--limit", String(queryLimit), "--after-seq", String(afterSeq)];
|
||||||
|
if (fullText) args.push("--full-text");
|
||||||
|
result = await runAgentRunRestCommand(config, "sessions", args);
|
||||||
|
data = record(innerData(result));
|
||||||
|
const items = arrayRecords(data.items);
|
||||||
|
if (items.length >= limit || afterSeq === 0) break;
|
||||||
|
window *= 2;
|
||||||
|
}
|
||||||
|
if (result === null) return await runAgentRunRestCommand(config, "sessions", ["output", sessionId, "--limit", String(limit), "--after-seq", "0"]);
|
||||||
|
const items = arrayRecords(data.items);
|
||||||
|
const tailedItems = items.slice(-limit);
|
||||||
|
const lastReturnedSeq = tailedItems.length > 0 ? nonNegativeIntegerOrNull(tailedItems[tailedItems.length - 1]?.seq) : null;
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
data: {
|
||||||
|
...data,
|
||||||
|
items: tailedItems,
|
||||||
|
count: tailedItems.length,
|
||||||
|
cursor: lastReturnedSeq === null ? data.cursor : String(lastReturnedSeq),
|
||||||
|
clientTail: {
|
||||||
|
requested: limit,
|
||||||
|
sourceLastEventSeq: lastSeq,
|
||||||
|
scanned: items.length,
|
||||||
|
valuesPrinted: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function resourceResult(config: UniDeskConfig | null, command: string, action: string | undefined, args: string[], options: AgentRunResourceOptions): Promise<RenderedCliResult> {
|
async function resourceResult(config: UniDeskConfig | null, command: string, action: string | undefined, args: string[], options: AgentRunResourceOptions): Promise<RenderedCliResult> {
|
||||||
const ref = parseResourceRef(action, args);
|
const ref = parseResourceRef(action, args);
|
||||||
if (ref.kind === "run") {
|
if (ref.kind === "run") {
|
||||||
@@ -4029,6 +4071,12 @@ function stringOrNull(value: unknown): string | null {
|
|||||||
return typeof value === "string" && value.length > 0 ? value : null;
|
return typeof value === "string" && value.length > 0 ? value : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nonNegativeIntegerOrNull(value: unknown): number | null {
|
||||||
|
if (typeof value === "number" && Number.isInteger(value) && value >= 0) return value;
|
||||||
|
if (typeof value === "string" && /^\d+$/u.test(value)) return Number(value);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function parseArgoStatus(text: string): { revision: string | null; syncStatus: string | null; healthStatus: string | null } {
|
function parseArgoStatus(text: string): { revision: string | null; syncStatus: string | null; healthStatus: string | null } {
|
||||||
const lines = text.split(/\r?\n/u);
|
const lines = text.split(/\r?\n/u);
|
||||||
const index = lines.findIndex((line) => line.trim() === "argo");
|
const index = lines.findIndex((line) => line.trim() === "argo");
|
||||||
|
|||||||
Reference in New Issue
Block a user