@poe-platform/safe-js 0.1.730 → 0.1.732

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 (100) hide show
  1. package/README.md +5 -5
  2. package/dist/safe-js/chunks/{chunk-SJZWSPWD.js → chunk-2GVBG23M.js} +1 -1
  3. package/dist/safe-js/chunks/{chunk-SJZWSPWD.js.map → chunk-2GVBG23M.js.map} +1 -1
  4. package/dist/safe-js/chunks/{chunk-MW2QLYVN.js → chunk-3ITVV2R6.js} +77 -66
  5. package/dist/safe-js/chunks/chunk-3ITVV2R6.js.map +7 -0
  6. package/dist/safe-js/chunks/{chunk-VIMROAQA.js → chunk-E4XLBT7R.js} +2 -2
  7. package/dist/safe-js/chunks/chunk-F6CV74HU.js +114 -0
  8. package/dist/safe-js/chunks/chunk-F6CV74HU.js.map +7 -0
  9. package/dist/safe-js/chunks/{chunk-OZLTLIHX.js → chunk-G6WTEIJJ.js} +2 -2
  10. package/dist/safe-js/chunks/{chunk-XX57YCGZ.js → chunk-GNEORAQI.js} +55 -50
  11. package/dist/safe-js/chunks/chunk-GNEORAQI.js.map +7 -0
  12. package/dist/safe-js/chunks/chunk-GVKXZW53.js +76 -0
  13. package/dist/safe-js/chunks/chunk-GVKXZW53.js.map +7 -0
  14. package/dist/safe-js/chunks/{chunk-MRULOD5J.js → chunk-K4T4EBED.js} +59 -38
  15. package/dist/safe-js/chunks/chunk-K4T4EBED.js.map +7 -0
  16. package/dist/safe-js/chunks/{chunk-MFCEBCGV.js → chunk-KETIFEA7.js} +17 -8
  17. package/dist/safe-js/chunks/chunk-KETIFEA7.js.map +7 -0
  18. package/dist/safe-js/chunks/{chunk-S5YDMMM3.js → chunk-MDIWQFYU.js} +95 -169
  19. package/dist/safe-js/chunks/{chunk-S5YDMMM3.js.map → chunk-MDIWQFYU.js.map} +4 -4
  20. package/dist/safe-js/chunks/{chunk-EN724VH3.js → chunk-O4IDRXW7.js} +4 -4
  21. package/dist/safe-js/chunks/{chunk-3LSNBW5N.js → chunk-P64CQIUA.js} +4 -4
  22. package/dist/safe-js/chunks/{chunk-EA7AHM2X.js → chunk-PSVV3IG2.js} +3 -3
  23. package/dist/safe-js/chunks/{chunk-Y5EZYHU6.js → chunk-QKO4FATZ.js} +33 -5
  24. package/dist/safe-js/chunks/chunk-QKO4FATZ.js.map +7 -0
  25. package/dist/safe-js/chunks/{chunk-EG3QWREA.js → chunk-RULU2F5J.js} +2 -2
  26. package/dist/safe-js/chunks/chunk-UQPYTZOZ.js +72 -0
  27. package/dist/safe-js/chunks/chunk-UQPYTZOZ.js.map +7 -0
  28. package/dist/safe-js/chunks/{chunk-LRSWTDIV.js → chunk-W4SWUHCQ.js} +58 -23
  29. package/dist/safe-js/chunks/chunk-W4SWUHCQ.js.map +7 -0
  30. package/dist/safe-js/chunks/{chunk-W3IY6FKO.js → chunk-WS2FJBH6.js} +2 -2
  31. package/dist/safe-js/chunks/{chunk-MVLDRXWS.js → chunk-X3CKAZQ4.js} +3 -3
  32. package/dist/safe-js/chunks/chunk-YUQFFRUF.js +26 -0
  33. package/dist/safe-js/chunks/chunk-YUQFFRUF.js.map +7 -0
  34. package/dist/safe-js/chunks/{cli-runtime-WSVW5DNT.js → cli-runtime-ZSOTNIVC.js} +51 -30
  35. package/dist/safe-js/chunks/cli-runtime-ZSOTNIVC.js.map +7 -0
  36. package/dist/safe-js/chunks/{dump-UNYK24YS.js → dump-RGRC3CG3.js} +5 -4
  37. package/dist/safe-js/chunks/harness-UMOMFXDT.js +11 -0
  38. package/dist/safe-js/chunks/mcp-2Z4XWHKW.js +12 -0
  39. package/dist/safe-js/chunks/migration-file-KRXQYI3Q.js +15 -0
  40. package/dist/safe-js/chunks/restore-GEO7VN2R.js +14 -0
  41. package/dist/safe-js/chunks/run-ZSFX66RN.js +20 -0
  42. package/dist/safe-js/chunks/runtime-modules-A3U2DKFL.js +11 -0
  43. package/dist/safe-js/chunks/source-files-L3SGK63Z.js +10 -0
  44. package/dist/safe-js/cli-runtime.d.ts +2 -0
  45. package/dist/safe-js/cli.js +4 -4
  46. package/dist/safe-js/core.d.ts +1 -0
  47. package/dist/safe-js/core.js +15 -8
  48. package/dist/safe-js/error/shape.js +170 -0
  49. package/dist/safe-js/index.js +42 -33
  50. package/dist/safe-js/index.js.map +2 -2
  51. package/dist/safe-js/interp/budget.js +600 -0
  52. package/dist/safe-js/interp/internal-symbols.js +1 -0
  53. package/dist/safe-js/interp/promise-replay.d.ts +1 -1
  54. package/dist/safe-js/interp/template-cache.js +7 -0
  55. package/dist/safe-js/migration-file.d.ts +2 -0
  56. package/dist/safe-js/modules/fs-config.d.ts +3 -1
  57. package/dist/safe-js/modules/fs.d.ts +8 -4
  58. package/dist/safe-js/modules/fs.js +16 -0
  59. package/dist/safe-js/modules/source-files.d.ts +3 -2
  60. package/dist/safe-js/platform/context.js +58 -0
  61. package/dist/safe-js/platform/node.js +64 -0
  62. package/dist/safe-js/platform/types.js +63 -0
  63. package/dist/safe-js/platform/workerd.js +39 -0
  64. package/dist/safe-js/runner/run-harness.d.ts +2 -0
  65. package/dist/safe-js/snapshot/backend.d.ts +2 -0
  66. package/package.json +9 -2
  67. package/dist/safe-js/chunks/chunk-FCCA27RC.js +0 -69
  68. package/dist/safe-js/chunks/chunk-FCCA27RC.js.map +0 -7
  69. package/dist/safe-js/chunks/chunk-LRSWTDIV.js.map +0 -7
  70. package/dist/safe-js/chunks/chunk-MFCEBCGV.js.map +0 -7
  71. package/dist/safe-js/chunks/chunk-MRULOD5J.js.map +0 -7
  72. package/dist/safe-js/chunks/chunk-MW2QLYVN.js.map +0 -7
  73. package/dist/safe-js/chunks/chunk-XX57YCGZ.js.map +0 -7
  74. package/dist/safe-js/chunks/chunk-Y5EZYHU6.js.map +0 -7
  75. package/dist/safe-js/chunks/cli-runtime-WSVW5DNT.js.map +0 -7
  76. package/dist/safe-js/chunks/fs-AOV77RQC.js +0 -13
  77. package/dist/safe-js/chunks/harness-ZIEO7NAV.js +0 -10
  78. package/dist/safe-js/chunks/mcp-E2AJXEQM.js +0 -11
  79. package/dist/safe-js/chunks/migration-file-3SWGNDS2.js +0 -12
  80. package/dist/safe-js/chunks/restore-FCTWPLU3.js +0 -13
  81. package/dist/safe-js/chunks/run-ESJHEXCE.js +0 -17
  82. package/dist/safe-js/chunks/runtime-modules-7V6BWCRK.js +0 -10
  83. package/dist/safe-js/chunks/source-files-73OHLNGH.js +0 -8
  84. /package/dist/safe-js/chunks/{chunk-VIMROAQA.js.map → chunk-E4XLBT7R.js.map} +0 -0
  85. /package/dist/safe-js/chunks/{chunk-OZLTLIHX.js.map → chunk-G6WTEIJJ.js.map} +0 -0
  86. /package/dist/safe-js/chunks/{chunk-EN724VH3.js.map → chunk-O4IDRXW7.js.map} +0 -0
  87. /package/dist/safe-js/chunks/{chunk-3LSNBW5N.js.map → chunk-P64CQIUA.js.map} +0 -0
  88. /package/dist/safe-js/chunks/{chunk-EA7AHM2X.js.map → chunk-PSVV3IG2.js.map} +0 -0
  89. /package/dist/safe-js/chunks/{chunk-EG3QWREA.js.map → chunk-RULU2F5J.js.map} +0 -0
  90. /package/dist/safe-js/chunks/{chunk-W3IY6FKO.js.map → chunk-WS2FJBH6.js.map} +0 -0
  91. /package/dist/safe-js/chunks/{chunk-MVLDRXWS.js.map → chunk-X3CKAZQ4.js.map} +0 -0
  92. /package/dist/safe-js/chunks/{dump-UNYK24YS.js.map → dump-RGRC3CG3.js.map} +0 -0
  93. /package/dist/safe-js/chunks/{fs-AOV77RQC.js.map → harness-UMOMFXDT.js.map} +0 -0
  94. /package/dist/safe-js/chunks/{harness-ZIEO7NAV.js.map → mcp-2Z4XWHKW.js.map} +0 -0
  95. /package/dist/safe-js/chunks/{mcp-E2AJXEQM.js.map → migration-file-KRXQYI3Q.js.map} +0 -0
  96. /package/dist/safe-js/chunks/{migration-file-3SWGNDS2.js.map → restore-GEO7VN2R.js.map} +0 -0
  97. /package/dist/safe-js/chunks/{restore-FCTWPLU3.js.map → run-ZSFX66RN.js.map} +0 -0
  98. /package/dist/safe-js/chunks/{run-ESJHEXCE.js.map → runtime-modules-A3U2DKFL.js.map} +0 -0
  99. /package/dist/safe-js/chunks/{runtime-modules-7V6BWCRK.js.map → source-files-L3SGK63Z.js.map} +0 -0
  100. /package/dist/safe-js/{chunks/source-files-73OHLNGH.js.map → modules/fs.js.map} +0 -0
package/README.md CHANGED
@@ -36,7 +36,7 @@ console.log(result.returnValue);
36
36
 
37
37
  `run()` takes source text, not a file path. Success returns `ok`, `returnValue`, `snapshot`, and `stats`. Handle both an `ok: false` result and a rejected promise: parsing, budget exhaustion, cancellation, and some execution failures can reject. Top-level `await` in this example lets rejections reach Node.
38
38
 
39
- `@poe-platform/safe-js/core` exposes `run`, `createRealm`, `defineExtension`, `lint`, `Budget`, and replayable-random helpers. The shared filesystem lives in `@poe-platform/safe-fs`, with a portable `/core` entry. Existing `@poe-platform/safe-js/fs`, `/fs/core`, and `/fs/node` imports re-export it. Legacy `poe-code/safe-js` imports remain available through the CLI package but use a separate runtime; keep factories and errors within one import family.
39
+ `@poe-platform/safe-js/core` exposes `run`, `createRealm`, `defineExtension`, `lint`, `Budget`, and replayable-random helpers. The `/core`, `/workerd`, and `/modules/fs` workspace entries bundle with the `workerd` or `browser` condition without Node built-ins. Supply a `@poe-code/safe-fs` adapter for filesystem capabilities; `createRootedSourceResolver(root, adapter)` grants portable source imports. File snapshots, migrations, harnesses, and file-running helpers also accept an `adapter`. The shared filesystem lives in `@poe-platform/safe-fs`, with a portable `/core` entry. Existing `@poe-platform/safe-js/fs`, `/fs/core`, and `/fs/node` imports re-export it. Legacy `poe-code/safe-js` imports remain available through the CLI package but use a separate runtime; keep factories and errors within one import family.
40
40
 
41
41
  ## Supported features
42
42
 
@@ -237,7 +237,7 @@ Execution gives host timers and cancellation turns between guest nodes after ela
237
237
  | `extensions` | Explicit `defineExtension(...)` registrations; `[]`. Setup runs once, on first evaluation, not on construction or unused close. |
238
238
  | `grants` | Granted capability names; `[]`. Every requested capability must be granted before any extension setup runs. |
239
239
  | `builtinOverrides` | Optional `{ console: "extension-name" }` authorizes that registered extension to replace only the builtin console. It must declare `console` and export a host object created in the realm. No overrides by default. |
240
- | `limits` | Positive integer caps: `extensions: 32`, `hostObjects: 1024`, `callbacks: 1024`, `guestReferences: 1024`, `cleanups: 1024`, `nestedEvaluations: 16`. Collection budgets also apply. |
240
+ | `limits` | Optional positive integer caps for `extensions`, `hostObjects`, `callbacks`, `guestReferences`, `cleanups`, and `nestedEvaluations`. Every cap defaults to `Infinity` and accepts explicit `Infinity`. Collection budgets also apply. |
241
241
  | `stringCompilation` | Optional `"allow"` (default) or `"deny"`. Denial raises a catchable guest EvalError for string eval and Function/AsyncFunction/GeneratorFunction/AsyncGeneratorFunction compilation, including retained callbacks. Host source evaluation remains available. This is separate from WebAssembly compilation policy. |
242
242
  | `classicScripts` | Optional boolean, default `false`. Evaluations use classic Script grammar with persistent globals: top-level `this` is the intrinsic global object, `var` and functions create global properties, and `let`/`const` remain lexical. Injected capabilities stay immutable lexical bindings. Explicit source modules retain module semantics. |
243
243
  | `classicScriptErrors` | Optional `"fatal"` (default) or `"report"`; reporting requires `classicScripts: true`. Ordinary escaped Script exceptions return `ok: false` with `recoverable: true` while preserving realm state. Syntax, budget, cancellation, module, callback and unhandled rejection failures remain fatal. |
@@ -445,7 +445,7 @@ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same re
445
445
  | `snapshotIntervalMs` | Periodic checkpoint interval when persistence is configured: 30,000 ms; `0` disables periodic writes. Capture happens at interpreter yield points. |
446
446
  | `hostCallResumeProvider` | Reconciles pending external operations on restore; returns a matching `HostCallResumeProof`. |
447
447
 
448
- `new Budget(options?)` accepts optional limits. A custom budget replaces the default, so include `maxCallDepth` if you want that guard.
448
+ `new Budget(options?)` accepts optional limits, each unlimited by default. Explicit `Infinity` also disables a limit. Set `maxCallDepth` to opt into a recursion guard in `run()` or `createRealm()`.
449
449
 
450
450
  | Option | Limit |
451
451
  | --- | --- |
@@ -536,7 +536,7 @@ Factories return exports to register in `modules`; calling a factory alone does
536
536
  | --- | --- |
537
537
  | `makeAgentModule(spawnAgent, options?)` | Inject the agent runner. Options: `defaultRetry`, `onEvent`, `otelSink`. Exposes `spawn`, `spawn.retry`, and `spawn.parallel`; call options follow this table. |
538
538
  | `makeMcpModule(options)` | Required `servers` map: stdio `{ command, args?, cwd?, env? }` or HTTP `{ url, headers? }`. Options: `requestTimeoutMs` (30,000), `closeTimeoutMs` (1,000), `maxToolPages` (100), `signal`, and injected `fetch`/`spawn`. Named clients expose `tools`, `tool`, `toolBatch`, and `close`; close managed clients when finished. A custom connector function is also accepted. |
539
- | `makeFsModule(options?)` | Node-backed `{ root?, fs? }`, or shared-filesystem `{ adapter, root?, cwd?, signal? }`; do not combine `fs` and `adapter`. Node access without `root` is unconfined. Rooted calls sharing the same adapter or Node implementation are serialized through path checks and backend completion to prevent guest namespace races. External host mutations or distinct adapters over the same storage require independent backend confinement. With an adapter, `root` confines access and `cwd` selects the virtual relative-path base; without `root`, explicit `cwd` also confines access. Omitting both uses virtual `/`. Adapter text reads pass a byte cap derived conservatively from the guest string and remaining data limits to the backend before decoding. Each read is also capped at 419,430 input bytes. A shared 16 MiB host read allowance reserves ten bytes per input byte for collection, copies, encoding expansion and admission; concurrent reads that exceed it reject, and reservations release after the underlying read settles and decoding finishes, including when cancellation rejects the caller earlier. Native Node/injected `fs` implementations retain their own read behavior. Read text with `readFile(path, "utf8")`; see the [module methods](src/modules/fs.ts) and [filesystem package](../safe-fs/README.md). |
539
+ | `makeFsModule(options?)` | Node-backed `{ root?, fs? }`, or shared-filesystem `{ adapter, root?, cwd?, signal? }`; do not combine `fs` and `adapter`. Node access without `root` is unconfined. Rooted calls sharing the same adapter or Node implementation are serialized through path checks and backend completion to prevent guest namespace races. External host mutations or distinct adapters over the same storage require independent backend confinement. With an adapter, `root` confines access and `cwd` selects the virtual relative-path base; without `root`, explicit `cwd` also confines access. Omitting both uses virtual `/`. Adapter text reads pass a byte cap derived conservatively from the guest string and remaining data limits to the backend before decoding. Optional `readFileMaxBytes` and `hostReadMemoryLimit` default to `Infinity` and accept explicit `Infinity`. A finite host allowance reserves ten bytes per input byte for collection, copies, encoding expansion and admission across concurrent reads from that module; reservations release after the underlying read settles and decoding finishes, including when cancellation rejects the caller earlier. Native Node/injected `fs` implementations retain their own read behavior. Read text with `readFile(path, "utf8")`; see the [module methods](src/modules/fs.ts) and [filesystem package](../safe-fs/README.md). |
540
540
  | `makeEnvModule(namesOrOptions)` | Allowed-name array or `{ allow, values? }`; exposes `get(name)`. `parseEnvConfig(json)` accepts the object form. |
541
541
  | `makeTimeModule(options?)` | `now`, `random`, `seed`, `signal`; exposes `now`, `random`, `sleep`, `uuid`. Defaults to host time/randomness; `seed` makes the random generator deterministic, and explicit `random` takes precedence. |
542
542
  | `makeLogModule(sink)` | Sends timestamped `info`, `error`, and `event` entries to your callback. |
@@ -548,7 +548,7 @@ Factories return exports to register in `modules`; calling a factory alone does
548
548
 
549
549
  `spawn.retry(definition, options, retryOptions)` and `defaultRetry` use `{ maxAttempts, backoffMs, isErrorRetryable?, isRetryable? }`. `spawn.parallel(calls, options?)` accepts definition/options tuples or spawn-handle factories; options are `check`, `maxConcurrent`, `failFast`, and `signal`. Usage helpers are `createSpawnUsageAccumulator()` and `runWithSpawnUsageAccumulator(accumulator, operation)`.
550
550
 
551
- **Config files.** `parseMcpConfig(json, directory)` accepts `servers` and the three numeric MCP limits, resolving stdio paths against `directory`. `parseFsConfig(json)` accepts `{ adapter: { type, options }, root?, cwd? }`; `resolveFsConfig(config, { registry? })` constructs the adapter for `makeFsModule`. Built-in types are `memory` and `real`; `real` requires an absolute host `options.root`. Outer `root`/`cwd` are absolute virtual paths. Custom registry descriptors supply `validateOptions` and `create`. Signals and injected functions are SDK options, not JSON fields.
551
+ **Config files.** `parseMcpConfig(json, directory)` accepts `servers` and the three numeric MCP limits, resolving stdio paths against `directory`. `parseFsConfig(json)` accepts `{ adapter: { type, options }, root?, cwd?, readFileMaxBytes?, hostReadMemoryLimit? }`; `resolveFsConfig(config, { registry? })` constructs the adapter for `makeFsModule`. Built-in types are `memory` and `real`; `real` requires an absolute host `options.root`. Outer `root`/`cwd` are absolute virtual paths. Custom registry descriptors supply `validateOptions` and `create`. Signals and injected functions are SDK options, not JSON fields.
552
552
 
553
553
  </details>
554
554
 
@@ -14,4 +14,4 @@ export {
14
14
  getOwnErrorCode,
15
15
  hasOwnErrorCode
16
16
  };
17
- //# sourceMappingURL=chunk-SJZWSPWD.js.map
17
+ //# sourceMappingURL=chunk-2GVBG23M.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/error-codes.ts"],
4
- "sourcesContent": ["export function getOwnErrorCode(error: unknown): string | undefined {\n if (\n typeof error !== \"object\" ||\n error === null ||\n !Object.prototype.hasOwnProperty.call(error, \"code\")\n ) {\n return undefined;\n }\n\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\nexport function hasOwnErrorCode(error: unknown, code: string): error is NodeJS.ErrnoException {\n return getOwnErrorCode(error) === code;\n}\n"],
4
+ "sourcesContent": ["export function getOwnErrorCode(error: unknown): string | undefined {\n if (\n typeof error !== \"object\" ||\n error === null ||\n !Object.prototype.hasOwnProperty.call(error, \"code\")\n ) {\n return undefined;\n }\n\n const code = (error as { code?: unknown }).code;\n return typeof code === \"string\" ? code : undefined;\n}\n\nexport function hasOwnErrorCode(error: unknown, code: string): error is NodeJS.ErrnoException {\n return getOwnErrorCode(error) === code;\n}\n\nexport type SystemError = Error & { code?: string; errno?: number; syscall?: string; path?: string; dest?: string };\n"],
5
5
  "mappings": ";AAAO,SAAS,gBAAgB,OAAoC;AAClE,MACE,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,OAAO,UAAU,eAAe,KAAK,OAAO,MAAM,GACnD;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAQ,MAA6B;AAC3C,SAAO,OAAO,SAAS,WAAW,OAAO;AAC3C;AAEO,SAAS,gBAAgB,OAAgB,MAA8C;AAC5F,SAAO,gBAAgB,KAAK,MAAM;AACpC;",
6
6
  "names": []
7
7
  }
@@ -148,48 +148,58 @@ function isJsonValue(value, options = {}) {
148
148
  const maxNodes = options.maxNodes ?? 1e4;
149
149
  const maxDepth = options.maxDepth ?? 64;
150
150
  if (maxNodes !== Infinity && (!Number.isSafeInteger(maxNodes) || maxNodes < 1)) throw new Error("maxNodes must be a positive safe integer");
151
- if (!Number.isSafeInteger(maxDepth) || maxDepth < 0 || maxDepth > 256) throw new Error("maxDepth must be an integer between 0 and 256");
151
+ if (maxDepth !== Infinity && (!Number.isSafeInteger(maxDepth) || maxDepth < 0)) throw new Error("maxDepth must be a nonnegative safe integer or Infinity");
152
152
  const ancestors = /* @__PURE__ */ new Set();
153
+ const stack = [];
154
+ function* properties(item2) {
155
+ if (Array.isArray(item2)) {
156
+ for (let index = 0; index < item2.length; index++) yield Object.getOwnPropertyDescriptor(item2, String(index));
157
+ } else for (const key2 in item2) {
158
+ const property = Object.getOwnPropertyDescriptor(item2, key2);
159
+ if (property !== void 0) yield property;
160
+ }
161
+ }
153
162
  let nodes = 0;
154
- const visit = (item, depth) => {
163
+ let item = value, depth = 0;
164
+ while (true) {
155
165
  if (++nodes > maxNodes || depth > maxDepth) return false;
156
- if (item === null || typeof item === "string" || typeof item === "boolean") return true;
157
- if (typeof item === "number") return Number.isFinite(item);
158
- if (typeof item !== "object" || ancestors.has(item)) return false;
159
- if (!Array.isArray(item) && Object.getPrototypeOf(item) !== Object.prototype && Object.getPrototypeOf(item) !== null) return false;
160
- let hookOwner = item;
161
- let prototypeDepth = 0;
162
- while (hookOwner !== null) {
163
- if (++prototypeDepth > 64) return false;
164
- const serializationHook = Object.getOwnPropertyDescriptor(hookOwner, "toJSON");
165
- if (serializationHook !== void 0) {
166
- if (!("value" in serializationHook) || typeof serializationHook.value === "function") return false;
167
- break;
168
- }
169
- hookOwner = Object.getPrototypeOf(hookOwner);
170
- }
171
- ancestors.add(item);
172
- let valid = true;
173
- if (Array.isArray(item)) {
174
- if (item.length > maxNodes) valid = false;
175
- else for (let index = 0; index < item.length; index++) {
176
- const property = Object.getOwnPropertyDescriptor(item, String(index));
177
- if (property === void 0 || !("value" in property) || !visit(property.value, depth + 1)) {
178
- valid = false;
179
- break;
166
+ if (item !== null && typeof item !== "string" && typeof item !== "boolean") {
167
+ if (typeof item === "number") {
168
+ if (!Number.isFinite(item)) return false;
169
+ } else {
170
+ if (typeof item !== "object" || ancestors.has(item)) return false;
171
+ if (!Array.isArray(item) && Object.getPrototypeOf(item) !== Object.prototype && Object.getPrototypeOf(item) !== null) return false;
172
+ let hookOwner = item;
173
+ let prototypeDepth = 0;
174
+ while (hookOwner !== null) {
175
+ if (++prototypeDepth > 64) return false;
176
+ const serializationHook = Object.getOwnPropertyDescriptor(hookOwner, "toJSON");
177
+ if (serializationHook !== void 0) {
178
+ if (!("value" in serializationHook) || typeof serializationHook.value === "function") return false;
179
+ break;
180
+ }
181
+ hookOwner = Object.getPrototypeOf(hookOwner);
180
182
  }
183
+ if (Array.isArray(item) && item.length > maxNodes - nodes) return false;
184
+ ancestors.add(item);
185
+ stack.push({ owner: item, children: properties(item), depth });
181
186
  }
182
- } else for (const key2 in item) {
183
- const property = Object.getOwnPropertyDescriptor(item, key2);
184
- if (property !== void 0 && (!("value" in property) || !visit(property.value, depth + 1))) {
185
- valid = false;
187
+ }
188
+ let next;
189
+ while (stack.length) {
190
+ const frame = stack[stack.length - 1];
191
+ next = frame.children.next();
192
+ if (!next.done) {
193
+ if (next.value === void 0 || !("value" in next.value)) return false;
194
+ item = next.value.value;
195
+ depth = frame.depth + 1;
186
196
  break;
187
197
  }
198
+ ancestors.delete(frame.owner);
199
+ stack.pop();
188
200
  }
189
- ancestors.delete(item);
190
- return valid;
191
- };
192
- return visit(value, 0);
201
+ if (!stack.length) return true;
202
+ }
193
203
  }
194
204
 
195
205
  // packages/toolcraft-schema/src/json-schema/utils.ts
@@ -3637,38 +3647,39 @@ async function waitForOAuthOperation(operation, signal) {
3637
3647
  // packages/mcp-oauth/src/client/bounded-json.ts
3638
3648
  function copyBoundedOAuthJson(value, message) {
3639
3649
  const invalid = () => new Error(message);
3640
- let nodes = 0;
3641
- function copy(input, depth) {
3642
- if (++nodes > 2e4 || depth > 64) throw invalid();
3643
- if (input === null || typeof input === "boolean" || typeof input === "string") return input;
3644
- if (typeof input === "number" && Number.isFinite(input)) return input;
3645
- if (typeof input !== "object" || input === null) throw invalid();
3646
- const descriptors = Object.getOwnPropertyDescriptors(input);
3647
- if (Array.isArray(input)) {
3648
- const length = descriptors.length?.value;
3649
- if (length > 2e4) throw invalid();
3650
- const result2 = [];
3651
- for (let index = 0; index < length; index++) {
3652
- const descriptor = descriptors[String(index)];
3653
- if (descriptor === void 0 || !Object.hasOwn(descriptor, "value")) throw invalid();
3654
- result2.push(copy(descriptor.value, depth + 1));
3655
- }
3656
- return result2;
3657
- }
3658
- if (Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null) throw invalid();
3659
- return Object.fromEntries(Object.entries(descriptors).filter(([, descriptor]) => descriptor.enumerable).map(([key2, descriptor]) => {
3660
- if (!Object.hasOwn(descriptor, "value")) throw invalid();
3661
- return [key2, copy(descriptor.value, depth + 1)];
3662
- }));
3663
- }
3664
- let result;
3650
+ const ancestors = /* @__PURE__ */ new Set();
3651
+ const root = {};
3652
+ const tasks = [{ input: value, target: root, key: "value" }];
3665
3653
  try {
3666
- result = copy(value, 0);
3654
+ while (tasks.length) {
3655
+ const task = tasks.pop();
3656
+ if ("leave" in task) {
3657
+ ancestors.delete(task.leave);
3658
+ continue;
3659
+ }
3660
+ const { input, target, key: key2 } = task;
3661
+ let output = input;
3662
+ if (input !== null && typeof input !== "boolean" && typeof input !== "string" && !(typeof input === "number" && Number.isFinite(input))) {
3663
+ if (typeof input !== "object" || input === null || ancestors.has(input)) throw invalid();
3664
+ const descriptors = Object.getOwnPropertyDescriptors(input);
3665
+ const array = Array.isArray(input);
3666
+ if (!array && Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null) throw invalid();
3667
+ output = array ? [] : {};
3668
+ ancestors.add(input);
3669
+ tasks.push({ leave: input });
3670
+ const keys = array ? Array.from({ length: input.length }, (_, index) => String(index)) : Object.keys(descriptors).filter((name) => descriptors[name].enumerable);
3671
+ for (let index = keys.length - 1; index >= 0; index--) {
3672
+ const name = keys[index], descriptor = descriptors[name];
3673
+ if (descriptor === void 0 || !Object.hasOwn(descriptor, "value")) throw invalid();
3674
+ tasks.push({ input: descriptor.value, target: output, key: name });
3675
+ }
3676
+ }
3677
+ Object.defineProperty(target, key2, { value: output, enumerable: true, configurable: true, writable: true });
3678
+ }
3679
+ return root.value;
3667
3680
  } catch {
3668
3681
  throw invalid();
3669
3682
  }
3670
- if (Buffer.byteLength(JSON.stringify(result), "utf8") > 64 * 1024) throw invalid();
3671
- return result;
3672
3683
  }
3673
3684
 
3674
3685
  // packages/mcp-oauth/src/client/loopback-authorization.ts
@@ -7817,7 +7828,7 @@ var HttpTransport = class {
7817
7828
  }
7818
7829
  async completeInitialization(options) {
7819
7830
  validateRequestTimer(options.timeoutMs, "timeoutMs");
7820
- const deadline = options.timeoutMs > 0 ? AbortSignal.timeout(Math.ceil(options.timeoutMs)) : void 0;
7831
+ const deadline = options.timeoutMs !== Infinity && options.timeoutMs > 0 ? AbortSignal.timeout(Math.ceil(options.timeoutMs)) : void 0;
7821
7832
  const signals = [options.signal, deadline].filter((signal2) => signal2 !== void 0);
7822
7833
  const signal = signals.length === 0 ? new AbortController().signal : AbortSignal.any(signals);
7823
7834
  signal.throwIfAborted();
@@ -8632,7 +8643,7 @@ var SseParser = class {
8632
8643
  }
8633
8644
  };
8634
8645
  function validateRequestTimer(value, name) {
8635
- if (!Number.isFinite(value) || value < 0 || value > 2147483647)
8646
+ if (value !== Infinity && (!Number.isFinite(value) || value < 0 || value > 2147483647))
8636
8647
  throw new Error(`${name} must be a non-negative finite number no greater than 2147483647`);
8637
8648
  }
8638
8649
  var JsonRpcMessageLayer = class {
@@ -8728,7 +8739,7 @@ var JsonRpcMessageLayer = class {
8728
8739
  currentRequestId = id;
8729
8740
  onRequestId?.(id);
8730
8741
  } };
8731
- const deadline = timeoutMs === null ? void 0 : setTimeout(() => {
8742
+ const deadline = timeoutMs === null || timeoutMs === Infinity ? void 0 : setTimeout(() => {
8732
8743
  let reason = new Error(`JSON-RPC request "${method}" timed out after ${timeoutMs}ms`);
8733
8744
  try {
8734
8745
  if (currentRequestId !== void 0) options.onTimeout?.(currentRequestId);
@@ -9818,4 +9829,4 @@ CC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for
9818
9829
  the full license text.
9819
9830
 
9820
9831
  */
9821
- //# sourceMappingURL=chunk-MW2QLYVN.js.map
9832
+ //# sourceMappingURL=chunk-3ITVV2R6.js.map