mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
fix(cli)!: keep a selected JSON null in --filter-output output (#2333)
createCliResultOutput rendered an explicit null selected by
--filter-output as the empty document {}, the same output it uses when
the selection has no value at all. On the streamed JSON/JSONL path,
a consumer could not distinguish a selected null from a missing field.
Write a selected null as null in streamed JSON and JSONL. This also
preserves an unfiltered top-level null. The {} fallback stays for
undefined, functions and symbols. The --full-output envelope already
carried data: null for a selected null. The --token-count path still
hands results that fit the formatted-string limit back to Incur and
prints 0 for a selected null. Other formats and Incur-owned result
paths are unchanged.
Consumers must accept JSON null for a present null and distinguish it
from a missing selection. Use --full-output if an object envelope is
required. Keeping the old shared {} representation would continue
hiding this distinction.
Claude-Session: https://claude.ai/code/session_019TTGAv6fe859ebbCLLfLHP
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -216,8 +216,9 @@ export const createCliResultOutput = (
|
||||
: filtered === undefined
|
||||
? { ok: true, meta }
|
||||
: { ok: true, data: filtered, meta }
|
||||
: filtered === undefined ||
|
||||
filtered === null ||
|
||||
: // A selected null is a value; only a selection with no JSON value
|
||||
// falls back to the empty document.
|
||||
filtered === undefined ||
|
||||
typeof filtered === "function" ||
|
||||
typeof filtered === "symbol"
|
||||
? {}
|
||||
|
||||
@@ -561,3 +561,35 @@ describe("CLI result output surface", () => {
|
||||
});
|
||||
}, 60_000);
|
||||
});
|
||||
|
||||
describe("streamed CLI filtered selections", () => {
|
||||
it.each([
|
||||
["raw_result", "json", "null\n"],
|
||||
["raw_result", "jsonl", "null\n"],
|
||||
["nested.value", "json", '{"nested":{"value":null}}\n'],
|
||||
["missing", "json", "{}\n"],
|
||||
["count", "json", "0\n"],
|
||||
["enabled", "json", "false\n"],
|
||||
] as const)(
|
||||
"keeps the selected value of --filter-output %s in %s",
|
||||
async (filter, format, expected) => {
|
||||
const chunks: Buffer[] = [];
|
||||
const destination = new Writable({
|
||||
write(chunk: Buffer, _encoding, callback) {
|
||||
chunks.push(chunk);
|
||||
callback();
|
||||
},
|
||||
});
|
||||
const output = createCliResultOutput(
|
||||
["--format", format, "--filter-output", filter],
|
||||
destination,
|
||||
);
|
||||
if (output === undefined) throw new Error("Missing JSON output surface");
|
||||
await output.write(
|
||||
{ raw_result: null, nested: { value: null }, count: 0, enabled: false },
|
||||
{ command: "fixture", duration: "1ms", format },
|
||||
);
|
||||
expect(Buffer.concat(chunks).toString("utf8")).toBe(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user