@codeworksh/harness 0.2.0 → 0.3.0-dev.20261013131320
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/{daytona-ByTHZelc.mjs → daytona-D4sNwzSr.mjs} +13 -7
- package/daytona-D4sNwzSr.mjs.map +1 -0
- package/effect.d.mts +848 -825
- package/effect.mjs +304 -179
- package/effect.mjs.map +1 -1
- package/package.json +3 -3
- package/resize-D34zcVQl.mjs +461 -0
- package/resize-D34zcVQl.mjs.map +1 -0
- package/sandboxes/daytona/index.mjs +1 -1
- package/tool/image/worker.mjs +1 -1
- package/daytona-ByTHZelc.mjs.map +0 -1
- package/resize-Dwv5dCgY.mjs +0 -263
- package/resize-Dwv5dCgY.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeworksh/harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-dev.20261013131320",
|
|
4
4
|
"description": "AI agent harness — agent loop, tools, plugins, sandbox, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -66,8 +66,8 @@
|
|
|
66
66
|
"node": ">=24.14.1"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@codeworksh/aikit": "
|
|
70
|
-
"@codeworksh/plugin": "0.2.
|
|
69
|
+
"@codeworksh/aikit": "0.11.0-dev.20261013131320",
|
|
70
|
+
"@codeworksh/plugin": "0.2.1-dev.20261013131320",
|
|
71
71
|
"@effect/platform-node": "4.0.1",
|
|
72
72
|
"@effect/sql-sqlite-node": "4.0.1",
|
|
73
73
|
"@npmcli/arborist": "^10.0.2",
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
import { registerHooks } from "node:module";
|
|
2
|
+
import { Config, Effect, Option, Schema } from "effect";
|
|
3
|
+
import { statSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { Script, constants } from "node:vm";
|
|
7
|
+
import { Worker } from "node:worker_threads";
|
|
8
|
+
//#region src/util/module.ts
|
|
9
|
+
/*!
|
|
10
|
+
* Adapted from OpenCode packages/util/src/runtime/import.node.ts.
|
|
11
|
+
*
|
|
12
|
+
* MIT License
|
|
13
|
+
*
|
|
14
|
+
* Copyright (c) 2025 opencode
|
|
15
|
+
*
|
|
16
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
18
|
+
* in the Software without restriction, including without limitation the rights
|
|
19
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
20
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
21
|
+
* furnished to do so, subject to the following conditions:
|
|
22
|
+
*
|
|
23
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
24
|
+
* copies or substantial portions of the Software.
|
|
25
|
+
*
|
|
26
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
31
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
|
+
* SOFTWARE.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Packages a plugin must share with the harness instead of using the copy installed beside it.
|
|
36
|
+
*
|
|
37
|
+
* A plugin is installed into the store as its own npm tree, so `effect` and the plugin SDK land
|
|
38
|
+
* there a second time. Two copies of the *same version* are still two module instances, and
|
|
39
|
+
* Effect Schema's checks do not survive the crossing: a schema built by one copy and evaluated by
|
|
40
|
+
* the other reports every check as failed, so a tool whose success type is `Schema.Finite` dies
|
|
41
|
+
* on "Expected a finite number" for `22800`. Nothing about that is visible at registration --
|
|
42
|
+
* `Schema.isSchema` passes, the JSON Schema is derived correctly, and the tool reaches the model
|
|
43
|
+
* -- so it surfaces on the first call rather than at boot.
|
|
44
|
+
*
|
|
45
|
+
* Resolution is the right place to fix it. A symlink into the store cannot be: a generation is
|
|
46
|
+
* immutable and shared by every project on the machine, while the harness doing the loading is
|
|
47
|
+
* whichever one is running now, and two applications embedding the harness need not agree on
|
|
48
|
+
* where their `effect` lives.
|
|
49
|
+
*
|
|
50
|
+
* Each package maps to the `Symbol.for` key of its {@link SharedRegistry}.
|
|
51
|
+
*/
|
|
52
|
+
const sharedPackages = /* @__PURE__ */ new Map([["effect", "codework.v1.effect"], ["@codeworksh/plugin", "codework.v1.plugin"]]);
|
|
53
|
+
const sharedScheme = "codeworkshared:";
|
|
54
|
+
function registryOf(key) {
|
|
55
|
+
return globalThis[Symbol.for(key)];
|
|
56
|
+
}
|
|
57
|
+
/** Publish a bundled host's registries, by package name, before any plugin loads. */
|
|
58
|
+
function share(packages) {
|
|
59
|
+
for (const [name, registry] of Object.entries(packages)) {
|
|
60
|
+
const key = sharedPackages.get(name);
|
|
61
|
+
if (key === void 0) throw new Error(`${name} is not a package shared with plugins`);
|
|
62
|
+
globalThis[Symbol.for(key)] = registry;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** A virtual module re-exporting the host's instance of `specifier`. */
|
|
66
|
+
function sharedSource(key, specifier, names) {
|
|
67
|
+
return [
|
|
68
|
+
`const m = await ${`globalThis[Symbol.for(${JSON.stringify(key)})]`}[${JSON.stringify(specifier)}].load();`,
|
|
69
|
+
...names.map((name, index) => `const $${index} = m[${JSON.stringify(name)}];`),
|
|
70
|
+
`export { ${names.map((name, index) => `$${index} as ${JSON.stringify(name)}`).join(", ")} };`
|
|
71
|
+
].join("\n");
|
|
72
|
+
}
|
|
73
|
+
/** The package a bare specifier names: `effect/Schema` -> `effect`, `@a/b/c` -> `@a/b`. */
|
|
74
|
+
function packageOf(specifier) {
|
|
75
|
+
if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.includes(":")) return "";
|
|
76
|
+
const segments = specifier.split("/");
|
|
77
|
+
return specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? "";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolve the shared packages to the host's own instances, for as long as `run` takes: from its
|
|
81
|
+
* registry when it published one, otherwise as though this module had imported them. Anything
|
|
82
|
+
* else resolves exactly as it would have.
|
|
83
|
+
*/
|
|
84
|
+
async function withSharedModules(run) {
|
|
85
|
+
const hook = registerHooks({
|
|
86
|
+
resolve(specifier, context, nextResolve) {
|
|
87
|
+
const key = sharedPackages.get(packageOf(specifier));
|
|
88
|
+
if (key === void 0) return nextResolve(specifier, context);
|
|
89
|
+
const registry = registryOf(key);
|
|
90
|
+
if (registry === void 0) return nextResolve(specifier, {
|
|
91
|
+
...context,
|
|
92
|
+
parentURL: import.meta.url
|
|
93
|
+
});
|
|
94
|
+
if (!Object.hasOwn(registry, specifier)) throw new Error(`${specifier} is not shared with plugins`);
|
|
95
|
+
return {
|
|
96
|
+
url: `${sharedScheme}${specifier}`,
|
|
97
|
+
shortCircuit: true
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
load(url, context, nextLoad) {
|
|
101
|
+
if (!url.startsWith(sharedScheme)) return nextLoad(url, context);
|
|
102
|
+
const specifier = url.slice(15);
|
|
103
|
+
const key = sharedPackages.get(packageOf(specifier));
|
|
104
|
+
const shared = registryOf(key)[specifier];
|
|
105
|
+
return {
|
|
106
|
+
format: "module",
|
|
107
|
+
source: sharedSource(key, specifier, shared.names),
|
|
108
|
+
shortCircuit: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
try {
|
|
113
|
+
return await run();
|
|
114
|
+
} finally {
|
|
115
|
+
hook.deregister();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Use Node's main loader even when the caller runs inside a bundler or test VM. */
|
|
119
|
+
async function importModule(specifier) {
|
|
120
|
+
const imported = await withSharedModules(() => new Script(`import(${JSON.stringify(specifier)})`, { importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER }).runInThisContext());
|
|
121
|
+
if (typeof imported !== "object" || imported === null) return imported;
|
|
122
|
+
const module = imported;
|
|
123
|
+
const exports = module["module.exports"];
|
|
124
|
+
if (exports !== module.default || typeof exports !== "object" && typeof exports !== "function" || exports === null) return imported;
|
|
125
|
+
return Object.assign({}, module, exports);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* `import.meta.resolve`. The main module of a single executable application, the standalone
|
|
129
|
+
* binary, has none, and its own `import()` reaches only built-ins: there the host calls
|
|
130
|
+
* {@link lendResolve} before anything resolves.
|
|
131
|
+
*/
|
|
132
|
+
let metaResolve = (specifier) => import.meta.resolve(specifier);
|
|
133
|
+
/**
|
|
134
|
+
* Borrow `import.meta.resolve` from a `data:` module loaded through the main loader, when this
|
|
135
|
+
* module has none. Not done at the top level: the binary bundles this module into an import cycle,
|
|
136
|
+
* where a top-level `await` never settles.
|
|
137
|
+
*/
|
|
138
|
+
async function lendResolve() {
|
|
139
|
+
if (typeof import.meta.resolve === "function") return;
|
|
140
|
+
metaResolve = (await importModule("data:text/javascript,export default (s) => import.meta.resolve(s)")).default;
|
|
141
|
+
}
|
|
142
|
+
/** Node resolution scoped synchronously to the caller. */
|
|
143
|
+
function resolveModule(specifier, directory, conditions) {
|
|
144
|
+
const hook = registerHooks({ resolve(target, context, nextResolve) {
|
|
145
|
+
return nextResolve(target, {
|
|
146
|
+
...context,
|
|
147
|
+
parentURL: pathToFileURL(path.join(directory, "package.json")).href,
|
|
148
|
+
...conditions === void 0 ? {} : { conditions: [.../* @__PURE__ */ new Set([...context.conditions, ...conditions])] }
|
|
149
|
+
});
|
|
150
|
+
} });
|
|
151
|
+
try {
|
|
152
|
+
const resolve = (target) => {
|
|
153
|
+
const resolved = metaResolve(path.isAbsolute(target) ? pathToFileURL(target).href : target);
|
|
154
|
+
if (resolved.startsWith("file:")) statSync(new URL(resolved));
|
|
155
|
+
return resolved;
|
|
156
|
+
};
|
|
157
|
+
try {
|
|
158
|
+
return resolve(specifier);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (path.extname(specifier) || !missing(error)) throw error;
|
|
161
|
+
for (const extension of [
|
|
162
|
+
".ts",
|
|
163
|
+
".tsx",
|
|
164
|
+
".js",
|
|
165
|
+
".jsx",
|
|
166
|
+
".mts",
|
|
167
|
+
".mjs",
|
|
168
|
+
".cts",
|
|
169
|
+
".cjs"
|
|
170
|
+
]) try {
|
|
171
|
+
return resolve(specifier + extension);
|
|
172
|
+
} catch (cause) {
|
|
173
|
+
if (!missing(cause)) throw cause;
|
|
174
|
+
}
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
} finally {
|
|
178
|
+
hook.deregister();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function missing(error) {
|
|
182
|
+
return error instanceof Error && "code" in error && [
|
|
183
|
+
"ENOENT",
|
|
184
|
+
"ENOTDIR",
|
|
185
|
+
"ERR_MODULE_NOT_FOUND"
|
|
186
|
+
].includes(String(error.code));
|
|
187
|
+
}
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/util/unpacked.ts
|
|
190
|
+
/**
|
|
191
|
+
* Import a package that reads files from beside its own modules (WASM, workers, native addons),
|
|
192
|
+
* so cannot be bundled. The standalone binary unpacks such packages into
|
|
193
|
+
* `CODEWORK_PACKAGES/node_modules`; anywhere else they resolve from here as usual.
|
|
194
|
+
*/
|
|
195
|
+
const load$1 = (name) => Effect.gen(function* () {
|
|
196
|
+
const directory = yield* Config.option(Config.String("CODEWORK_PACKAGES")).pipe(Effect.orDie);
|
|
197
|
+
const url = Option.isNone(directory) ? import.meta.resolve(name) : yield* Effect.try(() => resolveModule(name, directory.value));
|
|
198
|
+
return yield* Effect.tryPromise(() => importModule(url));
|
|
199
|
+
});
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/tool/image/exif.ts
|
|
202
|
+
/**
|
|
203
|
+
* EXIF orientation for JPEG and WebP. Photon decodes pixels as stored, so a phone
|
|
204
|
+
* photo taken sideways would reach the model sideways without this.
|
|
205
|
+
*/
|
|
206
|
+
const readOrientationFromTiff = (bytes, tiffStart) => {
|
|
207
|
+
if (tiffStart + 8 > bytes.length) return 1;
|
|
208
|
+
const le = (byte(bytes, tiffStart) << 8 | byte(bytes, tiffStart + 1)) === 18761;
|
|
209
|
+
const read16 = (pos) => le ? byte(bytes, pos) | byte(bytes, pos + 1) << 8 : byte(bytes, pos) << 8 | byte(bytes, pos + 1);
|
|
210
|
+
const read32 = (pos) => le ? (byte(bytes, pos) | byte(bytes, pos + 1) << 8 | byte(bytes, pos + 2) << 16 | byte(bytes, pos + 3) << 24) >>> 0 : (byte(bytes, pos) << 24 | byte(bytes, pos + 1) << 16 | byte(bytes, pos + 2) << 8 | byte(bytes, pos + 3)) >>> 0;
|
|
211
|
+
const ifdStart = tiffStart + read32(tiffStart + 4);
|
|
212
|
+
if (ifdStart + 2 > bytes.length) return 1;
|
|
213
|
+
const entryCount = read16(ifdStart);
|
|
214
|
+
for (let index = 0; index < entryCount; index++) {
|
|
215
|
+
const entryPos = ifdStart + 2 + index * 12;
|
|
216
|
+
if (entryPos + 12 > bytes.length) return 1;
|
|
217
|
+
if (read16(entryPos) === 274) {
|
|
218
|
+
const value = read16(entryPos + 8);
|
|
219
|
+
return value >= 1 && value <= 8 ? value : 1;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return 1;
|
|
223
|
+
};
|
|
224
|
+
const findJpegTiffOffset = (bytes) => {
|
|
225
|
+
let offset = 2;
|
|
226
|
+
while (offset < bytes.length - 1) {
|
|
227
|
+
if (bytes[offset] !== 255) return -1;
|
|
228
|
+
const marker = bytes[offset + 1];
|
|
229
|
+
if (marker === 255) {
|
|
230
|
+
offset++;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (marker === 225) {
|
|
234
|
+
const segmentStart = offset + 4;
|
|
235
|
+
if (segmentStart + 6 > bytes.length) return -1;
|
|
236
|
+
if (hasExifHeader(bytes, segmentStart)) return segmentStart + 6;
|
|
237
|
+
}
|
|
238
|
+
if (offset + 4 > bytes.length) return -1;
|
|
239
|
+
offset += 2 + (byte(bytes, offset + 2) << 8 | byte(bytes, offset + 3));
|
|
240
|
+
}
|
|
241
|
+
return -1;
|
|
242
|
+
};
|
|
243
|
+
const findWebpTiffOffset = (bytes) => {
|
|
244
|
+
let offset = 12;
|
|
245
|
+
while (offset + 8 <= bytes.length) {
|
|
246
|
+
const chunkId = String.fromCharCode(...bytes.subarray(offset, offset + 4));
|
|
247
|
+
const chunkSize = byte(bytes, offset + 4) | byte(bytes, offset + 5) << 8 | byte(bytes, offset + 6) << 16 | byte(bytes, offset + 7) << 24;
|
|
248
|
+
const dataStart = offset + 8;
|
|
249
|
+
if (chunkId === "EXIF") {
|
|
250
|
+
if (dataStart + chunkSize > bytes.length) return -1;
|
|
251
|
+
return chunkSize >= 6 && hasExifHeader(bytes, dataStart) ? dataStart + 6 : dataStart;
|
|
252
|
+
}
|
|
253
|
+
offset = dataStart + chunkSize + chunkSize % 2;
|
|
254
|
+
}
|
|
255
|
+
return -1;
|
|
256
|
+
};
|
|
257
|
+
const hasExifHeader = (bytes, offset) => [
|
|
258
|
+
69,
|
|
259
|
+
120,
|
|
260
|
+
105,
|
|
261
|
+
102,
|
|
262
|
+
0,
|
|
263
|
+
0
|
|
264
|
+
].every((value, index) => bytes[offset + index] === value);
|
|
265
|
+
const orientationOf = (bytes) => {
|
|
266
|
+
let tiffOffset = -1;
|
|
267
|
+
if (bytes[0] === 255 && bytes[1] === 216) tiffOffset = findJpegTiffOffset(bytes);
|
|
268
|
+
else if (String.fromCharCode(...bytes.subarray(0, 4)) === "RIFF" && String.fromCharCode(...bytes.subarray(8, 12)) === "WEBP") tiffOffset = findWebpTiffOffset(bytes);
|
|
269
|
+
return tiffOffset === -1 ? 1 : readOrientationFromTiff(bytes, tiffOffset);
|
|
270
|
+
};
|
|
271
|
+
const byte = (bytes, index) => bytes[index] ?? 0;
|
|
272
|
+
const rotate90 = (photon, image, dstIndex) => {
|
|
273
|
+
const w = image.get_width();
|
|
274
|
+
const h = image.get_height();
|
|
275
|
+
const src = image.get_raw_pixels();
|
|
276
|
+
const dst = new Uint8Array(src.length);
|
|
277
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) dst.set(src.subarray((y * w + x) * 4, (y * w + x) * 4 + 4), dstIndex(x, y, w, h) * 4);
|
|
278
|
+
return new photon.PhotonImage(dst, h, w);
|
|
279
|
+
};
|
|
280
|
+
const clockwise = (x, y, _w, h) => x * h + (h - 1 - y);
|
|
281
|
+
const counterClockwise = (x, y, w, h) => (w - 1 - x) * h + y;
|
|
282
|
+
/** Flips mutate `image`; rotations return a new image, which the caller frees alongside the old one. */
|
|
283
|
+
const applyOrientation = (photon, image, originalBytes) => {
|
|
284
|
+
switch (orientationOf(originalBytes)) {
|
|
285
|
+
case 2:
|
|
286
|
+
photon.fliph(image);
|
|
287
|
+
return image;
|
|
288
|
+
case 3:
|
|
289
|
+
photon.fliph(image);
|
|
290
|
+
photon.flipv(image);
|
|
291
|
+
return image;
|
|
292
|
+
case 4:
|
|
293
|
+
photon.flipv(image);
|
|
294
|
+
return image;
|
|
295
|
+
case 5: {
|
|
296
|
+
const rotated = rotate90(photon, image, clockwise);
|
|
297
|
+
photon.fliph(rotated);
|
|
298
|
+
return rotated;
|
|
299
|
+
}
|
|
300
|
+
case 6: return rotate90(photon, image, clockwise);
|
|
301
|
+
case 7: {
|
|
302
|
+
const rotated = rotate90(photon, image, counterClockwise);
|
|
303
|
+
photon.fliph(rotated);
|
|
304
|
+
return rotated;
|
|
305
|
+
}
|
|
306
|
+
case 8: return rotate90(photon, image, counterClockwise);
|
|
307
|
+
default: return image;
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region src/tool/image/photon.ts
|
|
312
|
+
/** Photon, loaded once on first use; `undefined` when its WASM cannot load, so images degrade instead of failing reads. */
|
|
313
|
+
const load = Effect.cached(load$1("@silvia-odwyer/photon-node").pipe(Effect.map((module) => module), Effect.orElseSucceed(() => void 0))).pipe(Effect.runSync);
|
|
314
|
+
/** Decode with EXIF orientation applied. The caller frees the result. */
|
|
315
|
+
const decode = (photon, bytes) => {
|
|
316
|
+
const raw = photon.PhotonImage.new_from_byteslice(bytes);
|
|
317
|
+
const oriented = applyOrientation(photon, raw, bytes);
|
|
318
|
+
if (oriented !== raw) raw.free();
|
|
319
|
+
return oriented;
|
|
320
|
+
};
|
|
321
|
+
//#endregion
|
|
322
|
+
//#region src/tool/image/resize.ts
|
|
323
|
+
const defaults = {
|
|
324
|
+
maxWidth: 2e3,
|
|
325
|
+
maxHeight: 2e3,
|
|
326
|
+
maxBytes: 4718592,
|
|
327
|
+
jpegQuality: 80
|
|
328
|
+
};
|
|
329
|
+
/** Tags worker replies: Node posts its own messages on the worker channel too (e.g. under `--watch`). */
|
|
330
|
+
const REPLY = "codework:photon-image-resize";
|
|
331
|
+
const base64 = (bytes) => {
|
|
332
|
+
const data = Buffer.from(bytes).toString("base64");
|
|
333
|
+
return {
|
|
334
|
+
data,
|
|
335
|
+
size: data.length
|
|
336
|
+
};
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* Fit an image within the dimensions and encoded size, in this thread. `null`
|
|
340
|
+
* when Photon is unavailable or nothing fits. Fits by: scaling to the max
|
|
341
|
+
* dimensions, keeping the smaller of PNG and JPEG, lowering JPEG quality, then
|
|
342
|
+
* shrinking by a quarter at a time down to 1x1.
|
|
343
|
+
*/
|
|
344
|
+
const resizeInProcess = (input, mimeType, options = defaults) => Effect.map(load, (photon) => {
|
|
345
|
+
if (photon === void 0) return null;
|
|
346
|
+
let image;
|
|
347
|
+
try {
|
|
348
|
+
image = decode(photon, input);
|
|
349
|
+
const originalWidth = image.get_width();
|
|
350
|
+
const originalHeight = image.get_height();
|
|
351
|
+
const inputSize = Math.ceil(input.byteLength / 3) * 4;
|
|
352
|
+
if (originalWidth <= options.maxWidth && originalHeight <= options.maxHeight && inputSize < options.maxBytes) return {
|
|
353
|
+
data: Buffer.from(input).toString("base64"),
|
|
354
|
+
mimeType,
|
|
355
|
+
originalWidth,
|
|
356
|
+
originalHeight,
|
|
357
|
+
width: originalWidth,
|
|
358
|
+
height: originalHeight,
|
|
359
|
+
wasResized: false
|
|
360
|
+
};
|
|
361
|
+
let width = originalWidth;
|
|
362
|
+
let height = originalHeight;
|
|
363
|
+
if (width > options.maxWidth) {
|
|
364
|
+
height = Math.max(1, Math.round(height * options.maxWidth / width));
|
|
365
|
+
width = options.maxWidth;
|
|
366
|
+
}
|
|
367
|
+
if (height > options.maxHeight) {
|
|
368
|
+
width = Math.max(1, Math.round(width * options.maxHeight / height));
|
|
369
|
+
height = options.maxHeight;
|
|
370
|
+
}
|
|
371
|
+
const qualities = [.../* @__PURE__ */ new Set([
|
|
372
|
+
options.jpegQuality,
|
|
373
|
+
85,
|
|
374
|
+
70,
|
|
375
|
+
55,
|
|
376
|
+
40
|
|
377
|
+
])];
|
|
378
|
+
while (true) {
|
|
379
|
+
const resized = photon.resize(image, width, height, photon.SamplingFilter.Lanczos3);
|
|
380
|
+
try {
|
|
381
|
+
const fit = [{
|
|
382
|
+
...base64(resized.get_bytes()),
|
|
383
|
+
mimeType: "image/png"
|
|
384
|
+
}, ...qualities.map((quality) => ({
|
|
385
|
+
...base64(resized.get_bytes_jpeg(quality)),
|
|
386
|
+
mimeType: "image/jpeg"
|
|
387
|
+
}))].find((candidate) => candidate.size < options.maxBytes);
|
|
388
|
+
if (fit !== void 0) return {
|
|
389
|
+
data: fit.data,
|
|
390
|
+
mimeType: fit.mimeType,
|
|
391
|
+
originalWidth,
|
|
392
|
+
originalHeight,
|
|
393
|
+
width,
|
|
394
|
+
height,
|
|
395
|
+
wasResized: true
|
|
396
|
+
};
|
|
397
|
+
} finally {
|
|
398
|
+
resized.free();
|
|
399
|
+
}
|
|
400
|
+
const nextWidth = Math.max(1, Math.floor(width * .75));
|
|
401
|
+
const nextHeight = Math.max(1, Math.floor(height * .75));
|
|
402
|
+
if (nextWidth === width && nextHeight === height) return null;
|
|
403
|
+
width = nextWidth;
|
|
404
|
+
height = nextHeight;
|
|
405
|
+
}
|
|
406
|
+
} catch {
|
|
407
|
+
return null;
|
|
408
|
+
} finally {
|
|
409
|
+
image?.free();
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
const workerUrl = Effect.gen(function* () {
|
|
413
|
+
const unpacked = yield* Config.option(Config.String("CODEWORK_IMAGE_WORKER"));
|
|
414
|
+
if (Option.isSome(unpacked)) return pathToFileURL(unpacked.value);
|
|
415
|
+
return import.meta.url.endsWith(".ts") ? new URL("./worker.ts", import.meta.url) : new URL("./tool/image/worker.mjs", import.meta.url);
|
|
416
|
+
}).pipe(Effect.orDie);
|
|
417
|
+
/** The worker could not resize; the caller falls back to this thread. */
|
|
418
|
+
var WorkerError = class extends Schema.TaggedError()("ImageResizeWorkerError", { message: Schema.String }) {};
|
|
419
|
+
const inWorker = (input, mimeType, options) => Effect.flatMap(workerUrl, (url) => Effect.callback((resume) => {
|
|
420
|
+
let worker;
|
|
421
|
+
try {
|
|
422
|
+
worker = new Worker(url);
|
|
423
|
+
} catch (cause) {
|
|
424
|
+
resume(Effect.fail(new WorkerError({ message: String(cause) })));
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const done = (effect) => {
|
|
428
|
+
resume(effect);
|
|
429
|
+
worker.terminate().catch(() => void 0);
|
|
430
|
+
};
|
|
431
|
+
worker.on("message", (message) => {
|
|
432
|
+
const reply = message;
|
|
433
|
+
if (reply?.type !== "codework:photon-image-resize") return;
|
|
434
|
+
done("error" in reply ? Effect.fail(new WorkerError({ message: reply.error })) : Effect.succeed(reply.result));
|
|
435
|
+
});
|
|
436
|
+
worker.once("error", (error) => done(Effect.fail(new WorkerError({ message: error.message }))));
|
|
437
|
+
worker.once("exit", (code) => done(Effect.fail(new WorkerError({ message: `Image resize worker exited with code ${code}` }))));
|
|
438
|
+
const bytes = new Uint8Array(input);
|
|
439
|
+
worker.postMessage({
|
|
440
|
+
input: bytes,
|
|
441
|
+
mimeType,
|
|
442
|
+
options
|
|
443
|
+
}, [bytes.buffer]);
|
|
444
|
+
return Effect.promise(() => worker.terminate());
|
|
445
|
+
}));
|
|
446
|
+
/**
|
|
447
|
+
* {@link resizeInProcess} on a worker thread, so decoding and encoding a large
|
|
448
|
+
* image never blocks the harness's event loop. Falls back to this thread when a
|
|
449
|
+
* worker cannot start, so a read still works.
|
|
450
|
+
*/
|
|
451
|
+
const resize = (input, mimeType, options = defaults) => inWorker(input, mimeType, options).pipe(Effect.catch(() => resizeInProcess(input, mimeType, options)));
|
|
452
|
+
/** Tells the model how to map coordinates on a resized image back to the original. */
|
|
453
|
+
const dimensionNote = (result) => {
|
|
454
|
+
if (!result.wasResized) return void 0;
|
|
455
|
+
const scale = result.originalWidth / result.width;
|
|
456
|
+
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.]`;
|
|
457
|
+
};
|
|
458
|
+
//#endregion
|
|
459
|
+
export { decode as a, importModule as c, share as d, resizeInProcess as i, lendResolve as l, dimensionNote as n, load as o, resize as r, load$1 as s, REPLY as t, resolveModule as u };
|
|
460
|
+
|
|
461
|
+
//# sourceMappingURL=resize-D34zcVQl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resize-D34zcVQl.mjs","names":["load","unpacked"],"sources":["../../src/util/module.ts","../../src/util/unpacked.ts","../../src/tool/image/exif.ts","../../src/tool/image/photon.ts","../../src/tool/image/resize.ts"],"sourcesContent":["/*!\n * Adapted from OpenCode packages/util/src/runtime/import.node.ts.\n *\n * MIT License\n *\n * Copyright (c) 2025 opencode\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n/* oxlint-disable effecttsgo/async-function -- Native module loading exposes a Promise-based importer contract. */\n// Resolution hooks cannot yield to Effect; existence checks must stay synchronous.\n// @effect-diagnostics-next-line nodeBuiltinImport:off\nimport { statSync } from \"node:fs\";\nimport { registerHooks } from \"node:module\";\n// @effect-diagnostics-next-line nodeBuiltinImport:off\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { Script, constants } from \"node:vm\";\n\n/**\n * Packages a plugin must share with the harness instead of using the copy installed beside it.\n *\n * A plugin is installed into the store as its own npm tree, so `effect` and the plugin SDK land\n * there a second time. Two copies of the *same version* are still two module instances, and\n * Effect Schema's checks do not survive the crossing: a schema built by one copy and evaluated by\n * the other reports every check as failed, so a tool whose success type is `Schema.Finite` dies\n * on \"Expected a finite number\" for `22800`. Nothing about that is visible at registration --\n * `Schema.isSchema` passes, the JSON Schema is derived correctly, and the tool reaches the model\n * -- so it surfaces on the first call rather than at boot.\n *\n * Resolution is the right place to fix it. A symlink into the store cannot be: a generation is\n * immutable and shared by every project on the machine, while the harness doing the loading is\n * whichever one is running now, and two applications embedding the harness need not agree on\n * where their `effect` lives.\n *\n * Each package maps to the `Symbol.for` key of its {@link SharedRegistry}.\n */\nconst sharedPackages: ReadonlyMap<string, string> = new Map([\n\t[\"effect\", \"codework.v1.effect\"],\n\t[\"@codeworksh/plugin\", \"codework.v1.plugin\"],\n]);\n\n/** One module of a shared package, as a bundled host publishes it. */\nexport interface SharedModule {\n\t/** Its export names; an ES module's exports must be known before it runs. */\n\treadonly names: ReadonlyArray<string>;\n\treadonly load: () => Promise<Record<string, unknown>>;\n}\n\n/**\n * A shared package's modules by specifier (`effect/Schema`), published on\n * `globalThis[Symbol.for(key)]` by a host that is a single bundled file, such as the standalone\n * binary. Such a host has no `effect` on disk to resolve to, so plugins get virtual modules that\n * re-export its own instances. Modules load on first import: `effect` alone has hundreds.\n */\nexport type SharedRegistry = Readonly<Record<string, SharedModule>>;\n\nconst sharedScheme = \"codeworkshared:\";\n\nfunction registryOf(key: string): SharedRegistry | undefined {\n\treturn (globalThis as Record<symbol, SharedRegistry | undefined>)[Symbol.for(key)];\n}\n\n/** Publish a bundled host's registries, by package name, before any plugin loads. */\nexport function share(packages: Readonly<Record<string, SharedRegistry>>): void {\n\tfor (const [name, registry] of Object.entries(packages)) {\n\t\tconst key = sharedPackages.get(name);\n\t\tif (key === undefined) throw new Error(`${name} is not a package shared with plugins`);\n\t\t(globalThis as Record<symbol, SharedRegistry>)[Symbol.for(key)] = registry;\n\t}\n}\n\n/** A virtual module re-exporting the host's instance of `specifier`. */\nfunction sharedSource(key: string, specifier: string, names: ReadonlyArray<string>): string {\n\tconst registry = `globalThis[Symbol.for(${JSON.stringify(key)})]`;\n\treturn [\n\t\t`const m = await ${registry}[${JSON.stringify(specifier)}].load();`,\n\t\t...names.map((name, index) => `const $${index} = m[${JSON.stringify(name)}];`),\n\t\t// String export names, since some are reserved words (`Effect.void`).\n\t\t`export { ${names.map((name, index) => `$${index} as ${JSON.stringify(name)}`).join(\", \")} };`,\n\t].join(\"\\n\");\n}\n\n/** The package a bare specifier names: `effect/Schema` -> `effect`, `@a/b/c` -> `@a/b`. */\nfunction packageOf(specifier: string): string {\n\tif (specifier.startsWith(\".\") || specifier.startsWith(\"/\") || specifier.includes(\":\")) return \"\";\n\tconst segments = specifier.split(\"/\");\n\treturn specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : (segments[0] ?? \"\");\n}\n\n/**\n * Resolve the shared packages to the host's own instances, for as long as `run` takes: from its\n * registry when it published one, otherwise as though this module had imported them. Anything\n * else resolves exactly as it would have.\n */\nasync function withSharedModules<A>(run: () => Promise<A>): Promise<A> {\n\tconst hook = registerHooks({\n\t\tresolve(specifier, context, nextResolve) {\n\t\t\tconst key = sharedPackages.get(packageOf(specifier));\n\t\t\tif (key === undefined) return nextResolve(specifier, context);\n\t\t\tconst registry = registryOf(key);\n\t\t\tif (registry === undefined) return nextResolve(specifier, { ...context, parentURL: import.meta.url });\n\t\t\t// Falling back to the plugin's own copy would bring back the two-instance failure above.\n\t\t\tif (!Object.hasOwn(registry, specifier)) throw new Error(`${specifier} is not shared with plugins`);\n\t\t\treturn { url: `${sharedScheme}${specifier}`, shortCircuit: true };\n\t\t},\n\t\tload(url, context, nextLoad) {\n\t\t\tif (!url.startsWith(sharedScheme)) return nextLoad(url, context);\n\t\t\tconst specifier = url.slice(sharedScheme.length);\n\t\t\tconst key = sharedPackages.get(packageOf(specifier))!;\n\t\t\tconst shared = registryOf(key)![specifier]!;\n\t\t\treturn { format: \"module\", source: sharedSource(key, specifier, shared.names), shortCircuit: true };\n\t\t},\n\t});\n\ttry {\n\t\treturn await run();\n\t} finally {\n\t\thook.deregister();\n\t}\n}\n\n/** Use Node's main loader even when the caller runs inside a bundler or test VM. */\nexport async function importModule(specifier: string): Promise<unknown> {\n\tconst imported: unknown = await withSharedModules(\n\t\t() =>\n\t\t\tnew Script(`import(${JSON.stringify(specifier)})`, {\n\t\t\t\timportModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,\n\t\t\t}).runInThisContext() as Promise<unknown>,\n\t);\n\tif (typeof imported !== \"object\" || imported === null) return imported;\n\tconst module = imported as Record<string, unknown>;\n\tconst exports = module[\"module.exports\"];\n\tif (exports !== module.default || (typeof exports !== \"object\" && typeof exports !== \"function\") || exports === null)\n\t\treturn imported;\n\treturn Object.assign({}, module, exports);\n}\n\n/**\n * `import.meta.resolve`. The main module of a single executable application, the standalone\n * binary, has none, and its own `import()` reaches only built-ins: there the host calls\n * {@link lendResolve} before anything resolves.\n */\nlet metaResolve = (specifier: string): string => import.meta.resolve(specifier);\n\n/**\n * Borrow `import.meta.resolve` from a `data:` module loaded through the main loader, when this\n * module has none. Not done at the top level: the binary bundles this module into an import cycle,\n * where a top-level `await` never settles.\n */\nexport async function lendResolve(): Promise<void> {\n\tif (typeof import.meta.resolve === \"function\") return;\n\tconst lender = (await importModule(\"data:text/javascript,export default (s) => import.meta.resolve(s)\")) as {\n\t\treadonly default: (specifier: string) => string;\n\t};\n\tmetaResolve = lender.default;\n}\n\n/** Node resolution scoped synchronously to the caller. */\nexport function resolveModule(specifier: string, directory: string, conditions?: ReadonlyArray<string>): string {\n\tconst hook = registerHooks({\n\t\tresolve(target, context, nextResolve) {\n\t\t\treturn nextResolve(target, {\n\t\t\t\t...context,\n\t\t\t\tparentURL: pathToFileURL(path.join(directory, \"package.json\")).href,\n\t\t\t\t...(conditions === undefined ? {} : { conditions: [...new Set([...context.conditions, ...conditions])] }),\n\t\t\t});\n\t\t},\n\t});\n\ttry {\n\t\tconst resolve = (target: string) => {\n\t\t\tconst resolved = metaResolve(path.isAbsolute(target) ? pathToFileURL(target).href : target);\n\t\t\tif (resolved.startsWith(\"file:\")) statSync(new URL(resolved));\n\t\t\treturn resolved;\n\t\t};\n\t\ttry {\n\t\t\treturn resolve(specifier);\n\t\t} catch (error) {\n\t\t\tif (path.extname(specifier) || !missing(error)) throw error;\n\t\t\tfor (const extension of [\".ts\", \".tsx\", \".js\", \".jsx\", \".mts\", \".mjs\", \".cts\", \".cjs\"]) {\n\t\t\t\ttry {\n\t\t\t\t\treturn resolve(specifier + extension);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tif (!missing(cause)) throw cause;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t} finally {\n\t\thook.deregister();\n\t}\n}\n\nfunction missing(error: unknown): boolean {\n\treturn (\n\t\terror instanceof Error &&\n\t\t\"code\" in error &&\n\t\t[\"ENOENT\", \"ENOTDIR\", \"ERR_MODULE_NOT_FOUND\"].includes(String(error.code))\n\t);\n}\n","import { type Cause, Config, Effect, Option } from \"effect\";\nimport { importModule, resolveModule } from \"./module.ts\";\n\n/**\n * Import a package that reads files from beside its own modules (WASM, workers, native addons),\n * so cannot be bundled. The standalone binary unpacks such packages into\n * `CODEWORK_PACKAGES/node_modules`; anywhere else they resolve from here as usual.\n */\nexport const load = (name: string): Effect.Effect<unknown, Cause.UnknownError> =>\n\tEffect.gen(function* () {\n\t\tconst directory = yield* Config.option(Config.String(\"CODEWORK_PACKAGES\")).pipe(Effect.orDie);\n\t\tconst url = Option.isNone(directory)\n\t\t\t? import.meta.resolve(name)\n\t\t\t: yield* Effect.try(() => resolveModule(name, directory.value));\n\t\t// The binary's own `import()` reaches only built-ins.\n\t\treturn yield* Effect.tryPromise(() => importModule(url));\n\t});\n","import type { Photon, PhotonImage } from \"./photon.ts\";\n\n/**\n * EXIF orientation for JPEG and WebP. Photon decodes pixels as stored, so a phone\n * photo taken sideways would reach the model sideways without this.\n */\n\nconst readOrientationFromTiff = (bytes: Uint8Array, tiffStart: number): number => {\n\tif (tiffStart + 8 > bytes.length) return 1;\n\tconst le = ((byte(bytes, tiffStart) << 8) | byte(bytes, tiffStart + 1)) === 0x4949;\n\tconst read16 = (pos: number): number =>\n\t\tle ? byte(bytes, pos) | (byte(bytes, pos + 1) << 8) : (byte(bytes, pos) << 8) | byte(bytes, pos + 1);\n\tconst read32 = (pos: number): number =>\n\t\tle\n\t\t\t? (byte(bytes, pos) |\n\t\t\t\t\t(byte(bytes, pos + 1) << 8) |\n\t\t\t\t\t(byte(bytes, pos + 2) << 16) |\n\t\t\t\t\t(byte(bytes, pos + 3) << 24)) >>>\n\t\t\t\t0\n\t\t\t: ((byte(bytes, pos) << 24) |\n\t\t\t\t\t(byte(bytes, pos + 1) << 16) |\n\t\t\t\t\t(byte(bytes, pos + 2) << 8) |\n\t\t\t\t\tbyte(bytes, pos + 3)) >>>\n\t\t\t\t0;\n\n\tconst ifdStart = tiffStart + read32(tiffStart + 4);\n\tif (ifdStart + 2 > bytes.length) return 1;\n\tconst entryCount = read16(ifdStart);\n\tfor (let index = 0; index < entryCount; index++) {\n\t\tconst entryPos = ifdStart + 2 + index * 12;\n\t\tif (entryPos + 12 > bytes.length) return 1;\n\t\tif (read16(entryPos) === 0x0112) {\n\t\t\tconst value = read16(entryPos + 8);\n\t\t\treturn value >= 1 && value <= 8 ? value : 1;\n\t\t}\n\t}\n\treturn 1;\n};\n\nconst findJpegTiffOffset = (bytes: Uint8Array): number => {\n\tlet offset = 2;\n\twhile (offset < bytes.length - 1) {\n\t\tif (bytes[offset] !== 0xff) return -1;\n\t\tconst marker = bytes[offset + 1];\n\t\tif (marker === 0xff) {\n\t\t\toffset++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (marker === 0xe1) {\n\t\t\tconst segmentStart = offset + 4;\n\t\t\tif (segmentStart + 6 > bytes.length) return -1;\n\t\t\tif (hasExifHeader(bytes, segmentStart)) return segmentStart + 6;\n\t\t}\n\t\tif (offset + 4 > bytes.length) return -1;\n\t\toffset += 2 + ((byte(bytes, offset + 2) << 8) | byte(bytes, offset + 3));\n\t}\n\treturn -1;\n};\n\nconst findWebpTiffOffset = (bytes: Uint8Array): number => {\n\tlet offset = 12;\n\twhile (offset + 8 <= bytes.length) {\n\t\tconst chunkId = String.fromCharCode(...bytes.subarray(offset, offset + 4));\n\t\tconst chunkSize =\n\t\t\tbyte(bytes, offset + 4) |\n\t\t\t(byte(bytes, offset + 5) << 8) |\n\t\t\t(byte(bytes, offset + 6) << 16) |\n\t\t\t(byte(bytes, offset + 7) << 24);\n\t\tconst dataStart = offset + 8;\n\t\tif (chunkId === \"EXIF\") {\n\t\t\tif (dataStart + chunkSize > bytes.length) return -1;\n\t\t\t// Some WebP files carry an \"Exif\\0\\0\" prefix before the TIFF header.\n\t\t\treturn chunkSize >= 6 && hasExifHeader(bytes, dataStart) ? dataStart + 6 : dataStart;\n\t\t}\n\t\t// RIFF chunks are padded to an even size.\n\t\toffset = dataStart + chunkSize + (chunkSize % 2);\n\t}\n\treturn -1;\n};\n\nconst hasExifHeader = (bytes: Uint8Array, offset: number): boolean =>\n\t[0x45, 0x78, 0x69, 0x66, 0x00, 0x00].every((value, index) => bytes[offset + index] === value);\n\nconst orientationOf = (bytes: Uint8Array): number => {\n\tlet tiffOffset = -1;\n\tif (bytes[0] === 0xff && bytes[1] === 0xd8) tiffOffset = findJpegTiffOffset(bytes);\n\telse if (\n\t\tString.fromCharCode(...bytes.subarray(0, 4)) === \"RIFF\" &&\n\t\tString.fromCharCode(...bytes.subarray(8, 12)) === \"WEBP\"\n\t)\n\t\ttiffOffset = findWebpTiffOffset(bytes);\n\treturn tiffOffset === -1 ? 1 : readOrientationFromTiff(bytes, tiffOffset);\n};\n\nconst byte = (bytes: Uint8Array, index: number): number => bytes[index] ?? 0;\n\ntype DstIndex = (x: number, y: number, w: number, h: number) => number;\n\nconst rotate90 = (photon: Photon, image: PhotonImage, dstIndex: DstIndex): PhotonImage => {\n\tconst w = image.get_width();\n\tconst h = image.get_height();\n\tconst src = image.get_raw_pixels();\n\tconst dst = new Uint8Array(src.length);\n\tfor (let y = 0; y < h; y++) {\n\t\tfor (let x = 0; x < w; x++) {\n\t\t\tdst.set(src.subarray((y * w + x) * 4, (y * w + x) * 4 + 4), dstIndex(x, y, w, h) * 4);\n\t\t}\n\t}\n\treturn new photon.PhotonImage(dst, h, w);\n};\n\nconst clockwise: DstIndex = (x, y, _w, h) => x * h + (h - 1 - y);\nconst counterClockwise: DstIndex = (x, y, w, h) => (w - 1 - x) * h + y;\n\n/** Flips mutate `image`; rotations return a new image, which the caller frees alongside the old one. */\nexport const applyOrientation = (photon: Photon, image: PhotonImage, originalBytes: Uint8Array): PhotonImage => {\n\tswitch (orientationOf(originalBytes)) {\n\t\tcase 2:\n\t\t\tphoton.fliph(image);\n\t\t\treturn image;\n\t\tcase 3:\n\t\t\tphoton.fliph(image);\n\t\t\tphoton.flipv(image);\n\t\t\treturn image;\n\t\tcase 4:\n\t\t\tphoton.flipv(image);\n\t\t\treturn image;\n\t\tcase 5: {\n\t\t\tconst rotated = rotate90(photon, image, clockwise);\n\t\t\tphoton.fliph(rotated);\n\t\t\treturn rotated;\n\t\t}\n\t\tcase 6:\n\t\t\treturn rotate90(photon, image, clockwise);\n\t\tcase 7: {\n\t\t\tconst rotated = rotate90(photon, image, counterClockwise);\n\t\t\tphoton.fliph(rotated);\n\t\t\treturn rotated;\n\t\t}\n\t\tcase 8:\n\t\t\treturn rotate90(photon, image, counterClockwise);\n\t\tdefault:\n\t\t\treturn image;\n\t}\n};\n","import { Effect } from \"effect\";\nimport { load as unpacked } from \"../../util/unpacked.ts\";\nimport { applyOrientation } from \"./exif.ts\";\n\nexport type Photon = typeof import(\"@silvia-odwyer/photon-node\");\nexport type PhotonImage = import(\"@silvia-odwyer/photon-node\").PhotonImage;\n\n/** Photon, loaded once on first use; `undefined` when its WASM cannot load, so images degrade instead of failing reads. */\nexport const load: Effect.Effect<Photon | undefined> = Effect.cached(\n\tunpacked(\"@silvia-odwyer/photon-node\").pipe(\n\t\tEffect.map((module) => module as Photon),\n\t\tEffect.orElseSucceed(() => undefined),\n\t),\n).pipe(Effect.runSync);\n\n/** Decode with EXIF orientation applied. The caller frees the result. */\nexport const decode = (photon: Photon, bytes: Uint8Array): PhotonImage => {\n\tconst raw = photon.PhotonImage.new_from_byteslice(bytes);\n\tconst oriented = applyOrientation(photon, raw, bytes);\n\tif (oriented !== raw) raw.free();\n\treturn oriented;\n};\n","import { Config, Effect, Option, Schema } from \"effect\";\nimport { pathToFileURL } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { decode, load } from \"./photon.ts\";\n\nexport interface ResizeOptions {\n\treadonly maxWidth: number;\n\treadonly maxHeight: number;\n\t/** Most bytes of base64 payload. */\n\treadonly maxBytes: number;\n\treadonly jpegQuality: number;\n}\n\nexport interface Resized {\n\t/** base64 */\n\treadonly data: string;\n\treadonly mimeType: string;\n\treadonly originalWidth: number;\n\treadonly originalHeight: number;\n\treadonly width: number;\n\treadonly height: number;\n\treadonly wasResized: boolean;\n}\n\n// 4.5MB of base64 leaves headroom below Anthropic's 5MB image limit.\nexport const defaults: ResizeOptions = {\n\tmaxWidth: 2000,\n\tmaxHeight: 2000,\n\tmaxBytes: 4.5 * 1024 * 1024,\n\tjpegQuality: 80,\n};\n\n/** Tags worker replies: Node posts its own messages on the worker channel too (e.g. under `--watch`). */\nexport const REPLY = \"codework:photon-image-resize\";\n\nexport type Reply = { type: typeof REPLY; result: Resized | null } | { type: typeof REPLY; error: string };\n\nconst base64 = (bytes: Uint8Array) => {\n\tconst data = Buffer.from(bytes).toString(\"base64\");\n\treturn { data, size: data.length };\n};\n\n/**\n * Fit an image within the dimensions and encoded size, in this thread. `null`\n * when Photon is unavailable or nothing fits. Fits by: scaling to the max\n * dimensions, keeping the smaller of PNG and JPEG, lowering JPEG quality, then\n * shrinking by a quarter at a time down to 1x1.\n */\nexport const resizeInProcess = (\n\tinput: Uint8Array,\n\tmimeType: string,\n\toptions: ResizeOptions = defaults,\n): Effect.Effect<Resized | null> =>\n\tEffect.map(load, (photon) => {\n\t\tif (photon === undefined) return null;\n\t\tlet image: ReturnType<typeof decode> | undefined;\n\t\ttry {\n\t\t\timage = decode(photon, input);\n\t\t\tconst originalWidth = image.get_width();\n\t\t\tconst originalHeight = image.get_height();\n\t\t\tconst inputSize = Math.ceil(input.byteLength / 3) * 4;\n\t\t\tif (originalWidth <= options.maxWidth && originalHeight <= options.maxHeight && inputSize < options.maxBytes) {\n\t\t\t\treturn {\n\t\t\t\t\tdata: Buffer.from(input).toString(\"base64\"),\n\t\t\t\t\tmimeType,\n\t\t\t\t\toriginalWidth,\n\t\t\t\t\toriginalHeight,\n\t\t\t\t\twidth: originalWidth,\n\t\t\t\t\theight: originalHeight,\n\t\t\t\t\twasResized: false,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// A side never scales below one pixel, or a thin image would vanish.\n\t\t\tlet width = originalWidth;\n\t\t\tlet height = originalHeight;\n\t\t\tif (width > options.maxWidth) {\n\t\t\t\theight = Math.max(1, Math.round((height * options.maxWidth) / width));\n\t\t\t\twidth = options.maxWidth;\n\t\t\t}\n\t\t\tif (height > options.maxHeight) {\n\t\t\t\twidth = Math.max(1, Math.round((width * options.maxHeight) / height));\n\t\t\t\theight = options.maxHeight;\n\t\t\t}\n\n\t\t\tconst qualities = [...new Set([options.jpegQuality, 85, 70, 55, 40])];\n\t\t\twhile (true) {\n\t\t\t\tconst resized = photon.resize(image, width, height, photon.SamplingFilter.Lanczos3);\n\t\t\t\ttry {\n\t\t\t\t\tconst candidates = [\n\t\t\t\t\t\t{ ...base64(resized.get_bytes()), mimeType: \"image/png\" },\n\t\t\t\t\t\t...qualities.map((quality) => ({\n\t\t\t\t\t\t\t...base64(resized.get_bytes_jpeg(quality)),\n\t\t\t\t\t\t\tmimeType: \"image/jpeg\",\n\t\t\t\t\t\t})),\n\t\t\t\t\t];\n\t\t\t\t\tconst fit = candidates.find((candidate) => candidate.size < options.maxBytes);\n\t\t\t\t\tif (fit !== undefined) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tdata: fit.data,\n\t\t\t\t\t\t\tmimeType: fit.mimeType,\n\t\t\t\t\t\t\toriginalWidth,\n\t\t\t\t\t\t\toriginalHeight,\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\twasResized: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tresized.free();\n\t\t\t\t}\n\t\t\t\tconst nextWidth = Math.max(1, Math.floor(width * 0.75));\n\t\t\t\tconst nextHeight = Math.max(1, Math.floor(height * 0.75));\n\t\t\t\tif (nextWidth === width && nextHeight === height) return null;\n\t\t\t\twidth = nextWidth;\n\t\t\t\theight = nextHeight;\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t} finally {\n\t\t\timage?.free();\n\t\t}\n\t});\n\n// From source the worker sits beside this module; packed, this module lands in a\n// chunk at the package's output root while the worker keeps its own entry path. The\n// standalone binary unpacks a bundled worker and names it.\nconst workerUrl = Effect.gen(function* () {\n\tconst unpacked = yield* Config.option(Config.String(\"CODEWORK_IMAGE_WORKER\"));\n\tif (Option.isSome(unpacked)) return pathToFileURL(unpacked.value);\n\treturn import.meta.url.endsWith(\".ts\")\n\t\t? new URL(\"./worker.ts\", import.meta.url)\n\t\t: new URL(\"./tool/image/worker.mjs\", import.meta.url);\n}).pipe(Effect.orDie);\n\n/** The worker could not resize; the caller falls back to this thread. */\nclass WorkerError extends Schema.TaggedError<WorkerError>()(\"ImageResizeWorkerError\", { message: Schema.String }) {}\n\nconst inWorker = (input: Uint8Array, mimeType: string, options: ResizeOptions) =>\n\tEffect.flatMap(workerUrl, (url) =>\n\t\tEffect.callback<Resized | null, WorkerError>((resume) => {\n\t\t\tlet worker: Worker;\n\t\t\ttry {\n\t\t\t\tworker = new Worker(url);\n\t\t\t} catch (cause) {\n\t\t\t\t// e.g. a Node permission model without worker access: resize in this thread instead.\n\t\t\t\tresume(Effect.fail(new WorkerError({ message: String(cause) })));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst done = (effect: Effect.Effect<Resized | null, WorkerError>) => {\n\t\t\t\tresume(effect);\n\t\t\t\tvoid worker.terminate().catch(() => undefined);\n\t\t\t};\n\t\t\tworker.on(\"message\", (message: unknown) => {\n\t\t\t\tconst reply = message as Partial<Reply> | null;\n\t\t\t\tif (reply?.type !== REPLY) return;\n\t\t\t\tdone(\n\t\t\t\t\t\"error\" in reply\n\t\t\t\t\t\t? Effect.fail(new WorkerError({ message: reply.error }))\n\t\t\t\t\t\t: Effect.succeed((reply as { result: Resized | null }).result),\n\t\t\t\t);\n\t\t\t});\n\t\t\tworker.once(\"error\", (error: Error) => done(Effect.fail(new WorkerError({ message: error.message }))));\n\t\t\tworker.once(\"exit\", (code) =>\n\t\t\t\tdone(Effect.fail(new WorkerError({ message: `Image resize worker exited with code ${code}` }))),\n\t\t\t);\n\t\t\t// Transferring detaches the buffer, so hand over a copy and leave the caller's bytes intact.\n\t\t\tconst bytes = new Uint8Array(input);\n\t\t\tworker.postMessage({ input: bytes, mimeType, options }, [bytes.buffer]);\n\t\t\treturn Effect.promise(() => worker.terminate());\n\t\t}),\n\t);\n\n/**\n * {@link resizeInProcess} on a worker thread, so decoding and encoding a large\n * image never blocks the harness's event loop. Falls back to this thread when a\n * worker cannot start, so a read still works.\n */\nexport const resize = (input: Uint8Array, mimeType: string, options: ResizeOptions = defaults) =>\n\tinWorker(input, mimeType, options).pipe(Effect.catch(() => resizeInProcess(input, mimeType, options)));\n\n/** Tells the model how to map coordinates on a resized image back to the original. */\nexport const dimensionNote = (result: Resized): string | undefined => {\n\tif (!result.wasResized) return undefined;\n\tconst scale = result.originalWidth / result.width;\n\treturn `[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.]`;\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as RuntimeConfig, c as sandbox, i as ResourcesConfig, n as CreateConfig, o as config, r as Options, s as make, t as ClientOptions } from "../../daytona-
|
|
1
|
+
import { a as RuntimeConfig, c as sandbox, i as ResourcesConfig, n as CreateConfig, o as config, r as Options, s as make, t as ClientOptions } from "../../daytona-D4sNwzSr.mjs";
|
|
2
2
|
export { ClientOptions, CreateConfig, Options, ResourcesConfig, RuntimeConfig, config, sandbox as default, make };
|
package/tool/image/worker.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as resizeInProcess, t as REPLY } from "../../resize-
|
|
1
|
+
import { i as resizeInProcess, t as REPLY } from "../../resize-D34zcVQl.mjs";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { parentPort } from "node:worker_threads";
|
|
4
4
|
//#region src/tool/image/worker.ts
|