@earendil-works/pi-coding-agent
Version:
Coding agent CLI with read, bash, edit, write tools and session management
97 lines • 3.88 kB
JavaScript
import { Worker } from "node:worker_threads";
import { resizeImageInProcess } from "./image-resize-core.js";
function toTransferableBytes(input) {
// Transfer detaches the buffer, so transfer a worker-owned copy and leave the
// caller's bytes intact.
return new Uint8Array(input);
}
function isResizeImageWorkerResponse(value) {
return value !== null && typeof value === "object";
}
function createResizeWorker(workerSpecifier) {
return new Worker(workerSpecifier);
}
async function resizeImageInWorker(workerSpecifier, inputBytes, mimeType, options) {
const worker = createResizeWorker(workerSpecifier);
try {
const inputBytesForWorker = toTransferableBytes(inputBytes);
return await new Promise((resolve, reject) => {
let settled = false;
const settle = (result) => {
if (settled)
return;
settled = true;
resolve(result);
};
const fail = (error) => {
if (settled)
return;
settled = true;
reject(error);
};
worker.once("message", (message) => {
if (!isResizeImageWorkerResponse(message)) {
fail(new Error("Invalid image resize worker response"));
return;
}
if (message.error) {
fail(new Error(message.error));
return;
}
settle(message.result ?? null);
});
worker.once("error", fail);
worker.once("exit", (code) => {
if (!settled) {
fail(new Error(`Image resize worker exited with code ${code}`));
}
});
worker.postMessage({
inputBytes: inputBytesForWorker,
mimeType,
options,
}, [inputBytesForWorker.buffer]);
});
}
finally {
void worker.terminate().catch(() => undefined);
}
}
/**
* Resize an image to fit within the specified max dimensions and encoded file size.
* Runs Photon in a worker thread so WASM decoding, resizing, and encoding do not
* block the TUI event loop. If the worker cannot be loaded (for example in some
* Bun compiled executable layouts), fall back to in-process resizing so image
* reads still work.
*/
export async function resizeImage(inputBytes, mimeType, options) {
const isTypeScriptRuntime = import.meta.url.endsWith(".ts");
const workerUrl = new URL(isTypeScriptRuntime ? "./image-resize-worker.ts" : "./image-resize-worker.js", import.meta.url);
// Bun compiled executables resolve worker entrypoints by string path, not via
// new URL(..., import.meta.url). Try the string path first under Bun so the
// release binary uses the embedded worker instead of falling back in-process.
if (typeof process.versions.bun === "string") {
try {
return await resizeImageInWorker("./src/utils/image-resize-worker.ts", inputBytes, mimeType, options);
}
catch { }
}
try {
return await resizeImageInWorker(workerUrl, inputBytes, mimeType, options);
}
catch {
return resizeImageInProcess(inputBytes, mimeType, options);
}
}
/**
* Format a dimension note for resized images.
* This helps the model understand the coordinate mapping.
*/
export function formatDimensionNote(result) {
if (!result.wasResized) {
return undefined;
}
const scale = result.originalWidth / result.width;
return `[Image: original ${result.originalWidth}x${result.originalHeight}, displayed at ${result.width}x${result.height}. Multiply coordinates by ${scale.toFixed(2)} to map to original image.]`;
}
//# sourceMappingURL=image-resize.js.map