@agent-native/core 0.211.0 → 0.211.1-nightly-20261020213022

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 (52) hide show
  1. package/dist/cli/template-baseline.js +18 -5
  2. package/dist/cli/template-sync.js +100 -19
  3. package/dist/collab/__fixtures__/live-copy-tasks.d.ts +1 -0
  4. package/dist/collab/__fixtures__/live-copy-tasks.js +92 -0
  5. package/dist/collab/awareness.d.ts +2 -2
  6. package/dist/collab/bounded-task-bundle.d.ts +17 -0
  7. package/dist/collab/bounded-task-bundle.js +39 -0
  8. package/dist/collab/bounded-task-source.d.ts +14 -0
  9. package/dist/collab/bounded-task-source.js +8 -0
  10. package/dist/collab/bounded-tasks.d.ts +67 -0
  11. package/dist/collab/bounded-tasks.js +439 -0
  12. package/dist/collab/index.d.ts +5 -2
  13. package/dist/collab/index.js +5 -2
  14. package/dist/collab/live-copy-tasks.d.ts +80 -0
  15. package/dist/collab/live-copy-tasks.js +330 -0
  16. package/dist/collab/live-copy.d.ts +188 -0
  17. package/dist/collab/live-copy.js +415 -0
  18. package/dist/collab/routes.d.ts +6 -1
  19. package/dist/collab/routes.js +24 -8
  20. package/dist/collab/storage.d.ts +53 -1
  21. package/dist/collab/storage.js +93 -5
  22. package/dist/collab/ydoc-manager.d.ts +92 -3
  23. package/dist/collab/ydoc-manager.js +447 -38
  24. package/dist/db/client.d.ts +6 -0
  25. package/dist/db/client.js +25 -5
  26. package/dist/deploy/build.js +2 -0
  27. package/dist/extensions/actions.js +1 -0
  28. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  29. package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
  30. package/dist/mcp/agent-connected.js +5 -1
  31. package/dist/mcp/build-server.js +39 -10
  32. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  33. package/dist/org/handlers.d.ts +1 -1
  34. package/dist/org/index.d.ts +1 -1
  35. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  36. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  37. package/dist/resources/handlers.d.ts +1 -1
  38. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  39. package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
  40. package/dist/server/collab-plugin.d.ts +10 -1
  41. package/dist/server/collab-plugin.js +89 -20
  42. package/dist/server/realtime-token.d.ts +1 -1
  43. package/dist/shared/optional-node-builtins.d.ts +1 -0
  44. package/dist/shared/optional-node-builtins.js +3 -0
  45. package/dist/tracking/providers.d.ts +1 -0
  46. package/dist/tracking/providers.js +2 -1
  47. package/dist/triggers/actions/manage-automation.d.ts +2 -2
  48. package/dist/vite/bounded-task-plugin.d.ts +22 -0
  49. package/dist/vite/bounded-task-plugin.js +44 -0
  50. package/dist/vite/client.js +2 -0
  51. package/dist/vitest-config.js +3 -0
  52. package/package.json +4 -3
@@ -10,6 +10,7 @@ const GIT_IDENTITY = {
10
10
  GIT_COMMITTER_NAME: "agent-native",
11
11
  GIT_COMMITTER_EMAIL: "noreply@agent-native.com",
12
12
  };
13
+ const KEEP_LINE_ENDINGS = ["-c", "core.autocrlf=false", "-c", "core.eol=lf"];
13
14
  export function resolveBaselineStore(appDir) {
14
15
  const resolved = realpath(path.resolve(appDir));
15
16
  const gitDir = findGitDir(resolved);
@@ -67,10 +68,15 @@ export function writeBaseline(store, sourceDir, slot, meta) {
67
68
  copyPlainTree(sourceDir, target);
68
69
  const indexFile = path.join(stage, "index");
69
70
  const env = { ...process.env, ...GIT_IDENTITY, GIT_INDEX_FILE: indexFile };
70
- git(store, ["--work-tree", stageRoot, "add", "-A", "--force", "."], {
71
- cwd: stageRoot,
72
- env,
73
- });
71
+ git(store, [
72
+ ...KEEP_LINE_ENDINGS,
73
+ "--work-tree",
74
+ stageRoot,
75
+ "add",
76
+ "-A",
77
+ "--force",
78
+ ".",
79
+ ], { cwd: stageRoot, env });
74
80
  const tree = git(store, ["write-tree"], { cwd: stageRoot, env }).trim();
75
81
  const ref = baselineRefName(store, slot);
76
82
  const parent = revParse(store, ref);
@@ -142,7 +148,14 @@ export function materializeBaseline(store, slot) {
142
148
  return null;
143
149
  }
144
150
  const tarPath = path.join(out, ".baseline.tar");
145
- const args = ["archive", "--format=tar", "-o", tarPath, ref];
151
+ const args = [
152
+ ...KEEP_LINE_ENDINGS,
153
+ "archive",
154
+ "--format=tar",
155
+ "-o",
156
+ tarPath,
157
+ ref,
158
+ ];
146
159
  if (store.prefix)
147
160
  args.push("--", store.prefix);
148
161
  git(store, args);
@@ -149,12 +149,13 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
149
149
  manual: [],
150
150
  keptLocal: [],
151
151
  };
152
- const paths = new Set([
152
+ const paths = Array.from(new Set([
153
153
  ...listMergeableFiles(baseDir),
154
154
  ...listMergeableFiles(theirsDir),
155
155
  ...listMergeableFiles(appDir),
156
- ]);
157
- for (const rel of Array.from(paths).sort()) {
156
+ ])).sort();
157
+ const normalized = crlfNormalizedPaths(appDir, paths);
158
+ for (const rel of paths) {
158
159
  const oursPath = path.join(appDir, rel);
159
160
  if (isLocalSymlink(oursPath)) {
160
161
  result.manual.push(`${rel} (local symlink)`);
@@ -162,7 +163,9 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
162
163
  }
163
164
  const base = readFileOrNull(path.join(baseDir, rel));
164
165
  const theirs = readFileOrNull(path.join(theirsDir, rel));
165
- const ours = readFileOrNull(oursPath);
166
+ const app = readAppFile(oursPath, normalized.has(rel) ? (base ?? theirs) : null);
167
+ const ours = app.content;
168
+ const writeOurs = (content) => writeFile(oursPath, app.crlf ? withCrlf(content) : content);
166
169
  if (equalBuffers(base, theirs))
167
170
  continue;
168
171
  if (theirs === null) {
@@ -193,7 +196,7 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
193
196
  continue;
194
197
  if (equalBuffers(ours, base)) {
195
198
  if (!options.dryRun)
196
- writeFile(oursPath, theirs);
199
+ writeOurs(theirs);
197
200
  result.updated.push(rel);
198
201
  continue;
199
202
  }
@@ -206,8 +209,9 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
206
209
  result.manual.push(`${rel} (merge failed)`);
207
210
  continue;
208
211
  }
209
- if (!options.dryRun)
210
- writeFile(oursPath, merged.content);
212
+ if (!options.dryRun && !equalBuffers(merged.content, ours)) {
213
+ writeOurs(merged.content);
214
+ }
211
215
  if (merged.conflicts > 0)
212
216
  result.conflicted.push(rel);
213
217
  else
@@ -475,19 +479,21 @@ async function statusCommand(target, flags, io) {
475
479
  try {
476
480
  const local = countLocallyModified(target.appDir, baseDir);
477
481
  lines.push(` locally modified files: ${local}`);
478
- const targetRef = flags.to ?? target.provenance.templateRef ?? latest;
479
- const theirs = await materializeForTarget(target, flags, targetRef);
480
482
  try {
481
- const changed = countUpstreamChanged(baseDir, theirs.dir);
482
- lines.push(` upstream-changed files: ${changed} (at ${theirs.ref})`);
483
+ const targetRef = flags.to ?? target.provenance.templateRef ?? latest;
484
+ const theirs = await materializeForTarget(target, flags, targetRef);
485
+ try {
486
+ const changed = countUpstreamChanged(baseDir, theirs.dir);
487
+ lines.push(` upstream-changed files: ${changed} (at ${theirs.ref})`);
488
+ }
489
+ finally {
490
+ fs.rmSync(theirs.dir, { recursive: true, force: true });
491
+ }
483
492
  }
484
- finally {
485
- fs.rmSync(theirs.dir, { recursive: true, force: true });
493
+ catch (err) {
494
+ lines.push(` upstream-changed files: unavailable (${err instanceof Error ? err.message.split("\n")[0] : String(err)})`);
486
495
  }
487
496
  }
488
- catch (err) {
489
- lines.push(` upstream-changed files: unavailable (${err instanceof Error ? err.message.split("\n")[0] : String(err)})`);
490
- }
491
497
  finally {
492
498
  fs.rmSync(baseDir, { recursive: true, force: true });
493
499
  }
@@ -648,13 +654,19 @@ function backfillProvenance(target, template, materialized) {
648
654
  shape: target.shape,
649
655
  };
650
656
  pkg["agent-native"] = agentNative;
651
- fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
657
+ const json = Buffer.from(`${JSON.stringify(pkg, null, 2)}\n`);
658
+ const app = readAppFile(pkgPath, json);
659
+ if (equalBuffers(app.content, json))
660
+ return;
661
+ fs.writeFileSync(pkgPath, app.crlf ? withCrlf(json) : json);
652
662
  }
653
663
  function countLocallyModified(appDir, baseDir) {
654
664
  let count = 0;
655
- for (const rel of listMergeableFiles(baseDir)) {
665
+ const paths = Array.from(listMergeableFiles(baseDir));
666
+ const normalized = crlfNormalizedPaths(appDir, paths);
667
+ for (const rel of paths) {
656
668
  const base = readFileOrNull(path.join(baseDir, rel));
657
- const ours = readFileOrNull(path.join(appDir, rel));
669
+ const ours = readAppFile(path.join(appDir, rel), normalized.has(rel) ? base : null).content;
658
670
  if (!equalBuffers(base, ours))
659
671
  count++;
660
672
  }
@@ -809,6 +821,75 @@ function equalBuffers(a, b) {
809
821
  return a === b;
810
822
  return a.equals(b);
811
823
  }
824
+ // CRLF that git normalizes on add is not a local edit.
825
+ function readAppFile(file, template) {
826
+ const content = readFileOrNull(file);
827
+ if (content === null ||
828
+ template === null ||
829
+ template.includes(0x0d) ||
830
+ !isTextBuffer(content) ||
831
+ !isTextBuffer(template)) {
832
+ return { content, crlf: false };
833
+ }
834
+ const text = content.toString("utf-8");
835
+ if (!text.includes("\r\n") || /\r(?!\n)/.test(text)) {
836
+ return { content, crlf: false };
837
+ }
838
+ return {
839
+ content: Buffer.from(text.replace(/\r\n/g, "\n")),
840
+ crlf: !/(^|[^\r])\n/.test(text),
841
+ };
842
+ }
843
+ // Paths whose CRLF git turns into LF on add; anywhere else a CR is content.
844
+ function crlfNormalizedPaths(appDir, rels) {
845
+ const normalized = new Set();
846
+ if (!resolveBaselineStore(appDir).gitDir)
847
+ return normalized;
848
+ const res = spawnSync("git", ["check-attr", "-z", "--stdin", "text", "crlf", "eol"], {
849
+ cwd: appDir,
850
+ input: rels.join("\0"),
851
+ encoding: "utf-8",
852
+ maxBuffer: 64 * 1024 * 1024,
853
+ });
854
+ if (res.status !== 0) {
855
+ throw new Error(`git check-attr failed in ${appDir}: ${res.stderr || res.error?.message}`);
856
+ }
857
+ const config = spawnSync("git", ["config", "--get", "core.autocrlf"], {
858
+ cwd: appDir,
859
+ encoding: "utf-8",
860
+ });
861
+ if (config.status !== 0 && config.status !== 1) {
862
+ throw new Error(`git config core.autocrlf failed in ${appDir}: ${config.stderr || config.error?.message}`);
863
+ }
864
+ const byConfig = ["true", "yes", "on", "1", "input"].includes(config.stdout.trim().toLowerCase());
865
+ const attrs = new Map();
866
+ const fields = res.stdout.split("\0");
867
+ for (let i = 0; i + 2 < fields.length; i += 3) {
868
+ attrs.set(fields[i], {
869
+ ...attrs.get(fields[i]),
870
+ [fields[i + 1]]: fields[i + 2],
871
+ });
872
+ }
873
+ for (const [rel, { text, crlf, eol }] of attrs) {
874
+ const byAttrs = conversion(text) ??
875
+ conversion(crlf) ??
876
+ (eol === "lf" || eol === "crlf" ? true : null);
877
+ if (byAttrs ?? byConfig)
878
+ normalized.add(rel);
879
+ }
880
+ return normalized;
881
+ }
882
+ // A text or crlf attribute as git reads it: convert, keep bytes, or no say.
883
+ function conversion(value) {
884
+ if (value === "set" || value === "auto" || value === "input")
885
+ return true;
886
+ return value === "unset" ? false : null;
887
+ }
888
+ function withCrlf(content) {
889
+ if (!isTextBuffer(content))
890
+ return content;
891
+ return Buffer.from(content.toString("utf-8").replace(/\r?\n/g, "\r\n"));
892
+ }
812
893
  function isTextBuffer(buf) {
813
894
  if (buf === null)
814
895
  return true;
@@ -0,0 +1 @@
1
+ export declare const tasks: Record<string, (input: never) => Promise<import("../live-copy-tasks.js").LiveCopyTaskResult>>;
@@ -0,0 +1,92 @@
1
+ import * as Y from "yjs";
2
+ import { defineLiveCopyTasks } from "../live-copy-tasks.js";
3
+ // A tiny live-copy task module for the live-copy spec: a body is a list of
4
+ // paragraphs, and anything else is refused rather than dropped. Paragraphs
5
+ // and seed sources starting with "!" drive the failure cases.
6
+ function paragraph(text) {
7
+ const element = new Y.XmlElement("paragraph");
8
+ const content = new Y.XmlText();
9
+ content.insert(0, text);
10
+ element.insert(0, [content]);
11
+ return element;
12
+ }
13
+ /** An update whose base this document never had. */
14
+ function orphanUpdate() {
15
+ const elsewhere = new Y.Doc();
16
+ elsewhere.getXmlFragment("default").insert(0, [paragraph("unknown base")]);
17
+ const before = Y.encodeStateVector(elsewhere);
18
+ const fragment = elsewhere.getXmlFragment("default");
19
+ fragment.insert(1, [paragraph("orphan")]);
20
+ return Y.encodeStateAsUpdate(elsewhere, before);
21
+ }
22
+ export const tasks = defineLiveCopyTasks({
23
+ derive(doc, field) {
24
+ const lines = [];
25
+ for (const node of doc.getXmlFragment(field).toArray()) {
26
+ if (!(node instanceof Y.XmlElement) || node.nodeName !== "paragraph") {
27
+ return {
28
+ kind: "refused",
29
+ reason: "unsupported_node",
30
+ detail: node instanceof Y.XmlElement ? node.nodeName : "text",
31
+ };
32
+ }
33
+ const text = node
34
+ .toArray()
35
+ .map((child) => child.toString())
36
+ .join("");
37
+ if (text === "!spin") {
38
+ for (;;) {
39
+ // never returns
40
+ }
41
+ }
42
+ if (text === "!html")
43
+ return { kind: "html" };
44
+ if (text === "!edit")
45
+ doc.getXmlFragment(field).insert(0, [paragraph("")]);
46
+ if (text === "!park")
47
+ Y.applyUpdate(doc, orphanUpdate());
48
+ lines.push(text);
49
+ }
50
+ return lines.join("\n");
51
+ },
52
+ seed(doc, field, source) {
53
+ if (source === "!refuse")
54
+ return { kind: "refused", reason: "too_complex" };
55
+ if (source === "!empty")
56
+ return;
57
+ if (source === "!junk")
58
+ return { kind: "update" };
59
+ if (source === "!stray")
60
+ doc.getText("other").insert(0, "hidden");
61
+ doc.getXmlFragment(field).insert(0, source.split("\n").map(paragraph));
62
+ },
63
+ edits: {
64
+ append(doc, field, input) {
65
+ const fragment = doc.getXmlFragment(field);
66
+ const text = input?.text ?? "";
67
+ fragment.insert(fragment.length, [paragraph(text)]);
68
+ },
69
+ clear(doc, field) {
70
+ const fragment = doc.getXmlFragment(field);
71
+ fragment.delete(0, fragment.length);
72
+ },
73
+ stray(doc) {
74
+ doc.getText("other").insert(0, "hidden");
75
+ },
76
+ unchanged() { },
77
+ refuse() {
78
+ return { kind: "refused", reason: "too_complex" };
79
+ },
80
+ junk() {
81
+ return { kind: "update" };
82
+ },
83
+ dependent(doc) {
84
+ Y.applyUpdate(doc, orphanUpdate());
85
+ },
86
+ dependentAndValid(doc, field) {
87
+ Y.applyUpdate(doc, orphanUpdate());
88
+ const fragment = doc.getXmlFragment(field);
89
+ fragment.insert(fragment.length, [paragraph("valid")]);
90
+ },
91
+ },
92
+ });
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
38
38
  error: string;
39
39
  states?: undefined;
40
40
  } | {
41
- error?: undefined;
42
41
  states: {
43
42
  clientId: number;
44
43
  state: string;
45
44
  }[];
45
+ error?: undefined;
46
46
  }>>;
47
47
  export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
48
48
  error: string;
49
49
  users?: undefined;
50
50
  } | {
51
- error?: undefined;
52
51
  users: {
53
52
  clientId: number;
54
53
  lastSeen: number;
55
54
  }[];
55
+ error?: undefined;
56
56
  }>>;
@@ -0,0 +1,17 @@
1
+ import { type BoundedTaskSource } from "./bounded-task-source.js";
2
+ export interface BundleBoundedTaskSourceOptions {
3
+ /** Shown in errors and runner names. Defaults to the entry file's name. */
4
+ name?: string;
5
+ /** Extra esbuild `conditions` for package resolution. */
6
+ conditions?: string[];
7
+ }
8
+ export interface BundledBoundedTaskSource extends BoundedTaskSource {
9
+ /** Every file esbuild read, for watch-mode rebuilds. */
10
+ readonly inputs: readonly string[];
11
+ }
12
+ /**
13
+ * Bundles a task module and everything it imports into one script a worker
14
+ * can evaluate. The module must export `tasks`: an object of functions that
15
+ * take plain data and return plain data (or a Promise of it).
16
+ */
17
+ export declare function bundleBoundedTaskSource(entry: string | URL, options?: BundleBoundedTaskSourceOptions): Promise<BundledBoundedTaskSource>;
@@ -0,0 +1,39 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { BOUNDED_TASK_GLOBAL, } from "./bounded-task-source.js";
4
+ /**
5
+ * Bundles a task module and everything it imports into one script a worker
6
+ * can evaluate. The module must export `tasks`: an object of functions that
7
+ * take plain data and return plain data (or a Promise of it).
8
+ */
9
+ export async function bundleBoundedTaskSource(entry, options = {}) {
10
+ const entryPath = entry instanceof URL || entry.startsWith("file:")
11
+ ? fileURLToPath(entry)
12
+ : path.resolve(entry);
13
+ const esbuild = await import("esbuild");
14
+ const result = await esbuild.build({
15
+ entryPoints: [entryPath],
16
+ bundle: true,
17
+ write: false,
18
+ format: "iife",
19
+ globalName: BOUNDED_TASK_GLOBAL,
20
+ platform: "node",
21
+ target: "node20",
22
+ metafile: true,
23
+ sourcemap: false,
24
+ legalComments: "none",
25
+ logLevel: "silent",
26
+ ...(options.conditions ? { conditions: options.conditions } : {}),
27
+ });
28
+ const output = result.outputFiles?.[0];
29
+ if (!output) {
30
+ throw new Error(`esbuild produced no output for bounded task ${entryPath}`);
31
+ }
32
+ const cwd = process.cwd();
33
+ return {
34
+ kind: "bounded-task-source",
35
+ name: options.name ?? path.basename(entryPath).replace(/\.[^.]+$/, ""),
36
+ code: output.text,
37
+ inputs: Object.keys(result.metafile?.inputs ?? {}).map((input) => path.resolve(cwd, input)),
38
+ };
39
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Identifier the bundled task module is assigned to. `bundleBoundedTaskSource`
3
+ * emits an IIFE with this global name; the worker host reads it back.
4
+ */
5
+ export declare const BOUNDED_TASK_GLOBAL = "__agentNativeBoundedTasks";
6
+ /**
7
+ * A self-contained task module, bundled to one script. Produce it with
8
+ * `bundleBoundedTaskSource` (Node, esbuild); never hand-write `code`.
9
+ */
10
+ export interface BoundedTaskSource {
11
+ readonly kind: "bounded-task-source";
12
+ readonly name: string;
13
+ readonly code: string;
14
+ }
@@ -0,0 +1,8 @@
1
+ // The bundler and the vitest base config import this, not bounded-tasks.ts:
2
+ // packages that typecheck @agent-native/core/vitest-config from source load
3
+ // several @types/node versions, and node:worker_threads does not type there.
4
+ /**
5
+ * Identifier the bundled task module is assigned to. `bundleBoundedTaskSource`
6
+ * emits an IIFE with this global name; the worker host reads it back.
7
+ */
8
+ export const BOUNDED_TASK_GLOBAL = "__agentNativeBoundedTasks";
@@ -0,0 +1,67 @@
1
+ import { BOUNDED_TASK_GLOBAL, type BoundedTaskSource } from "./bounded-task-source.js";
2
+ export { BOUNDED_TASK_GLOBAL, type BoundedTaskSource };
3
+ export type BoundedTaskErrorCode = "unavailable" | "closed" | "queue_full" | "queue_timeout" | "invalid_input" | "input_too_large" | "startup_failed" | "task_unknown" | "task_threw" | "deadline_exceeded" | "memory_exceeded" | "invalid_output" | "output_too_large" | "worker_crashed";
4
+ export declare class BoundedTaskError extends Error {
5
+ readonly code: BoundedTaskErrorCode;
6
+ readonly task: string;
7
+ /** `name` of the error the task threw, for `task_threw`. */
8
+ readonly taskErrorName?: string;
9
+ constructor(code: BoundedTaskErrorCode, task: string, message: string, options?: {
10
+ cause?: unknown;
11
+ taskErrorName?: string;
12
+ });
13
+ }
14
+ export interface BoundedTaskRunnerOptions {
15
+ source: BoundedTaskSource;
16
+ /** Wall-clock budget for one task once a worker has it. Default 2000 ms. */
17
+ deadlineMs?: number;
18
+ /** Budget for a fresh worker to evaluate the bundle. Default 10000 ms. */
19
+ startupTimeoutMs?: number;
20
+ /** Workers alive at once; also the number of tasks running at once. Default 1. */
21
+ maxWorkers?: number;
22
+ /** Tasks allowed to wait for a worker. Beyond this, `queue_full`. Default 8. */
23
+ maxQueue?: number;
24
+ /**
25
+ * Longest a task may wait for a busy or terminating worker. A task waiting
26
+ * only for a worker to start is bounded by `startupTimeoutMs` instead.
27
+ * Default `deadlineMs`.
28
+ */
29
+ queueTimeoutMs?: number;
30
+ /** Strings count two bytes per UTF-16 unit. Default 8 MiB. */
31
+ maxInputBytes?: number;
32
+ /** Checked inside the worker before the result is copied out. Default 16 MiB. */
33
+ maxOutputBytes?: number;
34
+ /** Worker old-generation heap. Default 128 MiB. */
35
+ memoryLimitMb?: number;
36
+ /** Default 4 MiB. */
37
+ stackSizeMb?: number;
38
+ /** An idle worker is stopped after this long. Default 30000 ms. */
39
+ idleTimeoutMs?: number;
40
+ }
41
+ export interface BoundedTaskRunnerStats {
42
+ workers: number;
43
+ running: number;
44
+ queued: number;
45
+ }
46
+ export interface BoundedTaskRunner {
47
+ readonly name: string;
48
+ run<Output = unknown>(task: string, input: unknown): Promise<Output>;
49
+ stats(): BoundedTaskRunnerStats;
50
+ close(): Promise<void>;
51
+ }
52
+ /**
53
+ * Size of a structured-clone payload in bytes, or -1 when it holds anything
54
+ * but plain data (or more than 200,000 values). Stops counting once
55
+ * `limit` is passed. The worker host evaluates this function's source, so it
56
+ * must not reference anything outside its own body.
57
+ */
58
+ export declare function measureBoundedPayload(value: unknown, limit: number): number;
59
+ /**
60
+ * Runs functions from one bundled module in worker threads, each under a
61
+ * terminable deadline and a heap limit, with a fixed number of workers and a
62
+ * bounded wait queue. A task that overruns is stopped by terminating its
63
+ * worker, so synchronous work in the task never blocks the caller's event
64
+ * loop. Where worker threads do not exist (Cloudflare Workers), every run
65
+ * fails with `unavailable`; it never falls back to running inline.
66
+ */
67
+ export declare function createBoundedTaskRunner(options: BoundedTaskRunnerOptions): BoundedTaskRunner;