@lorekit/cli 1.33.1 → 1.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lorekit.mjs +32 -2
- package/package.json +1 -1
package/bin/lorekit.mjs
CHANGED
|
@@ -718,8 +718,38 @@ async function main() {
|
|
|
718
718
|
}
|
|
719
719
|
|
|
720
720
|
main()
|
|
721
|
-
.then((code) =>
|
|
721
|
+
.then((code) => flushThenExit(code ?? 0))
|
|
722
722
|
.catch((e) => {
|
|
723
723
|
err(`${c.red('Error:')} ${e && e.stack ? e.stack : e}`);
|
|
724
|
-
|
|
724
|
+
flushThenExit(1);
|
|
725
725
|
});
|
|
726
|
+
|
|
727
|
+
// Exit only after stdout/stderr have drained.
|
|
728
|
+
//
|
|
729
|
+
// `process.exit()` truncates any output still buffered for a PIPE (the shape a
|
|
730
|
+
// spawned child's stdout has), because pipe writes are asynchronous. `lorekit
|
|
731
|
+
// mcp` streams newline-delimited JSON-RPC frames to stdout, and a large frame —
|
|
732
|
+
// e.g. a `memory.list` result for a big scope — overflows the pipe buffer, so
|
|
733
|
+
// exiting the instant `main()` resolves drops the tail of that write and the
|
|
734
|
+
// client sees a silent "no response" (this reproduced deterministically once a
|
|
735
|
+
// scope's payload crossed ~½ MB). Flushing first makes the final frame whole.
|
|
736
|
+
// The unref'd safety timer guarantees the process still exits if a stream never
|
|
737
|
+
// drains, so this can never turn a finished command into a hang.
|
|
738
|
+
function flushThenExit(code) {
|
|
739
|
+
let pending = 2;
|
|
740
|
+
const done = () => {
|
|
741
|
+
pending -= 1;
|
|
742
|
+
if (pending === 0) process.exit(code);
|
|
743
|
+
};
|
|
744
|
+
const safety = setTimeout(() => process.exit(code), 2000);
|
|
745
|
+
safety.unref?.();
|
|
746
|
+
for (const stream of [process.stdout, process.stderr]) {
|
|
747
|
+
try {
|
|
748
|
+
// An empty write's callback fires only after every previously-queued write
|
|
749
|
+
// has flushed to the fd, so it is a reliable drain barrier.
|
|
750
|
+
stream.write('', done);
|
|
751
|
+
} catch {
|
|
752
|
+
done();
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|