@nyte-ai/host 0.0.18 → 0.0.19

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.
Files changed (102) hide show
  1. package/THIRD-PARTY-NOTICES.md +66 -0
  2. package/dist/chunks/{canvas-preview-5hxat7hh.js → canvas-preview-11nadadc.js} +8 -6
  3. package/dist/chunks/{canvas-preview-rp6fz0w5.js → canvas-preview-2jwbe14k.js} +5 -5
  4. package/dist/chunks/{canvas-preview-m02v4yy6.js → canvas-preview-55s0y68g.js} +3 -2
  5. package/dist/chunks/{canvas-preview-xn10d4f8.js → canvas-preview-5ekjx6sw.js} +9 -4
  6. package/dist/chunks/{canvas-preview-75db60xy.js → canvas-preview-8xc0vn7v.js} +5 -4
  7. package/dist/chunks/{canvas-preview-zn2d0k9d.js → canvas-preview-af86jz8t.js} +14 -6
  8. package/dist/chunks/{canvas-preview-d9wwhbtz.js → canvas-preview-aq5j4p25.js} +1 -1
  9. package/dist/chunks/{canvas-preview-j1tnf51w.js → canvas-preview-b2v8wfnz.js} +1 -1
  10. package/dist/chunks/canvas-preview-befkjea2.js +60 -0
  11. package/dist/chunks/canvas-preview-bxnqt8cd.js +103 -0
  12. package/dist/chunks/{canvas-preview-vax9ne4e.js → canvas-preview-cawy6vbz.js} +22 -11
  13. package/dist/chunks/{canvas-preview-senpjwep.js → canvas-preview-crmzxxt8.js} +3 -3
  14. package/dist/chunks/{canvas-preview-ymgz0937.js → canvas-preview-drctegz4.js} +8 -4
  15. package/dist/chunks/{canvas-preview-yrfz2ak6.js → canvas-preview-e3vnkkc5.js} +6 -6
  16. package/dist/chunks/canvas-preview-ec2mt7es.js +108 -0
  17. package/dist/chunks/{canvas-preview-1ta3avah.js → canvas-preview-fxa0rfb0.js} +10 -5
  18. package/dist/chunks/{canvas-preview-8xgt67ka.js → canvas-preview-g5fkjs34.js} +1 -1
  19. package/dist/chunks/{canvas-preview-g3qj3y3k.js → canvas-preview-jeddjex8.js} +13 -3
  20. package/dist/chunks/{canvas-preview-0nrnbt76.js → canvas-preview-k1yg4fgp.js} +199 -125
  21. package/dist/chunks/canvas-preview-kp75gb63.js +141 -0
  22. package/dist/chunks/{canvas-preview-ewgspmsd.js → canvas-preview-n2a35zv5.js} +1 -1
  23. package/dist/chunks/{canvas-preview-h8hshnff.js → canvas-preview-pkzqg96v.js} +1 -1
  24. package/dist/chunks/{canvas-preview-evh92ywd.js → canvas-preview-tnqe7k0b.js} +15 -10
  25. package/dist/chunks/{canvas-preview-ehf3vp31.js → canvas-preview-vm9zdp2t.js} +45 -58
  26. package/dist/chunks/{canvas-preview-76fwvd6e.js → canvas-preview-w54ymtb3.js} +1 -1
  27. package/dist/chunks/canvas-preview-y5y6ghaw.js +125 -0
  28. package/dist/chunks/{canvas-preview-98aj5p34.js → canvas-preview-ycepb05s.js} +1 -1
  29. package/dist/src/canvas-preview.js +7 -3
  30. package/dist/src/deploy/cloudflare/worker.js +1 -1
  31. package/dist/src/deploy/vercel/server/routes/[...].js +2 -2
  32. package/dist/src/deploy/vercel/server/utils/host.js +1 -1
  33. package/dist/src/deploy/vercel/server/workflows/drive.js +3 -3
  34. package/dist/src/images/exif.d.ts +1 -0
  35. package/dist/src/images/exif.js +6 -0
  36. package/dist/src/images/node.d.ts +37 -0
  37. package/dist/src/images/node.js +12 -0
  38. package/dist/src/images/photon.d.ts +3 -0
  39. package/dist/src/images/photon.js +7 -0
  40. package/dist/src/images/worker.d.ts +1 -0
  41. package/dist/src/images/worker.js +23 -0
  42. package/dist/src/index.d.ts +0 -1
  43. package/dist/src/index.js +23 -22
  44. package/dist/src/listen-fetch.js +3 -3
  45. package/dist/src/listen.js +4 -4
  46. package/dist/src/local/command.d.ts +5 -0
  47. package/dist/src/local/command.js +6 -2
  48. package/dist/src/local/files.js +2 -2
  49. package/dist/src/local/git-watch.d.ts +1 -1
  50. package/dist/src/local/git-watch.js +1 -1
  51. package/dist/src/local/git.js +3 -3
  52. package/dist/src/local/github.js +2 -2
  53. package/dist/src/local/jobs.d.ts +1 -1
  54. package/dist/src/local/jobs.js +2 -1
  55. package/dist/src/local/provider.js +9 -9
  56. package/dist/src/local/snapshots.js +2 -2
  57. package/dist/src/local/worktrees.js +2 -2
  58. package/dist/src/mcp/connect.d.ts +0 -13
  59. package/dist/src/mcp/connect.js +1 -1
  60. package/dist/src/mcp/hub.js +2 -2
  61. package/dist/src/open.d.ts +2 -30
  62. package/dist/src/open.js +20 -18
  63. package/dist/src/serve/binding.js +1 -1
  64. package/dist/src/serve/handler.js +2 -2
  65. package/dist/src/sqlite.d.ts +2 -1
  66. package/dist/src/sqlite.js +4 -3
  67. package/dist/src/store-usage.js +4 -1
  68. package/dist/src/usage-history.d.ts +54 -0
  69. package/dist/src/usage-history.js +14 -0
  70. package/dist/src/usage-service.d.ts +2 -1
  71. package/dist/src/usage-service.js +7 -3
  72. package/dist/src/usage-worker.js +8 -4
  73. package/dist/src/usage.d.ts +150 -27
  74. package/dist/src/usage.js +12 -2
  75. package/package.json +16 -8
  76. package/src/canvas-preview.ts +4 -3
  77. package/src/images/exif.ts +69 -0
  78. package/src/images/node.ts +163 -0
  79. package/src/images/photon.ts +141 -0
  80. package/src/images/worker.ts +29 -0
  81. package/src/index.ts +19 -1
  82. package/src/local/command.ts +64 -12
  83. package/src/local/files.ts +8 -3
  84. package/src/local/git-watch.ts +16 -6
  85. package/src/local/git.ts +7 -2
  86. package/src/local/github.ts +3 -4
  87. package/src/local/jobs.ts +55 -69
  88. package/src/local/snapshots.ts +4 -2
  89. package/src/local/worktrees.ts +4 -4
  90. package/src/mcp/connect.ts +1 -14
  91. package/src/open.ts +16 -36
  92. package/src/serve/binding.ts +4 -3
  93. package/src/sqlite.ts +33 -8
  94. package/src/store-usage.ts +5 -2
  95. package/src/usage-history.ts +219 -0
  96. package/src/usage-service.ts +12 -3
  97. package/src/usage.ts +251 -176
  98. package/dist/chunks/canvas-preview-a3yw0j70.js +0 -72
  99. package/dist/chunks/canvas-preview-azg56359.js +0 -68
  100. package/dist/src/store-owner.d.ts +0 -15
  101. package/dist/src/store-owner.js +0 -9
  102. package/src/store-owner.ts +0 -98
@@ -18,13 +18,11 @@ import {
18
18
  sessionIndexChanges2,
19
19
  sqlSessionIndex2
20
20
  } from "./canvas-preview-0cmbkp2j.js";
21
- import {
22
- claimStore2
23
- } from "./canvas-preview-a3yw0j70.js";
24
21
 
25
22
  // src/sqlite.ts
26
23
  import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
27
24
  import { dirname, join } from "node:path";
25
+ import process from "node:process";
28
26
  import { DatabaseSync } from "node:sqlite";
29
27
  import { asSeq } from "@nyte-ai/schema";
30
28
  import { dev } from "@nyte-ai/core";
@@ -43,14 +41,15 @@ import {
43
41
  var BUSY_TIMEOUT_MS = 5000;
44
42
  var BACKUPS_KEPT = 3;
45
43
  var PUT_BODY = "INSERT INTO objects (id, body) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET body = excluded.body WHERE objects.body IS NULL";
44
+ function storePath2(home) {
45
+ return process.env["NYTE_DB"] ?? join(home, ".nyte", "nyte.db");
46
+ }
46
47
  function sqliteStore2(input) {
47
48
  let database = null;
48
49
  let opening = null;
49
50
  let closing = null;
50
51
  let workers = null;
51
- let release = null;
52
52
  const open = async () => {
53
- const claim = "path" in input ? claimStore2(input.path) : null;
54
53
  let created;
55
54
  try {
56
55
  created = new DatabaseSync("path" in input ? input.path : ":memory:", {
@@ -65,11 +64,9 @@ function sqliteStore2(input) {
65
64
  created.exec("PRAGMA optimize = 0x10012");
66
65
  } catch (error) {
67
66
  created?.close();
68
- claim?.();
69
67
  throw error;
70
68
  }
71
69
  database = created;
72
- release = claim;
73
70
  workers = "path" in input ? sqliteWorkers2(created, input.path) : null;
74
71
  return connect(created, workers);
75
72
  };
@@ -91,10 +88,8 @@ function sqliteStore2(input) {
91
88
  });
92
89
  await workers?.close();
93
90
  database?.close();
94
- release?.();
95
91
  workers = null;
96
92
  database = null;
97
- release = null;
98
93
  opening = null;
99
94
  })().finally(() => {
100
95
  closing = null;
@@ -219,6 +214,7 @@ function connect(database, workers) {
219
214
  const listRange = database.prepare("SELECT name, target, revision FROM refs WHERE name >= ? AND name < ? ORDER BY name");
220
215
  const putRef = database.prepare("INSERT INTO refs (name, target, revision) VALUES (?, ?, ?) ON CONFLICT (name) DO UPDATE SET target = excluded.target, revision = excluded.revision");
221
216
  const deleteRef = database.prepare("DELETE FROM refs WHERE name = ?");
217
+ const audit = auditing(database);
222
218
  const append = database.prepare("INSERT INTO log (session, seq, at, event) VALUES (?, ?, ?, ?)");
223
219
  const readLog = database.prepare("SELECT seq, at, event FROM log WHERE session = ? AND seq > ? ORDER BY seq LIMIT ?");
224
220
  const readTail = database.prepare("SELECT MAX(seq) AS tail FROM log WHERE session = ?");
@@ -295,12 +291,15 @@ function connect(database, workers) {
295
291
  };
296
292
  }
297
293
  const touched = new Map;
294
+ const current = new Map([...before].map(([name, row]) => [name, row?.revision ?? null]));
298
295
  const revisions = updates.map((update) => {
299
296
  const revision = mintRevision2();
300
297
  if (update.target === null)
301
298
  deleteRef.run(update.name);
302
299
  else
303
300
  putRef.run(update.name, update.target, revision);
301
+ audit?.run(Date.now(), process.pid, fenceNames([update]).find((name) => name.startsWith("processes/")) ?? null, update.name, current.get(update.name) ?? null, update.target === null ? null : revision, update.target);
302
+ current.set(update.name, update.target === null ? null : revision);
304
303
  updateSessionIndex(database, update.name, update.target, revision);
305
304
  const session = parseSessionRef(update.name);
306
305
  if (session !== null)
@@ -354,6 +353,12 @@ function connect(database, workers) {
354
353
  }
355
354
  };
356
355
  }
356
+ function auditing(database) {
357
+ if (process.env.NYTE_STORE_AUDIT !== "1")
358
+ return null;
359
+ database.exec("CREATE TABLE IF NOT EXISTS store_audit (id INTEGER PRIMARY KEY, at INTEGER NOT NULL, pid INTEGER NOT NULL, writer TEXT, name TEXT NOT NULL, before TEXT, after TEXT, target TEXT)");
360
+ return database.prepare("INSERT INTO store_audit (at, pid, writer, name, before, after, target) VALUES (?, ?, ?, ?, ?, ?, ?)");
361
+ }
357
362
  function updateSessionIndex(database, name, target, revision) {
358
363
  if (sessionIndexRef(name) === null)
359
364
  return;
@@ -366,4 +371,4 @@ function write(database, statement, ...params) {
366
371
  return (size > 64 * 1024 ? database.prepare(statement.sourceSQL) : statement).run(...params);
367
372
  }
368
373
 
369
- export { sqliteStore2 };
374
+ export { storePath2, sqliteStore2 };
@@ -1,7 +1,14 @@
1
+ import {
2
+ run2,
3
+ spawnCommand2,
4
+ killTree2,
5
+ findExecutable2
6
+ } from "./canvas-preview-bxnqt8cd.js";
7
+
1
8
  // src/local/jobs.ts
2
9
  import { spawn } from "node:child_process";
3
10
  import { createRequire } from "node:module";
4
- import { resolve } from "node:path";
11
+ import { basename, resolve } from "node:path";
5
12
  import { asId, SdkError } from "@nyte-ai/schema";
6
13
  import {
7
14
  processEnvironment,
@@ -16,11 +23,7 @@ var PAUSE_BYTES = 256 * 1024;
16
23
  var RESUME_BYTES = 64 * 1024;
17
24
  var STOP_GRACE_MS = 2000;
18
25
  var CLOSE_GRACE_MS = 2000;
19
- var QUIET_MS = 300;
20
26
  var DONE = { done: true, value: undefined };
21
- var ESC = "\x1B";
22
- var BEL = "\x07";
23
- var PROMPT_MARKER = new RegExp(`${ESC}\\]133;([ABCD])`, "g");
24
27
  var loaded;
25
28
  function localExec2(root, options) {
26
29
  const readers = new Set;
@@ -106,7 +109,7 @@ function localExec2(root, options) {
106
109
  return { kind: "not-pty" };
107
110
  return finished === null && driver.resize(size) ? { kind: "resized" } : { kind: "missing" };
108
111
  },
109
- idle: async () => finished === null && driver.idle(),
112
+ idle: async () => driver.pty && (finished !== null || driver.idle()),
110
113
  stop: async () => ({ kind: "settled", outcome: await stop() }),
111
114
  settled: (request) => waitEnd(ended, request),
112
115
  close,
@@ -116,16 +119,16 @@ function localExec2(root, options) {
116
119
  };
117
120
  }
118
121
  async function pipe(command, options, log, finish) {
119
- const group = process.platform !== "win32";
122
+ const windows = process.platform === "win32";
120
123
  const [file, ...args] = typeof command === "string" ? [command] : command;
121
124
  const settings = {
122
125
  cwd: options.cwd,
123
126
  env: options.env,
124
- detached: group,
127
+ detached: !windows,
125
128
  stdio: "pipe",
126
129
  windowsHide: true
127
130
  };
128
- const child = typeof command === "string" ? spawn(command, { ...settings, shell: true }) : spawn(file ?? "", args, settings);
131
+ const child = typeof command === "string" ? spawn(command, { ...settings, shell: true }) : spawnCommand2(windows ? await findExecutable2(file ?? "") ?? file ?? "" : file ?? "", args, settings);
129
132
  await new Promise((started, failed) => {
130
133
  child.once("spawn", started);
131
134
  child.once("error", (error) => failed(new SdkError("unavailable", `Cannot start ${file ?? ""}: ${error.message}`)));
@@ -146,12 +149,13 @@ async function pipe(command, options, log, finish) {
146
149
  child.stdin?.on("error", () => {
147
150
  return;
148
151
  });
149
- child.on("close", (code) => finish(code));
152
+ let killed = false;
153
+ child.on("close", (code) => finish(killed ? null : code));
150
154
  child.on("exit", (code) => {
151
155
  setTimeout(() => {
152
156
  child.stdout?.destroy();
153
157
  child.stderr?.destroy();
154
- finish(code);
158
+ finish(killed ? null : code);
155
159
  }, CLOSE_GRACE_MS).unref();
156
160
  });
157
161
  return {
@@ -165,8 +169,13 @@ async function pipe(command, options, log, finish) {
165
169
  resize: () => false,
166
170
  idle: () => false,
167
171
  kill(signal) {
172
+ if (windows) {
173
+ killed = true;
174
+ killTree2(child, signal);
175
+ return;
176
+ }
168
177
  try {
169
- if (group && child.pid !== undefined)
178
+ if (child.pid !== undefined)
170
179
  process.kill(-child.pid, signal);
171
180
  else
172
181
  child.kill(signal);
@@ -200,21 +209,7 @@ async function terminal(command, options, log, finish) {
200
209
  throw new SdkError("unavailable", `Cannot start ${file ?? shell} in a pty: ${error instanceof Error ? error.message : String(error)}`);
201
210
  }
202
211
  const encoder = new TextEncoder;
203
- let marker = null;
204
- let line = "";
205
- let quietSince = 0;
206
- term.onData((text) => {
207
- log.push(encoder.encode(text));
208
- quietSince = Date.now();
209
- marker = lastMarker(text) ?? marker;
210
- const plain = withoutEscapes(text);
211
- const broken = plain.lastIndexOf(`
212
- `);
213
- line = (broken < 0 ? line + plain : plain.slice(broken + 1)).slice(-1024);
214
- const returned = line.replace(/\r+$/, "").lastIndexOf("\r");
215
- if (returned >= 0)
216
- line = line.slice(returned + 1);
217
- });
212
+ term.onData((text) => log.push(encoder.encode(text)));
218
213
  term.onExit(({ exitCode, signal }) => finish(signal ? null : exitCode));
219
214
  log.throttle({ pause: () => term.pause(), resume: () => term.resume() });
220
215
  return {
@@ -226,10 +221,29 @@ async function terminal(command, options, log, finish) {
226
221
  term.resize(size.columns, size.rows);
227
222
  return true;
228
223
  },
229
- idle() {
230
- if (marker !== null)
231
- return marker !== "C";
232
- return quietSince > 0 && Date.now() - quietSince >= QUIET_MS && line.trim() !== "";
224
+ async idle() {
225
+ if (typeof command === "string" || command.length !== 0)
226
+ return false;
227
+ const result = await run2(windows ? "powershell.exe" : "ps", windows ? [
228
+ "-NoProfile",
229
+ "-NonInteractive",
230
+ "-Command",
231
+ `Get-CimInstance Win32_Process -Filter "ParentProcessId = ${term.pid} AND Name != 'conhost.exe' AND Name != 'OpenConsole.exe'" | Select-Object -ExpandProperty ProcessId`
232
+ ] : ["-A", "-o", "pid=,ppid=,stat=,comm="], { cwd: options.cwd, timeoutMs: 1500 });
233
+ if (result.code !== 0)
234
+ throw new SdkError("unavailable", "Cannot inspect terminal processes");
235
+ const processes = result.stdout.toString("utf8").trim();
236
+ if (windows)
237
+ return processes === "";
238
+ return !processes.split(`
239
+ `).some((line) => {
240
+ const [pid, parent, state, ...name] = line.trim().split(/\s+/);
241
+ if (state?.startsWith("Z"))
242
+ return false;
243
+ if (Number(parent) === term.pid)
244
+ return true;
245
+ return Number(pid) === term.pid && basename(name.join(" ")).replace(/^-/, "") !== basename(shell);
246
+ });
233
247
  },
234
248
  kill(signal) {
235
249
  try {
@@ -238,33 +252,6 @@ async function terminal(command, options, log, finish) {
238
252
  }
239
253
  };
240
254
  }
241
- function lastMarker(text) {
242
- return Array.from(text.matchAll(PROMPT_MARKER), (match) => match[1]).at(-1) ?? null;
243
- }
244
- function withoutEscapes(text) {
245
- let plain = "";
246
- let at = 0;
247
- while (at < text.length) {
248
- const char = text[at] ?? "";
249
- if (char !== ESC) {
250
- plain += char;
251
- at += 1;
252
- continue;
253
- }
254
- const kind = text[at + 1] ?? "";
255
- at += 2;
256
- if (kind === "[") {
257
- while (at < text.length && !/[@-~]/.test(text[at] ?? ""))
258
- at += 1;
259
- at += 1;
260
- } else if (kind === "]") {
261
- while (at < text.length && text[at] !== BEL && !(text[at] === ESC && text[at + 1] === "\\"))
262
- at += 1;
263
- at += text[at] === BEL ? 1 : 2;
264
- }
265
- }
266
- return plain;
267
- }
268
255
  function loadPty() {
269
256
  if (loaded === undefined)
270
257
  loaded = ptyFrom(() => createRequire(import.meta.url)("@lydell/node-pty"));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createHandler2
3
- } from "./canvas-preview-d9wwhbtz.js";
3
+ } from "./canvas-preview-aq5j4p25.js";
4
4
 
5
5
  // src/listen-fetch.ts
6
6
  import { SdkError } from "@nyte-ai/schema";
@@ -0,0 +1,125 @@
1
+ import {
2
+ photonImages2
3
+ } from "./canvas-preview-ec2mt7es.js";
4
+
5
+ // src/images/node.ts
6
+ import { readFile } from "node:fs/promises";
7
+ import { fileURLToPath } from "node:url";
8
+ import { Worker } from "node:worker_threads";
9
+ import { Type } from "typebox";
10
+ import { Value } from "typebox/value";
11
+ var size = Type.Object({ width: Type.Number(), height: Type.Number() });
12
+ var prepareReply2 = Type.Union([
13
+ Type.Object({ id: Type.Integer(), result: Type.Null() }),
14
+ Type.Object({
15
+ id: Type.Integer(),
16
+ result: Type.Object({
17
+ data: Type.String(),
18
+ mimeType: Type.String(),
19
+ resized: Type.Optional(Type.Object({ from: size, to: size }))
20
+ })
21
+ }),
22
+ Type.Object({ id: Type.Integer(), error: Type.String() })
23
+ ]);
24
+ var IDLE_MS = 30000;
25
+ function nodeImages2(options = {}) {
26
+ const worker = options.worker ?? new URL(import.meta.url.endsWith(".ts") ? "./worker.ts" : "./worker.js", import.meta.url);
27
+ let wasm;
28
+ const loadWasm = () => wasm ??= readFile(options.wasm ?? resolvePhotonWasmPath2());
29
+ let thread;
30
+ let inProcess;
31
+ return {
32
+ async prepare(bytes, mimeType, limits) {
33
+ if (inProcess !== undefined)
34
+ return inProcess.prepare(bytes, mimeType, limits);
35
+ const module = await loadWasm();
36
+ try {
37
+ thread ??= new PhotonThread(worker, module, (ended) => {
38
+ if (thread === ended)
39
+ thread = undefined;
40
+ });
41
+ return await thread.prepare(bytes, mimeType, limits);
42
+ } catch (cause) {
43
+ if (!(cause instanceof WorkerUnavailable))
44
+ throw cause;
45
+ inProcess ??= photonImages2(module);
46
+ return inProcess.prepare(bytes, mimeType, limits);
47
+ }
48
+ }
49
+ };
50
+ }
51
+ function resolvePhotonWasmPath2() {
52
+ return fileURLToPath(import.meta.resolve("@silvia-odwyer/photon/photon_rs_bg.wasm"));
53
+ }
54
+
55
+ class WorkerUnavailable extends Error {
56
+ }
57
+
58
+ class PhotonThread {
59
+ #worker;
60
+ #pending = new Map;
61
+ #onExit;
62
+ #nextId = 0;
63
+ #idle;
64
+ #started = false;
65
+ constructor(entry, wasm, onExit) {
66
+ this.#onExit = onExit;
67
+ try {
68
+ this.#worker = new Worker(entry, { workerData: wasm });
69
+ } catch (cause) {
70
+ throw new WorkerUnavailable("The image worker cannot start", { cause });
71
+ }
72
+ this.#worker.on("message", (reply) => {
73
+ if (!Value.Check(prepareReply2, reply)) {
74
+ this.#fail(new Error("Malformed image worker reply"));
75
+ this.#worker.terminate();
76
+ return;
77
+ }
78
+ this.#started = true;
79
+ const request = this.#pending.get(reply.id);
80
+ if (request === undefined)
81
+ return;
82
+ this.#pending.delete(reply.id);
83
+ if ("error" in reply)
84
+ request.reject(new Error(reply.error));
85
+ else
86
+ request.resolve(reply.result ?? undefined);
87
+ this.#settled();
88
+ });
89
+ this.#worker.on("error", (cause) => this.#fail(cause));
90
+ this.#worker.on("exit", (code) => this.#fail(new Error(`The image worker exited with code ${String(code)}`)));
91
+ }
92
+ prepare(bytes, mimeType, limits) {
93
+ const id = this.#nextId++;
94
+ const request = Promise.withResolvers();
95
+ this.#pending.set(id, request);
96
+ clearTimeout(this.#idle);
97
+ this.#idle = undefined;
98
+ this.#worker.ref();
99
+ const copy = bytes.slice();
100
+ this.#worker.postMessage({ id, bytes: copy, mimeType, limits }, [
101
+ copy.buffer
102
+ ]);
103
+ return request.promise;
104
+ }
105
+ #settled() {
106
+ if (this.#pending.size > 0)
107
+ return;
108
+ this.#worker.unref();
109
+ this.#idle = setTimeout(() => {
110
+ this.#onExit(this);
111
+ this.#worker.terminate();
112
+ }, IDLE_MS);
113
+ this.#idle.unref();
114
+ }
115
+ #fail(cause) {
116
+ const failure = this.#started ? cause : new WorkerUnavailable("The image worker cannot start", { cause });
117
+ for (const request of this.#pending.values())
118
+ request.reject(failure);
119
+ this.#pending.clear();
120
+ clearTimeout(this.#idle);
121
+ this.#onExit(this);
122
+ }
123
+ }
124
+
125
+ export { prepareReply2, nodeImages2, resolvePhotonWasmPath2 };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  listenFetch2
3
- } from "./canvas-preview-76fwvd6e.js";
3
+ } from "./canvas-preview-w54ymtb3.js";
4
4
 
5
5
  // src/listen.ts
6
6
  import { createServer } from "node:http";
@@ -1,3 +1,7 @@
1
+ import {
2
+ killTree2
3
+ } from "../chunks/canvas-preview-bxnqt8cd.js";
4
+
1
5
  // src/canvas-preview.ts
2
6
  import { spawn } from "node:child_process";
3
7
  import { existsSync, readdirSync } from "node:fs";
@@ -192,12 +196,12 @@ function stop(child) {
192
196
  if (child.exitCode !== null || child.signalCode !== null)
193
197
  return Promise.resolve();
194
198
  return new Promise((resolve) => {
195
- const kill = setTimeout(() => child.kill("SIGKILL"), 2000);
199
+ const kill = setTimeout(() => killTree2(child, "SIGKILL"), 2000);
196
200
  child.once("exit", () => {
197
201
  clearTimeout(kill);
198
202
  resolve();
199
203
  });
200
- child.kill();
204
+ killTree2(child, "SIGTERM");
201
205
  });
202
206
  }
203
207
  function chromiumCanvasPreview(shell, executable = findChromium) {
@@ -257,7 +261,7 @@ function chromiumCanvasPreview(shell, executable = findChromium) {
257
261
  }
258
262
  } finally {
259
263
  await stop(child);
260
- await rm(profile, { recursive: true, force: true });
264
+ await rm(profile, { recursive: true, force: true, maxRetries: 10 });
261
265
  }
262
266
  };
263
267
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  package_default
3
- } from "../../../chunks/canvas-preview-g3qj3y3k.js";
3
+ } from "../../../chunks/canvas-preview-jeddjex8.js";
4
4
 
5
5
  // src/deploy/cloudflare/worker.ts
6
6
  import { asId, SdkError } from "@nyte-ai/schema";
@@ -1,11 +1,11 @@
1
1
  import"../../../../../chunks/canvas-preview-2zdyh9ny.js";
2
2
  import {
3
3
  vercelHost2
4
- } from "../../../../../chunks/canvas-preview-ewgspmsd.js";
4
+ } from "../../../../../chunks/canvas-preview-n2a35zv5.js";
5
5
  import"../../../../../chunks/canvas-preview-65xqjw7f.js";
6
6
  import {
7
7
  dispatchHead2
8
- } from "../../../../../chunks/canvas-preview-j1tnf51w.js";
8
+ } from "../../../../../chunks/canvas-preview-b2v8wfnz.js";
9
9
 
10
10
  // src/deploy/vercel/server/routes/[...].ts
11
11
  import { defineHandler } from "nitro/h3";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  vercelHost2
3
- } from "../../../../../chunks/canvas-preview-ewgspmsd.js";
3
+ } from "../../../../../chunks/canvas-preview-n2a35zv5.js";
4
4
  import"../../../../../chunks/canvas-preview-2zdyh9ny.js";
5
5
  export {
6
6
  vercelHost2 as vercelHost
@@ -2,10 +2,10 @@ import {
2
2
  dispatchHead2,
3
3
  driveHead2,
4
4
  advanceHead2
5
- } from "../../../../../chunks/canvas-preview-j1tnf51w.js";
6
- import"../../../../../chunks/canvas-preview-65xqjw7f.js";
7
- import"../../../../../chunks/canvas-preview-ewgspmsd.js";
5
+ } from "../../../../../chunks/canvas-preview-b2v8wfnz.js";
6
+ import"../../../../../chunks/canvas-preview-n2a35zv5.js";
8
7
  import"../../../../../chunks/canvas-preview-2zdyh9ny.js";
8
+ import"../../../../../chunks/canvas-preview-65xqjw7f.js";
9
9
  export {
10
10
  advanceHead2 as advanceHead,
11
11
  dispatchHead2 as dispatchHead,
@@ -0,0 +1 @@
1
+ export declare function exifOrientation(bytes: Uint8Array): number;
@@ -0,0 +1,6 @@
1
+ import {
2
+ exifOrientation2
3
+ } from "../../chunks/canvas-preview-befkjea2.js";
4
+ export {
5
+ exifOrientation2 as exifOrientation
6
+ };
@@ -0,0 +1,37 @@
1
+ import type { ImageLimits, ImageProcessor } from "@nyte-ai/core";
2
+ import { Type } from "typebox";
3
+ export interface NodeImagesOptions {
4
+ readonly worker?: string | URL;
5
+ readonly wasm?: string;
6
+ }
7
+ export interface PrepareRequest {
8
+ readonly id: number;
9
+ readonly bytes: Uint8Array;
10
+ readonly mimeType: string;
11
+ readonly limits: ImageLimits;
12
+ }
13
+ export declare const prepareReply: Type.TUnion<[Type.TObject<{
14
+ id: Type.TInteger;
15
+ result: Type.TNull;
16
+ }>, Type.TObject<{
17
+ id: Type.TInteger;
18
+ result: Type.TObject<{
19
+ data: Type.TString;
20
+ mimeType: Type.TString;
21
+ resized: Type.TOptional<Type.TObject<{
22
+ from: Type.TObject<{
23
+ width: Type.TNumber;
24
+ height: Type.TNumber;
25
+ }>;
26
+ to: Type.TObject<{
27
+ width: Type.TNumber;
28
+ height: Type.TNumber;
29
+ }>;
30
+ }>>;
31
+ }>;
32
+ }>, Type.TObject<{
33
+ id: Type.TInteger;
34
+ error: Type.TString;
35
+ }>]>;
36
+ export declare function nodeImages(options?: NodeImagesOptions): ImageProcessor;
37
+ export declare function resolvePhotonWasmPath(): string;
@@ -0,0 +1,12 @@
1
+ import {
2
+ prepareReply2,
3
+ nodeImages2,
4
+ resolvePhotonWasmPath2
5
+ } from "../../chunks/canvas-preview-y5y6ghaw.js";
6
+ import"../../chunks/canvas-preview-ec2mt7es.js";
7
+ import"../../chunks/canvas-preview-befkjea2.js";
8
+ export {
9
+ nodeImages2 as nodeImages,
10
+ prepareReply2 as prepareReply,
11
+ resolvePhotonWasmPath2 as resolvePhotonWasmPath
12
+ };
@@ -0,0 +1,3 @@
1
+ import type { SyncInitInput } from "@silvia-odwyer/photon/photon_rs.js";
2
+ import type { ImageProcessor } from "@nyte-ai/core";
3
+ export declare function photonImages(wasm: SyncInitInput): ImageProcessor;
@@ -0,0 +1,7 @@
1
+ import {
2
+ photonImages2
3
+ } from "../../chunks/canvas-preview-ec2mt7es.js";
4
+ import"../../chunks/canvas-preview-befkjea2.js";
5
+ export {
6
+ photonImages2 as photonImages
7
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import"../../chunks/canvas-preview-befkjea2.js";
2
+ import {
3
+ photonImages2
4
+ } from "../../chunks/canvas-preview-ec2mt7es.js";
5
+
6
+ // src/images/worker.ts
7
+ import { parentPort, workerData } from "node:worker_threads";
8
+ var port = parentPort;
9
+ if (port === null)
10
+ throw new Error("The image worker needs a parent thread");
11
+ var wasm = workerData;
12
+ if (!(wasm instanceof Uint8Array))
13
+ throw new Error("The image worker needs Photon's WebAssembly");
14
+ var images = photonImages2(wasm);
15
+ port.on("message", (request) => {
16
+ images.prepare(request.bytes, request.mimeType, request.limits).then((result) => port.postMessage({
17
+ id: request.id,
18
+ result: result ?? null
19
+ }), (cause) => port.postMessage({
20
+ id: request.id,
21
+ error: cause instanceof Error ? cause.message : String(cause)
22
+ }));
23
+ });
@@ -18,4 +18,3 @@ export * from "./plugins/loader.ts";
18
18
  export * from "./postgres.ts";
19
19
  export * from "./secrets.ts";
20
20
  export * from "./sqlite.ts";
21
- export { StoreOwned } from "./store-owner.ts";