fix: surface nested devicepod executor output
This commit is contained in:
@@ -1400,8 +1400,13 @@ test("cloud api dispatches authorized device jobs to the internal device-pod exe
|
||||
traceId: "trc_executor_refresh",
|
||||
operationId: "op_executor_refresh",
|
||||
job: { id: request.url.split("/").at(-2), devicePodId: "device-pod-71-freq", status: "completed", intent: "workspace.ls" },
|
||||
output: { text: "executor output", bytes: 15, truncation: { maxBytes: 12000, truncated: false } },
|
||||
text: "executor output"
|
||||
output: {
|
||||
executor: { status: "completed" },
|
||||
output: { dispatch: { exitCode: 0, stdoutBytes: 15 } },
|
||||
text: "executor output",
|
||||
bytes: 15,
|
||||
truncation: { maxBytes: 12000, truncated: false }
|
||||
}
|
||||
}));
|
||||
return;
|
||||
}
|
||||
@@ -1468,6 +1473,7 @@ test("cloud api dispatches authorized device jobs to the internal device-pod exe
|
||||
assert.equal(output.body.blocker, null);
|
||||
assert.equal(output.body.freshness.stale, false);
|
||||
assert.equal(output.body.output.text, "executor output");
|
||||
assert.deepEqual(output.body.output.output.dispatch, { exitCode: 0, stdoutBytes: 15 });
|
||||
assert.equal(output.body.truncation.truncated, false);
|
||||
assert.ok(executorRequests.some((item) => item.method === "GET" && item.url.endsWith(`/jobs/${runningJob.body.job.id}/output`)));
|
||||
|
||||
|
||||
@@ -1765,6 +1765,7 @@ async function jsonBody(request) {
|
||||
|
||||
function requiredText(value, field) { const text = textOr(value, ""); if (!text) throw Object.assign(new Error(`${field} is required`), { statusCode: 400, code: "invalid_params" }); return text; }
|
||||
function textOr(value, fallback) { const text = String(value ?? "").trim(); return text || fallback; }
|
||||
function firstString(...values) { return values.find((value) => typeof value === "string") ?? ""; }
|
||||
function normalizeObject(value) { return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : {}; }
|
||||
function assertDevicePodProfileSafe(profile, field = "profile") {
|
||||
const findings = [];
|
||||
@@ -1844,7 +1845,17 @@ function deviceJobBlocked(code, summary, retryable) { return { code, layer: "dev
|
||||
function devicePodExecutorBlocker(summary) { return { code: "device_pod_executor_unavailable", layer: "device-pod", retryable: true, summary, userMessage: "Device Pod 已授权,但内部执行服务当前不可用。" }; }
|
||||
function gatewayDispatchBlocker(summary) { return { code: "gateway_dispatch_unavailable", layer: "device-pod", retryable: true, summary, userMessage: "Device Pod 已授权,但当前没有可用 gateway/device-host-cli 执行通道。" }; }
|
||||
function normalizeDeviceJobStatus(status, httpStatus) { const text = textOr(status, ""); return ["queued", "running", "completed", "failed", "blocked", "canceled"].includes(text) ? text : httpStatus >= 400 ? "blocked" : "running"; }
|
||||
function executorOutputPayload(body, httpStatus) { return { executor: body ?? {}, output: normalizeObject(body?.output), text: typeof body?.text === "string" ? body.text : typeof body?.output?.text === "string" ? body.output.text : "", httpStatus }; }
|
||||
function executorOutputPayload(body, httpStatus) {
|
||||
const output = normalizeObject(body?.output);
|
||||
const nestedOutput = normalizeObject(output.output);
|
||||
const text = firstString(body?.text, output.text, nestedOutput.text);
|
||||
return {
|
||||
executor: body ?? {},
|
||||
output: Object.keys(nestedOutput).length > 0 ? nestedOutput : output,
|
||||
text,
|
||||
httpStatus
|
||||
};
|
||||
}
|
||||
function boundedOutput(output, maxBytes = DEVICE_JOB_OUTPUT_MAX_BYTES) {
|
||||
const source = normalizeObject(output);
|
||||
const text = typeof source.text === "string" ? source.text : stableJson(source);
|
||||
|
||||
Reference in New Issue
Block a user