@selvajs/compute 4.2.2-beta.0 → 5.0.0-beta.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-XZk7EVP3.cjs","names":[],"sources":["../src/core/errors.ts","../src/core/utils/logger.ts","../src/core/utils/read-field.ts","../src/core/server/validate-server-url.ts","../src/core/compute-fetch/request.ts","../src/core/server/classify-probe-failure.ts","../src/core/utils/encoding.ts","../src/core/compute-fetch/server-timing.ts","../src/core/compute-fetch/signal.ts","../src/core/compute-fetch/wire-size.ts","../src/core/compute-fetch/response.ts","../src/core/compute-fetch/retry.ts","../src/core/compute-fetch/compute-fetch.ts","../src/core/definition-ref.ts","../src/core/files/sub-folder.ts","../src/core/files/handle-files.ts"],"sourcesContent":["export const ErrorCodes = {\n\t/** Connection failure, a gateway status (502/503/504), or a 2xx body cut off mid-stream. */\n\tNETWORK_ERROR: 'NETWORK_ERROR',\n\t/** HTTP 401 or 403: the server rejected the credentials. */\n\tAUTH_ERROR: 'AUTH_ERROR',\n\t/** The server rejected the request (HTTP 400, 413), or an input failed a client-side check. */\n\tVALIDATION_ERROR: 'VALIDATION_ERROR',\n\t/** The server failed the solve (HTTP 500), or the solve reported errors. */\n\tCOMPUTATION_ERROR: 'COMPUTATION_ERROR',\n\t/** No response within `ComputeConfig.timeoutMs`. */\n\tTIMEOUT_ERROR: 'TIMEOUT_ERROR',\n\t/** A browser fetch failed with no response: most often CORS, which the browser hides. */\n\tCORS_ERROR: 'CORS_ERROR',\n\t/** HTTP 404: the endpoint doesn't exist on this server. Never retried. */\n\tNOT_FOUND: 'NOT_FOUND',\n\t/** HTTP 429. Retried, honouring `Retry-After`, when the policy allows (`RetryPolicy.retryOn429`). */\n\tRATE_LIMIT: 'RATE_LIMIT',\n\t/** A 2xx that declared a non-JSON body, e.g. a captive portal or proxy login page. Never retried. */\n\tINVALID_RESPONSE: 'INVALID_RESPONSE',\n\t/** Any failure not classified by another code. */\n\tUNKNOWN_ERROR: 'UNKNOWN_ERROR',\n\t/** An object was used after `dispose()`, or a file download failed part-way. */\n\tINVALID_STATE: 'INVALID_STATE',\n\t/** A caller-supplied argument is unusable: an empty definition, an unserializable body. */\n\tINVALID_INPUT: 'INVALID_INPUT',\n\t/** Bad configuration: an invalid `serverUrl`, an incomplete logger, an interval out of range. */\n\tINVALID_CONFIG: 'INVALID_CONFIG',\n\t/** A browser-only API (file download) was called outside a browser. */\n\tBROWSER_ONLY: 'BROWSER_ONLY',\n\t/** The runtime has no base64 codec: neither `Buffer` nor `atob`/`btoa`. */\n\tENVIRONMENT_ERROR: 'ENVIRONMENT_ERROR',\n\t/** A string that should be base64 isn't. */\n\tENCODING_ERROR: 'ENCODING_ERROR',\n\t/** An input's `default` had a shape the normalizer didn't recognize. */\n\tMALFORMED_DEFAULT: 'MALFORMED_DEFAULT',\n\t/** Latest-wins scheduling: a newer call replaced this one. */\n\tSUPERSEDED: 'SUPERSEDED',\n\t/** The scheduler or a caller-supplied `AbortSignal` aborted this call. */\n\tABORTED: 'ABORTED',\n\t/**\n\t * The queue was at `maxQueueDepth`, so the call was rejected without queueing. Retryable after a\n\t * back-off. `context` carries `{ queueDepth, maxQueueDepth }`.\n\t */\n\tQUEUE_FULL: 'QUEUE_FULL',\n\t/**\n\t * The call waited longer than `queueWaitMs` without starting, and was rejected rather than run\n\t * stale. Retryable. `context` carries `{ waitedMs, queueWaitMs }`.\n\t */\n\tQUEUE_TIMEOUT: 'QUEUE_TIMEOUT',\n\t/**\n\t * The server no longer holds the definition a `pointer` named (evicted, restarted, another\n\t * child). Retry with the full definition. Read from the error body's\n\t * `code: \"definition_not_cached\"`.\n\t */\n\tDEFINITION_NOT_CACHED: 'DEFINITION_NOT_CACHED'\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n/** Error with a typed `code`: switch on it rather than on the message. */\nexport class ComputeError extends Error {\n\tpublic readonly code: ErrorCode;\n\tpublic readonly statusCode?: number;\n\tpublic readonly context?: Record<string, unknown>;\n\tpublic readonly originalError?: Error;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tcode: ErrorCode = ErrorCodes.UNKNOWN_ERROR,\n\t\toptions?: { statusCode?: number; context?: Record<string, unknown>; originalError?: unknown }\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'ComputeError';\n\t\tthis.code = code;\n\t\tthis.statusCode = options?.statusCode;\n\t\tthis.context = options?.context;\n\t\tif (options?.originalError !== undefined) {\n\t\t\tconst original = options.originalError;\n\t\t\tthis.originalError = original instanceof Error ? original : new Error(String(original));\n\t\t\t(this as { cause?: unknown }).cause = this.originalError;\n\t\t}\n\t}\n}\n","import { ComputeError, ErrorCodes } from '../errors';\n\nexport interface Logger {\n\tdebug(message: string, ...args: unknown[]): void;\n\tinfo(message: string, ...args: unknown[]): void;\n\twarn(message: string, ...args: unknown[]): void;\n\terror(message: string, ...args: unknown[]): void;\n}\n\nconst silent: Logger = {\n\tdebug() {},\n\tinfo() {},\n\twarn() {},\n\terror() {}\n};\n\nlet internalLogger: Logger = silent;\n\nexport function getLogger(): Logger {\n\treturn internalLogger;\n}\n\n/**\n * Route the package's logs to `logger`; `null` silences them (the default).\n *\n * @throws {ComputeError} `INVALID_CONFIG` if the logger lacks one of the four methods, rather\n * than a \"debug is not a function\" later at an unrelated call site.\n *\n * @example\n * ```typescript\n * import { setLogger } from '@selvajs/compute/core';\n *\n * setLogger(console);\n * setLogger({\n * debug: (msg, ...args) => myLogger.debug(msg, ...args),\n * info: (msg, ...args) => myLogger.info(msg, ...args),\n * warn: (msg, ...args) => myLogger.warn(msg, ...args),\n * error: (msg, ...args) => myLogger.error(msg, ...args)\n * });\n * setLogger(null);\n * ```\n */\nexport function setLogger(logger: Logger | Console | null): void {\n\tif (logger === null) {\n\t\tinternalLogger = silent;\n\t\treturn;\n\t}\n\n\tconst missing = (['debug', 'info', 'warn', 'error'] as const).filter(\n\t\t(method) => typeof (logger as unknown as Record<string, unknown>)[method] !== 'function'\n\t);\n\tif (missing.length > 0) {\n\t\tthrow new ComputeError(\n\t\t\t`Logger is missing required method(s): ${missing.join(', ')}. A logger must implement debug, info, warn and error.`,\n\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t{ context: { missingMethods: missing } }\n\t\t);\n\t}\n\n\tinternalLogger = logger as Logger;\n}\n\n/** Shorthand for `setLogger(console)`. */\nexport function enableDebugLogging(): void {\n\tsetLogger(console);\n}\n","/**\n * Case-insensitive field reads for wire payloads.\n *\n * Rhino Compute branches serialize the same field in different casings. mcneel 8.x/9.x send the IO\n * schema PascalCase (`ParamType`, `Default`, `InnerTree`): those C# classes carry no\n * `[JsonProperty]`. The VektorNode fork sends camelCase, except inside the `default` DataTree\n * (`ParamName`, `InnerTree`), an external type it can't attribute. So one response can mix casings.\n * Read the fields you need through here and leave the rest verbatim: rewriting every key corrupts\n * user-authored ones such as value-list labels.\n */\n\n/** Own keys only: a payload probed for `constructor` must not find `Object.prototype`'s. */\nfunction findOwnKey(obj: unknown, name: string): string | undefined {\n\tif (!obj || typeof obj !== 'object') return undefined;\n\tif (Object.prototype.hasOwnProperty.call(obj, name)) return name;\n\tconst lower = name.toLowerCase();\n\treturn Object.keys(obj).find((key) => key.toLowerCase() === lower);\n}\n\n/**\n * Read `name` in any casing, preferring an exact-case match. `undefined` when no own key matches or\n * `obj` isn't an object.\n */\nexport function readField<T = unknown>(obj: unknown, name: string): T | undefined {\n\tconst key = findOwnKey(obj, name);\n\treturn key === undefined ? undefined : ((obj as Record<string, unknown>)[key] as T);\n}\n\n/** Whether `name` is present in any casing, even with a null or undefined value. */\nexport function hasField(obj: unknown, name: string): boolean {\n\treturn findOwnKey(obj, name) !== undefined;\n}\n","import { ComputeError, ErrorCodes } from '@/core/errors';\n\n/**\n * The public McNeel endpoint, blocked by default: users must point at their own server. Its raw IP\n * isn't blocked: it sits behind a load balancer with no stable address to pin.\n */\nexport const DEFAULT_BLOCKED_HOST = 'compute.rhino3d.com';\n\nexport interface ValidateServerUrlOptions {\n\t/**\n\t * Hostnames rejected as a `serverUrl` — a backend's shared public endpoint,\n\t * which callers must not point at. Defaults to `[DEFAULT_BLOCKED_HOST]`; pass\n\t * `[]` to block nothing. Compared lowercased with any trailing dot stripped.\n\t */\n\tblockedHosts?: readonly string[];\n}\n\n/**\n * Validate a compute `serverUrl` and return it trimmed, without trailing slashes. Every entry point\n * that takes a server URL calls this, so a URL is accepted or rejected the same way everywhere.\n *\n * @throws {ComputeError} `INVALID_CONFIG` when the URL is empty, isn't http(s), doesn't parse,\n * embeds credentials, has a query or fragment, or names a blocked host.\n */\nexport function validateServerUrl(raw: string, options?: ValidateServerUrlOptions): string {\n\tconst trimmed = raw?.trim() ?? '';\n\tif (!trimmed) {\n\t\tthrow new ComputeError('serverUrl is required', ErrorCodes.INVALID_CONFIG, {\n\t\t\tcontext: { receivedServerUrl: raw }\n\t\t});\n\t}\n\n\tconst invalid = (reason: string, originalError?: unknown) =>\n\t\tnew ComputeError(`Invalid serverUrl: \"${trimmed}\". ${reason}`, ErrorCodes.INVALID_CONFIG, {\n\t\t\tcontext: { receivedServerUrl: raw },\n\t\t\toriginalError\n\t\t});\n\n\tif (!/^https?:\\/\\//i.test(trimmed)) {\n\t\tthrow invalid(\n\t\t\t'Must start with \"http://\" or \"https://\". ' +\n\t\t\t\t'For example: \"http://localhost:6500\" or \"https://example.com\"'\n\t\t);\n\t}\n\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(trimmed);\n\t} catch (err) {\n\t\tthrow invalid(\n\t\t\t`Must be a valid URL. Received error: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\terr\n\t\t);\n\t}\n\n\tif (parsed.username !== '' || parsed.password !== '') {\n\t\tthrow invalid(\n\t\t\t'Must not embed credentials (user:pass@host) — ' +\n\t\t\t\t'fetch rejects credentialed URLs at request time. Pass the API key separately.'\n\t\t);\n\t}\n\n\t// A string check: a bare trailing \"?\" or \"#\" parses to an empty search/hash but still corrupts\n\t// the endpoint paths appended to this URL.\n\tif (trimmed.includes('?') || trimmed.includes('#')) {\n\t\tthrow invalid(\n\t\t\t'Must not contain a query string or fragment — ' +\n\t\t\t\t'endpoint paths are appended to this URL (e.g. \"${serverUrl}/version\"), ' +\n\t\t\t\t'and a \"?\" or \"#\" suffix would corrupt every request path.'\n\t\t);\n\t}\n\n\t// Lowercase + strip any trailing dot so the FQDN form can't bypass the block.\n\tconst hostname = parsed.hostname.toLowerCase().replace(/\\.+$/, '');\n\tconst blocked = (options?.blockedHosts ?? [DEFAULT_BLOCKED_HOST]).map((h) =>\n\t\th.toLowerCase().replace(/\\.+$/, '')\n\t);\n\tif (blocked.includes(hostname)) {\n\t\tthrow new ComputeError(\n\t\t\t'serverUrl must be set to your Compute server URL. The shared public endpoint is not allowed.',\n\t\t\tErrorCodes.INVALID_CONFIG,\n\t\t\t{ context: { receivedServerUrl: raw } }\n\t\t);\n\t}\n\n\treturn trimmed.replace(/\\/+$/, '');\n}\n","import { getLogger } from '../utils/logger';\n\nimport type { ComputeAuth, ComputeConfig } from '../types';\n\nexport function buildUrl(endpoint: string, serverUrl: string): string {\n\tconst base = serverUrl.replace(/\\/+$/, '');\n\tconst path = endpoint.replace(/^\\/+/, '');\n\treturn `${base}/${path}`;\n}\n\nfunction isLocalhost(serverUrl: string): boolean {\n\ttry {\n\t\t// `hostname` (not `host`) strips the port; IPv6 hostnames keep their\n\t\t// brackets, so `http://[::1]:6500` yields `[::1]`.\n\t\tconst hostname = new URL(serverUrl).hostname.toLowerCase();\n\t\treturn hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';\n\t} catch {\n\t\treturn /(localhost|127\\.0\\.0\\.1|\\[::1\\])/i.test(serverUrl);\n\t}\n}\n\n/** Server URLs already warned about missing auth — warn once per server, not per request. */\nconst warnedNoAuth = new Set<string>();\n\nconst DEFAULT_API_KEY_HEADER = 'RhinoComputeKey';\n\n/**\n * Caller headers plus credentials. Every request to the server builds its headers here,\n * so a liveness probe authenticates exactly like the solve it gates.\n */\nexport function buildAuthHeaders(auth: ComputeAuth): Record<string, string> {\n\treturn mergeUnder(auth.headers, credentialHeaders(auth));\n}\n\nexport function buildHeaders(requestId: string, config: ComputeConfig): HeadersInit {\n\tconst headers = mergeUnder(config.headers, {\n\t\t...credentialHeaders(config),\n\t\t'X-Request-ID': requestId,\n\t\t'Content-Type': 'application/json'\n\t});\n\n\tif (\n\t\t!config.apiKey &&\n\t\t!config.authToken &&\n\t\t!warnedNoAuth.has(config.serverUrl) &&\n\t\t!isLocalhost(config.serverUrl)\n\t) {\n\t\twarnedNoAuth.add(config.serverUrl);\n\t\tgetLogger().warn(\n\t\t\t`⚠️ [Compute] Request [${requestId}] targets remote server (${config.serverUrl}) but no API key or auth token is configured. Requests may fail or be rate-limited. (warned once per server)`\n\t\t);\n\t}\n\n\treturn headers;\n}\n\nfunction credentialHeaders(auth: ComputeAuth): Record<string, string> {\n\treturn {\n\t\t...(auth.authToken && { Authorization: auth.authToken }),\n\t\t...(auth.apiKey && { [auth.apiKeyHeader ?? DEFAULT_API_KEY_HEADER]: auth.apiKey })\n\t};\n}\n\n/**\n * Header names are case-insensitive and fetch joins duplicates, so a caller key\n * matching a transport key in any case is dropped rather than sent alongside it.\n */\nfunction mergeUnder(\n\tcaller: Record<string, string> | undefined,\n\ttransport: Record<string, string>\n): Record<string, string> {\n\tconst taken = new Set(Object.keys(transport).map((name) => name.toLowerCase()));\n\tconst kept = Object.entries(caller ?? {}).filter(([name]) => !taken.has(name.toLowerCase()));\n\treturn { ...Object.fromEntries(kept), ...transport };\n}\n\nexport function generateRequestId(): string {\n\treturn `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","/**\n * Why a liveness probe failed, and whether waiting can change the answer.\n *\n * `retryable` is the whole point: a powered-off VM and a booting one both read\n * as \"offline\" from a single probe, but only one of them will ever come up. A\n * caller that can't tell them apart has to assume the optimistic case and burn\n * its full retry window on a machine that is simply off.\n */\nexport type ProbeVerdict =\n\t/** Nothing is listening on the port — the host answered, and said no. */\n\t| 'refused'\n\t/** The hostname does not resolve. */\n\t| 'dns'\n\t/** No answer within the timeout: a booting host swallows packets rather than refusing them. */\n\t| 'timeout'\n\t/** The server answered, but rejected the probe's credentials (401/403). */\n\t| 'unauthorized'\n\t/** The server answered with a non-2xx that isn't an auth rejection. */\n\t| 'http_error'\n\t/** Connection failed in a way we can't attribute. */\n\t| 'unknown';\n\nexport interface ProbeFailure {\n\tverdict: ProbeVerdict;\n\t/** Whether retrying the same probe could plausibly succeed later. */\n\tretryable: boolean;\n\t/** Operator-facing sentence. Never includes the API key. */\n\tsummary: string;\n}\n\n/**\n * `ECONNREFUSED` arrives spelled differently depending on the runtime and how\n * many layers wrapped it: Node puts the code on the error, undici nests it under\n * `cause`, and browsers collapse everything into an opaque \"Failed to fetch\".\n * Matching the stringified probe error covers all of them without the caller\n * having to normalize first.\n */\nconst REFUSED_PATTERN = /ECONNREFUSED|ERR_CONNECTION_REFUSED|connection refused/i;\nconst DNS_PATTERN = /ENOTFOUND|EAI_AGAIN|getaddrinfo|ERR_NAME_NOT_RESOLVED|dns/i;\nconst TIMEOUT_PATTERN =\n\t/TimeoutError|ETIMEDOUT|ECONNRESET|EHOSTUNREACH|ENETUNREACH|abort|timed? ?out/i;\n\n/**\n * Classify a {@link ComputeServerStats.probeServer} result.\n *\n * A DNS failure is treated as retryable even though a missing record won't fix\n * itself: `EAI_AGAIN` is a *timeout* talking to the resolver, and the two are\n * not distinguishable from the error alone. Retrying a genuinely-wrong hostname\n * costs one window; giving up on a resolver hiccup breaks a server that is fine.\n *\n * @param probe - The `{ online, status?, error? }` a probe returned. An `online`\n * probe is not a failure and yields `null`.\n */\nexport function classifyProbeFailure(probe: {\n\tonline: boolean;\n\tstatus?: number;\n\terror?: string;\n}): ProbeFailure | null {\n\tif (probe.online) return null;\n\n\tif (probe.status !== undefined) {\n\t\tif (probe.status === 401 || probe.status === 403) {\n\t\t\treturn {\n\t\t\t\tverdict: 'unauthorized',\n\t\t\t\tretryable: false,\n\t\t\t\tsummary: `The server rejected the liveness probe with HTTP ${probe.status} — check the API key.`\n\t\t\t};\n\t\t}\n\t\t// 5xx from a proxy in front of a starting child does clear on its own;\n\t\t// a 4xx means we asked for something this server will never serve.\n\t\tconst retryable = probe.status >= 500;\n\t\treturn {\n\t\t\tverdict: 'http_error',\n\t\t\tretryable,\n\t\t\tsummary: retryable\n\t\t\t\t? `The server answered HTTP ${probe.status} — it may still be starting up.`\n\t\t\t\t: `The server answered HTTP ${probe.status}, which will not change on retry.`\n\t\t};\n\t}\n\n\tconst error = probe.error ?? '';\n\n\tif (REFUSED_PATTERN.test(error)) {\n\t\treturn {\n\t\t\tverdict: 'refused',\n\t\t\tretryable: false,\n\t\t\tsummary:\n\t\t\t\t'Connection refused — the host is reachable but nothing is listening on that port. ' +\n\t\t\t\t'Rhino.Compute is not running, or the URL names the wrong port.'\n\t\t};\n\t}\n\n\tif (DNS_PATTERN.test(error)) {\n\t\treturn {\n\t\t\tverdict: 'dns',\n\t\t\tretryable: true,\n\t\t\tsummary: 'The server hostname could not be resolved — check the URL and DNS.'\n\t\t};\n\t}\n\n\tif (TIMEOUT_PATTERN.test(error)) {\n\t\treturn {\n\t\t\tverdict: 'timeout',\n\t\t\tretryable: true,\n\t\t\tsummary:\n\t\t\t\t'No response before the timeout — the machine may be powered off, blocked by a ' +\n\t\t\t\t'firewall, or still booting.'\n\t\t};\n\t}\n\n\treturn {\n\t\tverdict: 'unknown',\n\t\tretryable: true,\n\t\tsummary: error ? `The connection failed: ${error}` : 'The connection failed.'\n\t};\n}\n","import { ComputeError, ErrorCodes } from '../errors';\n\nfunction getNodeBuffer(): typeof Buffer | undefined {\n\tconst buf = (globalThis as { Buffer?: typeof Buffer }).Buffer;\n\treturn typeof buf === 'function' ? buf : undefined;\n}\n\nexport function encodeStringToBase64(str: string): string {\n\tconst Buffer = getNodeBuffer();\n\tif (Buffer) {\n\t\treturn Buffer.from(str, 'utf-8').toString('base64');\n\t}\n\treturn base64ByteArray(new TextEncoder().encode(str));\n}\n\n/**\n * WHATWG forgiving-base64 normalization: strip ASCII whitespace, then drop trailing padding where\n * the spec allows it (total length a multiple of 4). `null` when the result can't be base64.\n */\nfunction normalizeBase64(str: string): string | null {\n\tlet data = str.replace(/[\\t\\n\\f\\r ]/g, '');\n\tif (data.length % 4 === 0) data = data.replace(/={1,2}$/, '');\n\treturn data.length % 4 === 1 || !/^[A-Za-z0-9+/]*$/.test(data) ? null : data;\n}\n\n/** Shortest string treated as base64 (≈ 48 bytes): human-written strings rarely reach it. */\nexport const BASE64_DETECT_MIN_LENGTH = 64;\n\nconst B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n/**\n * Whether an untyped string is base64 content: the canonical padded form when confident, else\n * `null` (treat it as plain text). A heuristic; pass a `Uint8Array` when it must be exact.\n */\nexport function detectBase64Payload(str: string): string | null {\n\tconst data = normalizeBase64(str);\n\tif (data === null || data.length < BASE64_DETECT_MIN_LENGTH) return null;\n\n\t// An encoder leaves the final character's unused low bits zero; otherwise re-encoding the\n\t// decoded bytes wouldn't reproduce the input.\n\tconst rem = data.length % 4;\n\tconst lastValue = B64_ALPHABET.indexOf(data.charAt(data.length - 1));\n\tif (rem === 2 && (lastValue & 0x0f) !== 0) return null;\n\tif (rem === 3 && (lastValue & 0x03) !== 0) return null;\n\n\treturn rem === 0 ? data : data + '=='.slice(0, 4 - rem);\n}\n\n/**\n * Decode base64 to bytes, normalizing and validating the same way in Node and browsers.\n * `packages/visualization/src/shared/encoding.ts` keeps a copy that throws its own error class;\n * change both together.\n *\n * @throws {ComputeError} `ENCODING_ERROR` if invalid, or `ENVIRONMENT_ERROR` if the runtime has no decoder\n */\nexport function decodeBase64ToBinary(base64File: string): Uint8Array {\n\tconst data = normalizeBase64(base64File);\n\tif (data === null) {\n\t\tthrow new ComputeError('Invalid base64 input.', ErrorCodes.ENCODING_ERROR, {\n\t\t\tcontext: { inputLength: base64File.length }\n\t\t});\n\t}\n\n\t// Buffer over atob in Node: faster, and skips the latin-1 string detour.\n\tconst Buffer = getNodeBuffer();\n\tif (Buffer) {\n\t\t// Copy out: a small Buffer.from result is a view over Node's shared 8 KiB pool slab, and\n\t\t// returning it would expose unrelated pooled bytes to anyone touching `.buffer`.\n\t\treturn new Uint8Array(Buffer.from(data, 'base64'));\n\t}\n\tif (typeof globalThis.atob === 'function') {\n\t\tconst binary = globalThis.atob(data);\n\t\tconst bytes = new Uint8Array(binary.length);\n\t\tfor (let i = 0; i < binary.length; i++) {\n\t\t\tbytes[i] = binary.charCodeAt(i) & 0xff;\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tthrow new ComputeError(\n\t\t'Base64 decoding not supported in this environment.',\n\t\tErrorCodes.ENVIRONMENT_ERROR,\n\t\t{ context: { environmentInfo: 'atob or Buffer not available' } }\n\t);\n}\n\n/** UTF-8 byte length without allocating the encoded copy `TextEncoder.encode` would. */\nexport function utf8ByteLength(str: string): number {\n\tconst Buffer = getNodeBuffer();\n\tif (Buffer) {\n\t\treturn Buffer.byteLength(str, 'utf-8');\n\t}\n\tlet bytes = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst code = str.charCodeAt(i);\n\t\tif (code < 0x80) {\n\t\t\tbytes += 1;\n\t\t} else if (code < 0x800) {\n\t\t\tbytes += 2;\n\t\t} else if (\n\t\t\tcode >= 0xd800 &&\n\t\t\tcode <= 0xdbff &&\n\t\t\ti + 1 < str.length &&\n\t\t\t(str.charCodeAt(i + 1) & 0xfc00) === 0xdc00\n\t\t) {\n\t\t\t// Surrogate pair → one 4-byte code point; lone surrogates fall through\n\t\t\t// to 3 bytes (the replacement-character encoding TextEncoder emits).\n\t\t\tbytes += 4;\n\t\t\ti++;\n\t\t} else {\n\t\t\tbytes += 3;\n\t\t}\n\t}\n\treturn bytes;\n}\n\nexport function base64ByteArray(bytes: Uint8Array): string {\n\tconst Buffer = getNodeBuffer();\n\tif (Buffer) {\n\t\treturn Buffer.from(bytes).toString('base64');\n\t}\n\tif (typeof globalThis.btoa === 'function') {\n\t\t// Chunked so memory doesn't peak at ~3× the input. CHUNK must be a multiple of 3: every\n\t\t// non-final chunk then encodes without padding, and the joined pieces equal a one-shot\n\t\t// encode. 32766 = 3 × 10922, well under fromCharCode.apply's argument limit.\n\t\tconst CHUNK = 32766;\n\t\tconst parts: string[] = [];\n\t\tfor (let i = 0; i < bytes.length; i += CHUNK) {\n\t\t\tparts.push(\n\t\t\t\tglobalThis.btoa(\n\t\t\t\t\tString.fromCharCode.apply(null, bytes.subarray(i, i + CHUNK) as unknown as number[])\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\t\treturn parts.join('');\n\t}\n\tthrow new ComputeError(\n\t\t'Base64 encoding not supported in this environment.',\n\t\tErrorCodes.ENVIRONMENT_ERROR,\n\t\t{ context: { environmentInfo: 'btoa or Buffer not available' } }\n\t);\n}\n","import { getLogger } from '../utils/logger';\n\nimport type { ServerTiming } from '../types';\n\n/**\n * Parse a W3C Server Timing header, as the solve endpoint emits it:\n * `decode;dur=3, solve;dur=120, encode;dur=8`. Null when it carries no recognised metric.\n */\nexport function parseServerTiming(headerValue: string | null): ServerTiming | null {\n\tif (!headerValue) return null;\n\tconst timing: ServerTiming = { raw: headerValue };\n\tlet sawMetric = false;\n\tfor (const part of headerValue.split(',')) {\n\t\tconst [name, ...params] = part.trim().split(';');\n\t\tconst durParam = params.find((p) => p.trim().toLowerCase().startsWith('dur'));\n\t\tif (!durParam) continue;\n\t\tconst dur = Number(durParam.split('=')[1]);\n\t\tif (!Number.isFinite(dur)) continue;\n\t\tconst key = name.trim().toLowerCase();\n\t\tif (key === 'decode' || key === 'solve' || key === 'encode') {\n\t\t\ttiming[key] = dur;\n\t\t\tsawMetric = true;\n\t\t}\n\t}\n\treturn sawMetric ? timing : null;\n}\n\nexport function fireServerTiming(\n\tresponse: Response,\n\trequestId: string,\n\tonServerTiming: ((timing: ServerTiming, requestId: string) => void) | undefined,\n\tdebug?: boolean\n): void {\n\tif (!onServerTiming) return;\n\tconst timing = parseServerTiming(response.headers.get('Server-Timing'));\n\tif (!timing) return;\n\ttry {\n\t\tonServerTiming(timing, requestId);\n\t} catch (err) {\n\t\tif (debug) getLogger().debug(` onServerTiming callback threw: ${err}`);\n\t}\n}\n","/** What fetch, or a body read, rejects with when its signal fires: a caller abort or a timeout. */\nexport function isAbortError(error: unknown): error is Error {\n\treturn error instanceof Error && (error.name === 'AbortError' || error.name === 'TimeoutError');\n}\n\n/**\n * Compose a caller-supplied AbortSignal with an optional timeout; `undefined` when neither was\n * given. `AbortSignal.timeout` rather than `setTimeout`: its timer isn't throttled in a hidden tab.\n */\nexport function composeSignal(\n\tcallerSignal: AbortSignal | undefined,\n\ttimeoutMs: number | undefined\n): { signal: AbortSignal | undefined; cleanup: () => void } {\n\tconst noCleanup = () => {};\n\tif (typeof timeoutMs !== 'number' || timeoutMs <= 0) {\n\t\treturn { signal: callerSignal, cleanup: noCleanup };\n\t}\n\n\tconst timeoutSignal = AbortSignal.timeout(timeoutMs);\n\tif (!callerSignal) return { signal: timeoutSignal, cleanup: noCleanup };\n\n\t// Not AbortSignal.any: it can't unregister its link on the caller's signal, so a long-lived\n\t// signal reused across solves would collect one registration per attempt.\n\tconst ctrl = new AbortController();\n\tconst sources = [callerSignal, timeoutSignal];\n\t// Forwarding the reason keeps fetch's rejection name ('TimeoutError' vs 'AbortError').\n\tconst onAbort = function (this: AbortSignal) {\n\t\tctrl.abort(this.reason);\n\t};\n\n\tfor (const s of sources) {\n\t\tif (s.aborted) {\n\t\t\tctrl.abort(s.reason);\n\t\t\tbreak;\n\t\t}\n\t\ts.addEventListener('abort', onAbort, { once: true });\n\t}\n\n\treturn {\n\t\tsignal: ctrl.signal,\n\t\tcleanup: () => {\n\t\t\tfor (const s of sources) s.removeEventListener('abort', onAbort);\n\t\t}\n\t};\n}\n","/**\n * A response's JSON text length, so byte-budgeted caches never re-serialize a huge tree. A WeakMap\n * rather than a field keeps `JSON.stringify(response)` clean; it is keyed by identity, so a derived\n * copy must re-register. `.length` stands in for UTF-8 bytes: the JSON is near-pure ASCII.\n */\n\nconst wireSizes = new WeakMap<object, number>();\n\n/** Record `response`'s wire size. No-op for non-object/null values. */\nexport function setResponseWireSize(response: unknown, size: number): void {\n\tif (typeof response !== 'object' || response === null) return;\n\twireSizes.set(response, size);\n}\n\n/** The wire size recorded for `response`, or undefined when never registered. */\nexport function getResponseWireSize(response: unknown): number | undefined {\n\tif (typeof response !== 'object' || response === null) return undefined;\n\treturn wireSizes.get(response);\n}\n","import { ComputeError, ErrorCodes, type ErrorCode } from '../errors';\nimport { getLogger } from '../utils/logger';\nimport { readField } from '../utils/read-field';\nimport { fireServerTiming } from './server-timing';\nimport { isAbortError } from './signal';\nimport { setResponseWireSize } from './wire-size';\n\nimport type { ComputeConfig } from '../types';\n\nexport interface RequestContext {\n\tfullUrl: string;\n\trequestId: string;\n\trequestSize: number;\n\tconfig: ComputeConfig;\n}\n\n/** Upper bound for the raw server body stored on error `context.responseBody`. */\nconst MAX_CONTEXT_BODY_CHARS = 4096;\n\nfunction truncateBody(body: string): string {\n\tif (body.length <= MAX_CONTEXT_BODY_CHARS) return body;\n\treturn `${body.slice(0, MAX_CONTEXT_BODY_CHARS)}… [truncated ${body.length - MAX_CONTEXT_BODY_CHARS} chars]`;\n}\n\n/**\n * `rawBody` is what came over the wire and goes on `context.responseBody`; `detail` may be a\n * message rewritten from it and only feeds the error message.\n */\nfunction throwHttpError(\n\tresponse: Response,\n\tctx: RequestContext,\n\trawBody: string,\n\tdetail: string,\n\tserverCode: string | undefined\n): never {\n\tconst { status, statusText } = response;\n\tconst { fullUrl, requestId, requestSize, config } = ctx;\n\n\tconst responseHeaders: Record<string, string> = {};\n\tresponse.headers.forEach((value, key) => {\n\t\tresponseHeaders[key] = value;\n\t});\n\n\tconst trimmed = detail.trim();\n\tconst bodyHint = trimmed ? ` — ${trimmed.slice(0, 200)}${trimmed.length > 200 ? '…' : ''}` : '';\n\n\tconst context = {\n\t\turl: fullUrl,\n\t\trequestId,\n\t\tmethod: 'POST',\n\t\trequestSize,\n\t\tserverUrl: config.serverUrl,\n\t\tresponseBody: rawBody ? truncateBody(rawBody) : undefined,\n\t\tresponseHeaders\n\t};\n\n\tconst errorMap: Record<number, { message: string; code: ErrorCode }> = {\n\t\t400: {\n\t\t\tmessage: `Bad request: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.VALIDATION_ERROR\n\t\t},\n\t\t401: { message: `HTTP ${status}: ${statusText}${bodyHint}`, code: ErrorCodes.AUTH_ERROR },\n\t\t403: { message: `HTTP ${status}: ${statusText}${bodyHint}`, code: ErrorCodes.AUTH_ERROR },\n\t\t404: { message: `Endpoint not found: ${fullUrl}`, code: ErrorCodes.NOT_FOUND },\n\t\t413: {\n\t\t\tmessage: `Request too large: ${(requestSize / 1024).toFixed(2)}KB`,\n\t\t\tcode: ErrorCodes.VALIDATION_ERROR\n\t\t},\n\t\t429: { message: `Rate limit exceeded${bodyHint}`, code: ErrorCodes.RATE_LIMIT },\n\t\t500: { message: `Server error: ${statusText}${bodyHint}`, code: ErrorCodes.COMPUTATION_ERROR },\n\t\t502: {\n\t\t\tmessage: `Bad gateway: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.NETWORK_ERROR\n\t\t},\n\t\t503: {\n\t\t\tmessage: `Service unavailable: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.NETWORK_ERROR\n\t\t},\n\t\t504: {\n\t\t\tmessage: `Gateway timeout: ${statusText}${bodyHint}`,\n\t\t\tcode: ErrorCodes.NETWORK_ERROR\n\t\t}\n\t};\n\n\tconst error = errorMap[status] || {\n\t\tmessage: `HTTP ${status}: ${statusText}${bodyHint}`,\n\t\tcode: ErrorCodes.UNKNOWN_ERROR\n\t};\n\n\tconst codes = config.serverErrorCodes;\n\t// The code is server-supplied: `constructor` must not resolve through the prototype.\n\tconst serverMapped =\n\t\tserverCode && codes && Object.prototype.hasOwnProperty.call(codes, serverCode)\n\t\t\t? codes[serverCode]\n\t\t\t: undefined;\n\n\tthrow new ComputeError(error.message, serverMapped ?? error.code, {\n\t\tstatusCode: status,\n\t\tcontext\n\t});\n}\n\nexport async function handleResponse(\n\tresponse: Response,\n\tctx: RequestContext,\n\tstartTime: number\n): Promise<unknown> {\n\tconst { requestId, config } = ctx;\n\tconst { debug, onServerTiming } = config;\n\tconst responseTime = Math.round(performance.now() - startTime);\n\n\tif (!response.ok) {\n\t\tconst rawBody = await response.text();\n\n\t\tif (debug) {\n\t\t\tconst logger = getLogger();\n\t\t\tlogger.debug(\n\t\t\t\t`❌ Request [${requestId}] failed with HTTP ${response.status} in ${responseTime}ms`\n\t\t\t);\n\t\t\tlogger.debug(` URL: ${ctx.fullUrl}`);\n\t\t\tlogger.debug(` Status: ${response.status} ${response.statusText}`);\n\t\t\tif (rawBody) {\n\t\t\t\tlogger.debug(\n\t\t\t\t\t` Response body: ${rawBody.substring(0, 500)}${rawBody.length > 500 ? '...' : ''}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tlet parsed: any;\n\t\tlet isJson = true;\n\t\ttry {\n\t\t\tparsed = JSON.parse(rawBody);\n\t\t} catch (e) {\n\t\t\tisJson = false;\n\t\t\tif (debug && response.status === 500) {\n\t\t\t\tgetLogger().debug(` Failed to parse error body as JSON: ${e}`);\n\t\t\t}\n\t\t}\n\n\t\t// Any error status can carry a `code`, not just 500.\n\t\tconst serverCode: string | undefined =\n\t\t\ttypeof parsed?.code === 'string' ? parsed.code : undefined;\n\t\tlet detail = rawBody;\n\n\t\tif (response.status === 500 && isJson) {\n\t\t\t// Values plus errors or warnings: the solve ran, so this is a partial success.\n\t\t\tconst values = readField(parsed, 'values');\n\t\t\tconst solveErrors = readField<unknown[]>(parsed, 'errors');\n\t\t\tconst solveWarnings = readField<unknown[]>(parsed, 'warnings');\n\t\t\tif (values && (solveErrors || solveWarnings)) {\n\t\t\t\tsetResponseWireSize(parsed, rawBody.length);\n\t\t\t\tif (debug) {\n\t\t\t\t\tconst logger = getLogger();\n\t\t\t\t\tlogger.debug(\n\t\t\t\t\t\t`⚠️ Request [${requestId}] completed with solver errors in ${responseTime}ms`\n\t\t\t\t\t);\n\t\t\t\t\tif (solveErrors && solveErrors.length > 0) {\n\t\t\t\t\t\tlogger.debug(` Errors: ${JSON.stringify(solveErrors, null, 2)}`);\n\t\t\t\t\t}\n\t\t\t\t\tif (solveWarnings && solveWarnings.length > 0) {\n\t\t\t\t\t\tlogger.debug(` Warnings: ${JSON.stringify(solveWarnings, null, 2)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfireServerTiming(response, requestId, onServerTiming, debug);\n\t\t\t\treturn parsed;\n\t\t\t}\n\n\t\t\t// Compute8's exception handler sends `{ error, message: \"<category>: <detail>\",\n\t\t\t// stackTrace? }`; older servers sent PascalCase `Message`/`ExceptionType`/`StackTrace`.\n\t\t\tconst serverMessage =\n\t\t\t\t(typeof parsed?.message === 'string' && parsed.message) ||\n\t\t\t\t(typeof parsed?.Message === 'string' && parsed.Message) ||\n\t\t\t\t'';\n\t\t\tconst exceptionType =\n\t\t\t\t(typeof parsed?.ExceptionType === 'string' && parsed.ExceptionType) || '';\n\t\t\tconst stack = parsed?.stackTrace ?? parsed?.StackTrace;\n\t\t\tconst stackStr = Array.isArray(stack) ? stack.join('\\n') : stack || '';\n\n\t\t\tif (serverMessage) {\n\t\t\t\tconst prefix = exceptionType ? `${exceptionType}: ` : '';\n\t\t\t\tdetail = `${prefix}${serverMessage}${stackStr ? `\\n${stackStr}` : ''}`;\n\t\t\t} else if (parsed?.error) {\n\t\t\t\tdetail =\n\t\t\t\t\ttypeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error, null, 2);\n\t\t\t}\n\t\t}\n\n\t\tthrowHttpError(response, ctx, rawBody, detail, serverCode);\n\t}\n\n\tif (debug) getLogger().debug(`✅ Request [${requestId}] completed in ${responseTime}ms`);\n\n\tfireServerTiming(response, requestId, onServerTiming, debug);\n\n\ttry {\n\t\t// Text, then parse, so the wire size rides along for byte-budgeted caches.\n\t\tconst rawBody = await response.text();\n\t\tconst parsed = JSON.parse(rawBody);\n\t\tsetResponseWireSize(parsed, rawBody.length);\n\t\treturn parsed;\n\t} catch (error) {\n\t\t// The signal stays armed while the body streams: an abort here is the caller's or the\n\t\t// timeout's, not a truncated body.\n\t\tif (isAbortError(error)) throw error;\n\t\t// A declared non-JSON body (captive portal, proxy login page) comes back identical on a\n\t\t// retry. Anything else that fails to parse was most likely cut off mid-stream.\n\t\tconst contentType = (response.headers.get('Content-Type') ?? '').toLowerCase();\n\t\tconst declaredNonJson = contentType !== '' && !contentType.includes('json');\n\t\tif (declaredNonJson) {\n\t\t\tthrow new ComputeError(\n\t\t\t\t`Server returned a non-JSON response (Content-Type: ${contentType}) — check the server URL / proxy configuration`,\n\t\t\t\tErrorCodes.INVALID_RESPONSE,\n\t\t\t\t{\n\t\t\t\t\tstatusCode: response.status,\n\t\t\t\t\tcontext: { url: ctx.fullUrl, requestId, contentType },\n\t\t\t\t\toriginalError: error\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t\tthrow new ComputeError('Failed to parse JSON response', ErrorCodes.NETWORK_ERROR, {\n\t\t\tstatusCode: response.status,\n\t\t\tcontext: { url: ctx.fullUrl, requestId },\n\t\t\toriginalError: error\n\t\t});\n\t}\n}\n","import type { RetryPolicy } from '../types';\n\nconst DEFAULT_RETRY: Required<RetryPolicy> = {\n\tattempts: 0,\n\tbaseDelayMs: 500,\n\tmaxDelayMs: 30_000,\n\tretryOn429: true\n};\n\nconst RETRYABLE_STATUS = new Set([502, 503, 504]);\n\n/**\n * Ceiling on a server-sent `Retry-After` wait. The server's window outranks\n * `RetryPolicy.maxDelayMs` (retrying sooner all but guarantees another 429), but a bad or hostile\n * header must not park the client for minutes. A `maxDelayMs` above this cap raises it.\n */\nconst RETRY_AFTER_CAP_MS = 60_000;\n\nexport function resolveRetryPolicy(policy: RetryPolicy | undefined): Required<RetryPolicy> {\n\tif (!policy) return DEFAULT_RETRY;\n\treturn {\n\t\tattempts: policy.attempts ?? DEFAULT_RETRY.attempts,\n\t\tbaseDelayMs: policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs,\n\t\tmaxDelayMs: policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs,\n\t\tretryOn429: policy.retryOn429 ?? DEFAULT_RETRY.retryOn429\n\t};\n}\n\nexport function isRetryableStatus(status: number, policy: Required<RetryPolicy>): boolean {\n\treturn RETRYABLE_STATUS.has(status) || (policy.retryOn429 && status === 429);\n}\n\n/** Delay before the next attempt: the server's `Retry-After` when it sent one, else backoff. */\nexport function retryDelay(\n\tretryAfter: string | null,\n\tattempt: number,\n\tpolicy: Required<RetryPolicy>\n): number {\n\tconst retryAfterMs = parseRetryAfter(retryAfter);\n\treturn retryAfterMs === null\n\t\t? backoffDelay(attempt, policy)\n\t\t: Math.min(retryAfterMs, Math.max(policy.maxDelayMs, RETRY_AFTER_CAP_MS));\n}\n\n/** A `Retry-After` value (seconds or HTTP-date) in ms; null when missing or unparseable. */\nfunction parseRetryAfter(headerValue: string | null): number | null {\n\tif (!headerValue) return null;\n\tconst seconds = Number(headerValue);\n\tif (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n\tconst dateMs = Date.parse(headerValue);\n\tif (Number.isFinite(dateMs)) {\n\t\tconst delta = dateMs - Date.now();\n\t\treturn delta > 0 ? delta : 0;\n\t}\n\treturn null;\n}\n\nexport function backoffDelay(attempt: number, policy: Required<RetryPolicy>): number {\n\tconst exponential = policy.baseDelayMs * Math.pow(2, attempt);\n\tconst jitter = Math.random() * policy.baseDelayMs;\n\treturn Math.min(exponential + jitter, policy.maxDelayMs);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new DOMException('Aborted', 'AbortError'));\n\t\t\treturn;\n\t\t}\n\t\tconst id = setTimeout(() => {\n\t\t\tsignal?.removeEventListener('abort', onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(id);\n\t\t\treject(new DOMException('Aborted', 'AbortError'));\n\t\t};\n\t\tsignal?.addEventListener('abort', onAbort, { once: true });\n\t});\n}\n","import { ComputeError, ErrorCodes } from '../errors';\nimport { utf8ByteLength } from '../utils/encoding';\nimport { getLogger } from '../utils/logger';\nimport { buildUrl, buildHeaders, generateRequestId } from './request';\nimport { handleResponse, type RequestContext } from './response';\nimport { backoffDelay, isRetryableStatus, resolveRetryPolicy, retryDelay, sleep } from './retry';\nimport { composeSignal, isAbortError } from './signal';\n\nimport type { ComputeConfig, RetryPolicy } from '../types';\n\ninterface AttemptContext extends RequestContext {\n\tendpoint: string;\n\tbody: string;\n\theaders: HeadersInit;\n\terrorContext: Record<string, unknown>;\n}\n\ntype AttemptOutcome =\n\t| { ok: true; value: unknown }\n\t| { ok: false; cause: ComputeError; retryable: boolean; delayMs?: number };\n\nfunction abortedByCaller(ctx: AttemptContext, originalError: Error): ComputeError {\n\treturn new ComputeError('Request aborted by caller', ErrorCodes.ABORTED, {\n\t\tcontext: ctx.errorContext,\n\t\toriginalError\n\t});\n}\n\nasync function attemptFetch(\n\tctx: AttemptContext,\n\tpolicy: Required<RetryPolicy>,\n\tattempt: number,\n\tisFinal: boolean\n): Promise<AttemptOutcome> {\n\tconst { signal, cleanup } = composeSignal(ctx.config.signal, ctx.config.timeoutMs);\n\tconst startTime = performance.now();\n\n\ttry {\n\t\tconst response = await fetch(ctx.fullUrl, {\n\t\t\tmethod: 'POST',\n\t\t\tbody: ctx.body,\n\t\t\theaders: ctx.headers,\n\t\t\tsignal\n\t\t});\n\n\t\tif (!isFinal && isRetryableStatus(response.status, policy)) {\n\t\t\t// Drain so the connection can be reused. The final attempt skips this branch so\n\t\t\t// handleResponse reads the body into the error instead.\n\t\t\tawait response.text().catch(() => {});\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tretryable: true,\n\t\t\t\tdelayMs: retryDelay(response.headers.get('Retry-After'), attempt, policy),\n\t\t\t\tcause: new ComputeError(\n\t\t\t\t\t`HTTP ${response.status} ${response.statusText} (will retry)`,\n\t\t\t\t\tresponse.status === 429 ? ErrorCodes.RATE_LIMIT : ErrorCodes.NETWORK_ERROR,\n\t\t\t\t\t{ statusCode: response.status, context: ctx.errorContext }\n\t\t\t\t)\n\t\t\t};\n\t\t}\n\n\t\treturn { ok: true, value: await handleResponse(response, ctx, startTime) };\n\t} catch (error) {\n\t\treturn classifyFetchError(error, ctx);\n\t} finally {\n\t\tcleanup();\n\t}\n}\n\nfunction classifyFetchError(error: unknown, ctx: AttemptContext): AttemptOutcome {\n\tif (isAbortError(error)) {\n\t\tif (ctx.config.signal?.aborted) {\n\t\t\treturn { ok: false, retryable: false, cause: abortedByCaller(ctx, error) };\n\t\t}\n\t\t// With no timeout armed, the runtime aborted on its own (e.g. an undici socket teardown):\n\t\t// as transient as a network drop, but not a timeout.\n\t\tconst { timeoutMs } = ctx.config;\n\t\tconst cause =\n\t\t\ttypeof timeoutMs === 'number' && timeoutMs > 0\n\t\t\t\t? new ComputeError(`Request timed out after ${timeoutMs}ms`, ErrorCodes.TIMEOUT_ERROR, {\n\t\t\t\t\t\tcontext: { ...ctx.errorContext, timeoutMs },\n\t\t\t\t\t\toriginalError: error\n\t\t\t\t\t})\n\t\t\t\t: new ComputeError(\n\t\t\t\t\t\t`Request aborted by the runtime (${error.name}): ${error.message}`,\n\t\t\t\t\t\tErrorCodes.NETWORK_ERROR,\n\t\t\t\t\t\t{ context: ctx.errorContext, originalError: error }\n\t\t\t\t\t);\n\t\treturn { ok: false, retryable: true, cause };\n\t}\n\n\tif (error instanceof TypeError) {\n\t\t// In a browser an opaque fetch TypeError is most often CORS, which the browser hides by\n\t\t// design. An offline network throws the same error, so it stays retryable either way.\n\t\tconst inBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';\n\t\tconst cause = inBrowser\n\t\t\t? new ComputeError(\n\t\t\t\t\t`Request failed: ${error.message} — in a browser this usually means a CORS misconfiguration on the server (or a network failure; the browser does not distinguish them)`,\n\t\t\t\t\tErrorCodes.CORS_ERROR,\n\t\t\t\t\t{ context: ctx.errorContext, originalError: error }\n\t\t\t\t)\n\t\t\t: new ComputeError(`Network error: ${error.message}`, ErrorCodes.NETWORK_ERROR, {\n\t\t\t\t\tcontext: ctx.errorContext,\n\t\t\t\t\toriginalError: error\n\t\t\t\t});\n\t\treturn { ok: false, retryable: true, cause };\n\t}\n\n\tif (error instanceof ComputeError) {\n\t\t// From handleResponse: a 2xx NETWORK_ERROR is a body cut off mid-stream.\n\t\tconst status = error.statusCode;\n\t\tconst truncatedSuccess =\n\t\t\terror.code === ErrorCodes.NETWORK_ERROR &&\n\t\t\tstatus !== undefined &&\n\t\t\tstatus >= 200 &&\n\t\t\tstatus < 300;\n\t\treturn { ok: false, retryable: truncatedSuccess, cause: error };\n\t}\n\n\treturn {\n\t\tok: false,\n\t\tretryable: false,\n\t\tcause: new ComputeError(\n\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\tErrorCodes.UNKNOWN_ERROR,\n\t\t\t{\n\t\t\t\tcontext: ctx.errorContext,\n\t\t\t\toriginalError: error\n\t\t\t}\n\t\t)\n\t};\n}\n\n/**\n * POST `args` as JSON to `<serverUrl>/<endpoint>` with retry, timeout and abort handling, and\n * return the parsed response. Most callers want a higher-level API.\n *\n * `R` names the expected response shape; nothing checks it, so the default `unknown` forces a\n * narrowing.\n *\n * @example\n * const response = await fetchCompute('grasshopper', args, {\n * serverUrl: 'https://my-server.com',\n * timeoutMs: 30_000,\n * retry: { attempts: 2 },\n * signal: controller.signal\n * });\n */\nexport async function fetchCompute<R = unknown>(\n\tendpoint: string,\n\targs: Record<string, any>,\n\tconfig: ComputeConfig\n): Promise<R> {\n\tconst requestId = generateRequestId();\n\t// Fail a circular or BigInt payload as INVALID_INPUT, before anything touches the network.\n\tlet body: string;\n\ttry {\n\t\tbody = JSON.stringify(args);\n\t} catch (error) {\n\t\tthrow new ComputeError(\n\t\t\t`Request body is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\tErrorCodes.INVALID_INPUT,\n\t\t\t{\n\t\t\t\tcontext: { endpoint, requestId },\n\t\t\t\toriginalError: error\n\t\t\t}\n\t\t);\n\t}\n\t// UTF-8 bytes: `body.length` counts UTF-16 code units and undercounts non-ASCII payloads.\n\tconst requestSize = utf8ByteLength(body);\n\tconst fullUrl = buildUrl(endpoint, config.serverUrl);\n\tconst headers = buildHeaders(requestId, config);\n\tconst retryPolicy = resolveRetryPolicy(config.retry);\n\tconst totalAttempts = retryPolicy.attempts + 1;\n\n\tif (config.debug) {\n\t\tconst sizeKb = (requestSize / 1024).toFixed(2);\n\t\tconst emoji = requestSize > 100000 ? '⚠️' : '🚀';\n\t\tgetLogger().debug(\n\t\t\t`${emoji} Starting compute request [${requestId}]: ${endpoint} (${sizeKb}KB)`\n\t\t);\n\t}\n\n\tconst ctx: AttemptContext = {\n\t\tendpoint,\n\t\tbody,\n\t\trequestSize,\n\t\tfullUrl,\n\t\trequestId,\n\t\theaders,\n\t\tconfig,\n\t\terrorContext: { serverUrl: config.serverUrl, url: fullUrl, endpoint, requestId, requestSize }\n\t};\n\n\tfor (let attempt = 0; ; attempt++) {\n\t\tconst isFinal = attempt >= retryPolicy.attempts;\n\t\tconst result = await attemptFetch(ctx, retryPolicy, attempt, isFinal);\n\n\t\tif (result.ok) return result.value as R;\n\t\tif (isFinal || !result.retryable) throw result.cause;\n\n\t\tconst delayMs = result.delayMs ?? backoffDelay(attempt, retryPolicy);\n\t\tif (config.debug) {\n\t\t\tgetLogger().debug(\n\t\t\t\t`🔁 Request [${requestId}] retrying after ${delayMs}ms (attempt ${attempt + 2}/${totalAttempts}): ${result.cause.message}`\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tawait sleep(delayMs, config.signal);\n\t\t} catch {\n\t\t\tthrow abortedByCaller(ctx, result.cause);\n\t\t}\n\t}\n}\n","/** A definition identified by a stable key, with its bytes loaded only when an upload is unavoidable. */\nexport interface DefinitionRef {\n\t/**\n\t * Identity of immutable bytes, such as a version UUID; never a mutable name or path. Every\n\t * cache trusts the key without looking at the bytes, so two contents sharing a key are served\n\t * each other's solves, with no diagnostic.\n\t */\n\tkey: string;\n\t/** Called when the solve runs, not when it is scheduled: a solve aborted while queued never loads. */\n\tload: () => Promise<Uint8Array>;\n}\n\n/**\n * A URL is sent as a pointer, a string is uploaded as base64 (or encoded text), bytes are\n * uploaded as-is. Strings and bytes are content-hashed for caching; a `DefinitionRef` is keyed\n * by its `key`.\n */\nexport type SolveDefinition = string | Uint8Array | DefinitionRef;\n\nexport function isDefinitionRef(definition: SolveDefinition): definition is DefinitionRef {\n\treturn (\n\t\ttypeof definition === 'object' &&\n\t\t!(definition instanceof Uint8Array) &&\n\t\ttypeof definition.key === 'string' &&\n\t\ttypeof definition.load === 'function'\n\t);\n}\n\n/** A URL is already a server-side reference: it is never uploaded or keyed by server cache key. */\nexport function isDefinitionUrl(definition: SolveDefinition): definition is string {\n\treturn typeof definition === 'string' && /^https?:\\/\\//i.test(definition);\n}\n","import type { FileData } from './types';\n\n/**\n * The `Sub Folder` convention, as authored on Selva's Grasshopper file components.\n *\n * `::` nests, matching Rhino's layer separator (`ROOT::Panels`), and `/` and `\\` are accepted\n * because people type them out of habit. The plugin normalizes to `/` before sending, so these\n * helpers also cover payloads from an older plugin that still emit `::`.\n *\n * The first segment is the **root**, which names the archive rather than becoming a folder inside\n * it: `ROOT::Panels` downloads as `ROOT.zip` containing `Panels/…`. Files sharing a root travel\n * together; distinct roots produce separate archives.\n */\n\n/**\n * Split a `Sub Folder` value into folder segments; `/`, `\\` and `::` all separate.\n *\n * Exported because anything rendering a folder tree has to agree with the archive on where the\n * boundaries are — splitting on `/` alone leaves `Main::Panels` as one literal segment and shows\n * a folder named after the separator.\n */\nexport const subFolderSegments = (subFolder: string | undefined): string[] =>\n\t(subFolder ?? '')\n\t\t.replace(/::/g, '/')\n\t\t.replace(/\\\\/g, '/')\n\t\t.split('/')\n\t\t.map((segment) => segment.trim())\n\t\t.filter((segment) => segment !== '');\n\n/** First `Sub Folder` segment, or `''` when the file sits at the top level. */\nconst rootOf = (file: Pick<FileData, 'subFolder'>): string =>\n\tsubFolderSegments(file.subFolder)[0] ?? '';\n\n/**\n * Everything below the root, as a `/`-joined path. The root names the archive, so repeating it\n * inside would nest it twice.\n */\nexport const pathBelowRoot = (file: Pick<FileData, 'subFolder'>): string =>\n\tsubFolderSegments(file.subFolder).slice(1).join('/');\n\n/**\n * Group files by their `Sub Folder` root, preserving encounter order.\n *\n * Rootless files group under `''` — a caller naming archives supplies its own fallback for that\n * bucket. Useful beyond downloading: a consumer writing to disk gets the same grouping without\n * touching the DOM.\n */\nexport const groupFilesByRoot = <T extends Pick<FileData, 'subFolder'>>(\n\tfiles: readonly T[]\n): Array<{ root: string; files: T[] }> => {\n\tconst groups = new Map<string, T[]>();\n\n\tfor (const file of files) {\n\t\tconst root = rootOf(file);\n\t\tconst bucket = groups.get(root);\n\t\tif (bucket) bucket.push(file);\n\t\telse groups.set(root, [file]);\n\t}\n\n\treturn Array.from(groups, ([root, grouped]) => ({ root, files: grouped }));\n};\n\n/**\n * Make a root usable as a download filename: path separators and the characters Windows forbids\n * would otherwise reach the download attribute verbatim and produce a broken or misdirected save.\n */\nexport const toArchiveName = (root: string): string => {\n\tconst safe = root\n\t\t.replace(/[/\\\\:*?\"<>|]/g, '_')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim()\n\t\t.replace(/^\\.+/, '');\n\n\treturn safe === '' ? 'files' : safe;\n};\n","import { ComputeError, ErrorCodes } from '@/core/errors';\nimport { getLogger } from '@/core/utils/logger';\nimport { decodeBase64ToBinary } from '@/core/utils/encoding';\nimport { readField } from '@/core/utils/read-field';\n\nimport { FileBaseInfo, FileData, ProcessedFile } from './types';\nimport { groupFilesByRoot, pathBelowRoot, subFolderSegments, toArchiveName } from './sub-folder';\n\n/**\n * Decode the files in a compute response, plus any external `additionalFiles`, without\n * downloading them. Never throws: an unnamed or undecodable item and a failed external fetch are\n * logged and dropped, the rest still resolve. Colliding archive paths are renamed\n * (`model.txt` → `model-2.txt`), so a consumer keying by `path` loses nothing.\n */\nexport const extractFilesFromComputeResponse = async (\n\tdownloadableFiles: FileData[],\n\tadditionalFiles: FileBaseInfo[] | FileBaseInfo | null = null\n): Promise<ProcessedFile[]> => {\n\tconst processedFiles = decodeResponseFiles(downloadableFiles);\n\n\tif (additionalFiles) {\n\t\tconst filesArray = Array.isArray(additionalFiles) ? additionalFiles : [additionalFiles];\n\t\tprocessedFiles.push(...(await fetchRemoteFiles(filesArray)));\n\t}\n\n\tconst taken = new Set<string>();\n\treturn processedFiles.map((file) => {\n\t\tconst path = uniqueArchivePath(file.path, taken);\n\t\ttaken.add(path);\n\t\tif (path === file.path) return file;\n\t\tgetLogger().warn(`Duplicate archive path \"${file.path}\" — storing as \"${path}\".`);\n\t\treturn { ...file, path, fileName: path.slice(path.lastIndexOf('/') + 1) };\n\t});\n};\n\n/** Downloads files from a compute response as a ZIP archive. */\nexport const downloadFileData = async (\n\tdownloadableFiles: FileData[],\n\tfileFoldername: string,\n\tadditionalFiles: FileBaseInfo[] | FileBaseInfo | null = null\n): Promise<void> => {\n\tif (typeof document === 'undefined' || typeof Blob === 'undefined') {\n\t\tthrow new ComputeError(\n\t\t\t'File download functionality is only available in browser environments. This function requires the DOM API (document, Blob).',\n\t\t\tErrorCodes.BROWSER_ONLY,\n\t\t\t{\n\t\t\t\tcontext: {\n\t\t\t\t\tenvironment: typeof window !== 'undefined' ? 'browser (SSR)' : 'Node.js',\n\t\t\t\t\tdocumentAvailable: typeof document !== 'undefined',\n\t\t\t\t\tblobAvailable: typeof Blob !== 'undefined'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\ttry {\n\t\tconst processedFiles = await extractFilesFromComputeResponse(\n\t\t\tdownloadableFiles,\n\t\t\tadditionalFiles\n\t\t);\n\t\tawait createAndDownloadZip(processedFiles, fileFoldername);\n\t} catch (err) {\n\t\tif (err instanceof ComputeError) {\n\t\t\tthrow err;\n\t\t}\n\t\tthrow new ComputeError(\n\t\t\t'Failed to download files from compute response',\n\t\t\tErrorCodes.INVALID_STATE,\n\t\t\t{\n\t\t\t\tcontext: { originalError: err instanceof Error ? err.message : String(err) },\n\t\t\t\toriginalError: err\n\t\t\t}\n\t\t);\n\t}\n};\n\n/**\n * Download one archive per `Sub Folder` root (see {@link groupFilesByRoot}). Files with no root go\n * into `fallbackName`, so a definition that never sets `Sub Folder` downloads as one archive.\n *\n * Archives are saved one at a time: browsers discard concurrent downloads issued in the same tick.\n * More than one save per gesture may prompt the user for permission.\n *\n * @param downloadableFiles - `FileData` items from the compute response.\n * @param fallbackName - Archive name for files with no `Sub Folder` root.\n * @param additionalFiles - Extra files to package; they carry no root and join the fallback archive.\n */\nexport const downloadFileDataByRoot = async (\n\tdownloadableFiles: FileData[],\n\tfallbackName: string,\n\tadditionalFiles: FileBaseInfo[] | FileBaseInfo | null = null\n): Promise<void> => {\n\tconst groups = groupFilesByRoot(downloadableFiles);\n\n\t// Extras alone still deserve an archive; without this they'd be dropped for having no root.\n\tif (groups.length === 0) {\n\t\tawait downloadFileData([], fallbackName, additionalFiles);\n\t\treturn;\n\t}\n\n\t// Extras belong to the definition rather than to any one root, so they ride with the rootless\n\t// archive — or with the first one when every file is rooted, rather than being dropped.\n\tconst extrasRoot = (groups.find((group) => group.root === '') ?? groups[0]).root;\n\n\tfor (const { root, files } of groups) {\n\t\tawait downloadFileData(\n\t\t\troot === '' ? files : files.map((file) => ({ ...file, subFolder: pathBelowRoot(file) })),\n\t\t\troot === '' ? fallbackName : toArchiveName(root),\n\t\t\troot === extrasRoot ? additionalFiles : null\n\t\t);\n\t}\n};\n\n/**\n * Zip-slip defense for a server-controlled path: drop `.`, `..` and drive-letter segments so no\n * entry escapes the extraction directory. `''` when nothing safe remains.\n */\nconst sanitizeArchivePath = (raw: string): string =>\n\tsubFolderSegments(raw)\n\t\t.filter((segment) => segment !== '.' && segment !== '..' && !/^[a-zA-Z]:$/.test(segment))\n\t\t.join('/');\n\n/** The `isBase64Encoded` wire flag. Some server branches send booleans as strings (`\"True\"`). */\nexport const isBase64Flag = (flag: unknown): boolean =>\n\tflag === true || (typeof flag === 'string' && flag.trim().toLowerCase() === 'true');\n\nconst decodeResponseFiles = (dataItems: FileData[]): ProcessedFile[] => {\n\tconst processedFiles: ProcessedFile[] = [];\n\n\tdataItems.forEach((item) => {\n\t\tconst rawName = readField<string>(item, 'fileName') ?? '';\n\t\tconst rawType = readField<string>(item, 'fileType') ?? '';\n\t\tconst fileName = sanitizeArchivePath(`${rawName}${rawType}`);\n\t\tif (fileName === '') {\n\t\t\tgetLogger().warn(\n\t\t\t\t`Skipping file with unusable name \"${rawName}${rawType}\": no safe archive path remains after sanitization.`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst rawSubFolder = readField<string>(item, 'subFolder');\n\t\tconst subFolder = rawSubFolder ? sanitizeArchivePath(rawSubFolder) : '';\n\t\tconst filePath = subFolder !== '' ? `${subFolder}/${fileName}` : fileName;\n\n\t\tconst data = readField<unknown>(item, 'data');\n\t\tif (typeof data !== 'string' || data === '') {\n\t\t\tgetLogger().warn(`Skipping file \"${filePath}\": item carries no usable data.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst metadata = readField<Record<string, string>>(item, 'metadata');\n\n\t\tif (isBase64Flag(readField<unknown>(item, 'isBase64Encoded'))) {\n\t\t\ttry {\n\t\t\t\tprocessedFiles.push({\n\t\t\t\t\tfileName,\n\t\t\t\t\tcontent: decodeBase64ToBinary(data),\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\tsubFolder,\n\t\t\t\t\t...(metadata ? { metadata } : {})\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tgetLogger().warn(`Skipping file \"${filePath}\": base64 decode failed.`, err);\n\t\t\t}\n\t\t} else {\n\t\t\tprocessedFiles.push({\n\t\t\t\tfileName,\n\t\t\t\tcontent: data,\n\t\t\t\tpath: filePath,\n\t\t\t\tsubFolder,\n\t\t\t\t...(metadata ? { metadata } : {})\n\t\t\t});\n\t\t}\n\t});\n\n\treturn processedFiles;\n};\n\n/** One dead URL must degrade the batch, not stall it forever. */\nconst REMOTE_FILE_TIMEOUT_MS = 30_000;\n\nconst fetchRemoteFiles = async (refs: FileBaseInfo[]): Promise<ProcessedFile[]> => {\n\tconst fetched = await Promise.all(\n\t\trefs.map(async (file) => {\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(file.filePath, {\n\t\t\t\t\tsignal: AbortSignal.timeout(REMOTE_FILE_TIMEOUT_MS)\n\t\t\t\t});\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tgetLogger().warn(`Failed to fetch additional file from URL: ${file.filePath}`);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst arrayBuffer = await response.arrayBuffer();\n\t\t\t\tconst safeName = sanitizeArchivePath(file.fileName);\n\t\t\t\tif (safeName === '') {\n\t\t\t\t\tgetLogger().warn(`Skipping fetched file with unusable name: ${file.fileName}`);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst subFolder = file.subFolder ? sanitizeArchivePath(file.subFolder) : '';\n\t\t\t\treturn {\n\t\t\t\t\tfileName: safeName,\n\t\t\t\t\tcontent: new Uint8Array(arrayBuffer),\n\t\t\t\t\tpath: subFolder !== '' ? `${subFolder}/${safeName}` : safeName,\n\t\t\t\t\t// No `metadata`: an external URL carries no GH authoring context.\n\t\t\t\t\tsubFolder\n\t\t\t\t} as ProcessedFile;\n\t\t\t} catch (error) {\n\t\t\t\tgetLogger().error(`Error fetching additional file from URL: ${file.filePath}`, error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t})\n\t);\n\n\treturn fetched.filter((f): f is ProcessedFile => f !== null);\n};\n\nasync function createAndDownloadZip(files: ProcessedFile[], zipName: string): Promise<void> {\n\tconst { zip, strToU8 } = await import('fflate');\n\n\t// Paths are already unique: extractFilesFromComputeResponse renames collisions.\n\tconst zipData: Record<string, Uint8Array> = {};\n\tfor (const file of files) {\n\t\tzipData[file.path] = typeof file.content === 'string' ? strToU8(file.content) : file.content;\n\t}\n\n\t// Async `zip` deflates on a worker thread; `zipSync` would block the UI on large exports.\n\tconst zipped = await new Promise<Uint8Array>((resolve, reject) => {\n\t\tzip(zipData, { level: 6 }, (err, data) => (err ? reject(err) : resolve(data)));\n\t});\n\n\tconst blob = new Blob([zipped as BlobPart], { type: 'application/zip' });\n\tsaveFile(blob, `${zipName}.zip`);\n}\n\n/**\n * First archive path not already taken in `taken`, disambiguating with a\n * numeric suffix before the extension: `dir/model.txt` → `dir/model-2.txt`.\n */\nfunction uniqueArchivePath(path: string, taken: ReadonlySet<string>): string {\n\tif (!taken.has(path)) return path;\n\tconst slash = path.lastIndexOf('/');\n\tconst dot = path.lastIndexOf('.');\n\tconst stemEnd = dot > slash ? dot : path.length;\n\tconst stem = path.slice(0, stemEnd);\n\tconst ext = path.slice(stemEnd);\n\tfor (let i = 2; ; i++) {\n\t\tconst candidate = `${stem}-${i}${ext}`;\n\t\tif (!taken.has(candidate)) return candidate;\n\t}\n}\n\nfunction saveFile(blob: Blob, filename: string) {\n\tconst url = URL.createObjectURL(blob);\n\tconst a = document.createElement('a');\n\ta.href = url;\n\ta.download = filename;\n\t// Firefox requires the anchor to be in the DOM for the click to download.\n\tdocument.body.appendChild(a);\n\ta.click();\n\ta.remove();\n\t// Revoking synchronously can abort the download: the browser pins the blob only once it starts.\n\tsetTimeout(() => URL.revokeObjectURL(url), 10_000);\n}\n"],"mappings":"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"}
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core-C9chLkyW.cjs");exports.ComputeError=e.S,exports.DEFAULT_BLOCKED_HOST=e.h,exports.ErrorCodes=e.C,exports.classifyProbeFailure=e.m,exports.decodeBase64ToBinary=e.d,exports.downloadFileData=e.t,exports.downloadFileDataByRoot=e.n,exports.enableDebugLogging=e.y,exports.extractFilesFromComputeResponse=e.r,exports.fetchCompute=e.s,exports.getLogger=e.b,exports.getResponseWireSize=e.c,exports.groupFilesByRoot=e.i,exports.hasField=e._,exports.isDefinitionRef=e.o,exports.readField=e.v,exports.setLogger=e.x,exports.setResponseWireSize=e.l,exports.subFolderSegments=e.a,exports.validateServerUrl=e.g;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core-XZk7EVP3.cjs");exports.ComputeError=e.T,exports.DEFAULT_BLOCKED_HOST=e.v,exports.ErrorCodes=e.E,exports.classifyProbeFailure=e.g,exports.decodeBase64ToBinary=e.p,exports.downloadFileData=e.t,exports.downloadFileDataByRoot=e.n,exports.enableDebugLogging=e.S,exports.extractFilesFromComputeResponse=e.r,exports.fetchCompute=e.l,exports.getLogger=e.C,exports.groupFilesByRoot=e.a,exports.hasField=e.b,exports.isDefinitionRef=e.s,exports.readField=e.x,exports.setLogger=e.w,exports.subFolderSegments=e.o,exports.validateServerUrl=e.y;
package/dist/core.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as ServerErrorCodeMap, C as getLogger, D as fetchCompute, E as setResponseWireSize, M as ComputeError, N as ErrorCode, O as ComputeConfig, P as ErrorCodes, S as enableDebugLogging, T as getResponseWireSize, _ as isDefinitionRef, a as extractFilesFromComputeResponse, b as readField, c as ProcessedFile, d as classifyProbeFailure, f as DEFAULT_BLOCKED_HOST, g as SolveDefinition, h as DefinitionRef, i as downloadFileDataByRoot, j as ServerTiming, k as RetryPolicy, l as ProbeFailure, m as validateServerUrl, n as subFolderSegments, o as FileBaseInfo, p as ValidateServerUrlOptions, r as downloadFileData, s as FileData, t as groupFilesByRoot, u as ProbeVerdict, v as decodeBase64ToBinary, w as setLogger, x as Logger, y as hasField } from "./index-zlzEAi12.cjs";
2
- export { type ComputeConfig, ComputeError, DEFAULT_BLOCKED_HOST, type DefinitionRef, type ErrorCode, ErrorCodes, type FileBaseInfo, type FileData, type Logger, type ProbeFailure, type ProbeVerdict, type ProcessedFile, type RetryPolicy, type ServerErrorCodeMap, type ServerTiming, type SolveDefinition, type ValidateServerUrlOptions, classifyProbeFailure, decodeBase64ToBinary, downloadFileData, downloadFileDataByRoot, enableDebugLogging, extractFilesFromComputeResponse, fetchCompute, getLogger, getResponseWireSize, groupFilesByRoot, hasField, isDefinitionRef, readField, setLogger, setResponseWireSize, subFolderSegments, validateServerUrl };
1
+ import { A as ServerTiming, C as getLogger, D as ComputeConfig, E as ComputeAuth, M as ErrorCode, N as ErrorCodes, O as RetryPolicy, S as enableDebugLogging, T as fetchCompute, _ as isDefinitionRef, a as extractFilesFromComputeResponse, b as readField, c as ProcessedFile, d as classifyProbeFailure, f as DEFAULT_BLOCKED_HOST, g as SolveDefinition, h as DefinitionRef, i as downloadFileDataByRoot, j as ComputeError, k as ServerErrorCodeMap, l as ProbeFailure, m as validateServerUrl, n as subFolderSegments, o as FileBaseInfo, p as ValidateServerUrlOptions, r as downloadFileData, s as FileData, t as groupFilesByRoot, u as ProbeVerdict, v as decodeBase64ToBinary, w as setLogger, x as Logger, y as hasField } from "./index-C5T6o4Fr.cjs";
2
+ export { type ComputeAuth, type ComputeConfig, ComputeError, DEFAULT_BLOCKED_HOST, type DefinitionRef, type ErrorCode, ErrorCodes, type FileBaseInfo, type FileData, type Logger, type ProbeFailure, type ProbeVerdict, type ProcessedFile, type RetryPolicy, type ServerErrorCodeMap, type ServerTiming, type SolveDefinition, type ValidateServerUrlOptions, classifyProbeFailure, decodeBase64ToBinary, downloadFileData, downloadFileDataByRoot, enableDebugLogging, extractFilesFromComputeResponse, fetchCompute, getLogger, groupFilesByRoot, hasField, isDefinitionRef, readField, setLogger, subFolderSegments, validateServerUrl };
package/dist/core.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as ServerErrorCodeMap, C as getLogger, D as fetchCompute, E as setResponseWireSize, M as ComputeError, N as ErrorCode, O as ComputeConfig, P as ErrorCodes, S as enableDebugLogging, T as getResponseWireSize, _ as isDefinitionRef, a as extractFilesFromComputeResponse, b as readField, c as ProcessedFile, d as classifyProbeFailure, f as DEFAULT_BLOCKED_HOST, g as SolveDefinition, h as DefinitionRef, i as downloadFileDataByRoot, j as ServerTiming, k as RetryPolicy, l as ProbeFailure, m as validateServerUrl, n as subFolderSegments, o as FileBaseInfo, p as ValidateServerUrlOptions, r as downloadFileData, s as FileData, t as groupFilesByRoot, u as ProbeVerdict, v as decodeBase64ToBinary, w as setLogger, x as Logger, y as hasField } from "./index-zlzEAi12.js";
2
- export { type ComputeConfig, ComputeError, DEFAULT_BLOCKED_HOST, type DefinitionRef, type ErrorCode, ErrorCodes, type FileBaseInfo, type FileData, type Logger, type ProbeFailure, type ProbeVerdict, type ProcessedFile, type RetryPolicy, type ServerErrorCodeMap, type ServerTiming, type SolveDefinition, type ValidateServerUrlOptions, classifyProbeFailure, decodeBase64ToBinary, downloadFileData, downloadFileDataByRoot, enableDebugLogging, extractFilesFromComputeResponse, fetchCompute, getLogger, getResponseWireSize, groupFilesByRoot, hasField, isDefinitionRef, readField, setLogger, setResponseWireSize, subFolderSegments, validateServerUrl };
1
+ import { A as ServerTiming, C as getLogger, D as ComputeConfig, E as ComputeAuth, M as ErrorCode, N as ErrorCodes, O as RetryPolicy, S as enableDebugLogging, T as fetchCompute, _ as isDefinitionRef, a as extractFilesFromComputeResponse, b as readField, c as ProcessedFile, d as classifyProbeFailure, f as DEFAULT_BLOCKED_HOST, g as SolveDefinition, h as DefinitionRef, i as downloadFileDataByRoot, j as ComputeError, k as ServerErrorCodeMap, l as ProbeFailure, m as validateServerUrl, n as subFolderSegments, o as FileBaseInfo, p as ValidateServerUrlOptions, r as downloadFileData, s as FileData, t as groupFilesByRoot, u as ProbeVerdict, v as decodeBase64ToBinary, w as setLogger, x as Logger, y as hasField } from "./index-C5T6o4Fr.js";
2
+ export { type ComputeAuth, type ComputeConfig, ComputeError, DEFAULT_BLOCKED_HOST, type DefinitionRef, type ErrorCode, ErrorCodes, type FileBaseInfo, type FileData, type Logger, type ProbeFailure, type ProbeVerdict, type ProcessedFile, type RetryPolicy, type ServerErrorCodeMap, type ServerTiming, type SolveDefinition, type ValidateServerUrlOptions, classifyProbeFailure, decodeBase64ToBinary, downloadFileData, downloadFileDataByRoot, enableDebugLogging, extractFilesFromComputeResponse, fetchCompute, getLogger, groupFilesByRoot, hasField, isDefinitionRef, readField, setLogger, subFolderSegments, validateServerUrl };
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,r as m,s as h,t as g,v as _,x as v,y}from"./core-BSKhoCtA.js";export{t as ComputeError,c as DEFAULT_BLOCKED_HOST,e as ErrorCodes,d as classifyProbeFailure,o as decodeBase64ToBinary,g as downloadFileData,f as downloadFileDataByRoot,y as enableDebugLogging,m as extractFilesFromComputeResponse,h as fetchCompute,i as getLogger,a as getResponseWireSize,l as groupFilesByRoot,n as hasField,p as isDefinitionRef,_ as readField,v as setLogger,u as setResponseWireSize,r as subFolderSegments,s as validateServerUrl};
1
+ import{C as e,E as t,S as n,T as r,a as i,b as a,g as o,l as s,n as c,o as l,p as u,r as d,s as f,t as p,v as m,w as h,x as g,y as _}from"./core-DcBw277f.js";export{r as ComputeError,m as DEFAULT_BLOCKED_HOST,t as ErrorCodes,o as classifyProbeFailure,u as decodeBase64ToBinary,p as downloadFileData,c as downloadFileDataByRoot,n as enableDebugLogging,d as extractFilesFromComputeResponse,s as fetchCompute,e as getLogger,i as groupFilesByRoot,a as hasField,f as isDefinitionRef,g as readField,h as setLogger,l as subFolderSegments,_ as validateServerUrl};
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core-C9chLkyW.cjs");var t=class t{serverUrl;apiKey;disposed=!1;activeMonitors=new Set;activeTimeouts=new Set;static DEFAULT_TIMEOUT_MS=5e3;static LIFECYCLE_TIMEOUT_MS=6e4;static MIN_MONITOR_INTERVAL_MS=100;constructor(t,n){this.serverUrl=e.g(t),this.apiKey=n}buildHeaders(){let e={"Content-Type":`application/json`};return this.apiKey&&(e.RhinoComputeKey=this.apiKey),e}fetchWithTimeout(e,n={},r=t.DEFAULT_TIMEOUT_MS){let i=new Headers(this.buildHeaders());n.headers&&new Headers(n.headers).forEach((e,t)=>{i.set(t,e)});let a={};i.forEach((e,t)=>{a[t]=e});let o={...n,headers:a};return r>0&&!o.signal&&(o.signal=AbortSignal.timeout(r)),fetch(e,o)}async isServerOnline(e=5e3){return(await this.probeServer(e)).online}async probeServer(t=5e3){this.ensureNotDisposed();let n=`${this.serverUrl}/`;try{let e=await this.fetchWithTimeout(n,{method:`GET`,redirect:`manual`},t),r=e.type===`opaqueredirect`||e.status>=300&&e.status<400;return{online:e.ok||r,status:e.status}}catch(t){return e.b().debug(`[ComputeServerStats] Fetch error:`,t),{online:!1,error:t instanceof Error?`${t.name}: ${t.message}`:String(t)}}}async getActiveChildren(n={}){this.ensureNotDisposed();let{initialize:r=!0}=n,i=r?`${this.serverUrl}/activechildren`:`${this.serverUrl}/activechildren?initialize=false`,a=r?t.LIFECYCLE_TIMEOUT_MS:t.DEFAULT_TIMEOUT_MS;try{let t=await this.fetchWithTimeout(i,{},a);if(!t.ok)return e.b().warn(`[ComputeServerStats] Failed to fetch active children:`,t.status),null;let n=(await t.text()).trim();return/^\d+$/.test(n)?parseInt(n,10):(e.b().warn(`[ComputeServerStats] Invalid active children response:`,n),null)}catch(t){return e.b().warn(`[ComputeServerStats] Error fetching active children:`,t),null}}async getVersion(){this.ensureNotDisposed();try{let t=await this.fetchWithTimeout(`${this.serverUrl}/version`);if(!t.ok)return e.b().warn(`[ComputeServerStats] Failed to fetch version:`,t.status),null;let n=await t.text();try{let e=JSON.parse(n);return{rhino:e.rhino??``,compute:e.compute??``,git_sha:e.git_sha??null}}catch{return{rhino:n,compute:``,git_sha:null}}}catch(t){return e.b().warn(`[ComputeServerStats] Error fetching version:`,t),null}}async getInstalledPlugins(t=`gh`){this.ensureNotDisposed();try{let n=await this.fetchWithTimeout(`${this.serverUrl}/plugins/${t}/installed`);if(!n.ok)return e.b().warn(`[ComputeServerStats] Failed to fetch ${t} plugins:`,n.status),null;let r=await n.text();try{let e=JSON.parse(r);return e&&typeof e==`object`?e:null}catch{return null}}catch(n){return e.b().warn(`[ComputeServerStats] Error fetching ${t} plugins:`,n),null}}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[e,t]=await Promise.all([this.getVersion(),this.getActiveChildren({initialize:!1})]);return{isOnline:!0,...e&&{version:e},...t!==null&&{activeChildren:t}}}async purgeCache(){this.ensureNotDisposed();try{let t=await this.fetchWithTimeout(`${this.serverUrl}/cache/purge`,{method:`POST`});if(!t.ok)return e.b().warn(`[ComputeServerStats] Failed to purge cache:`,t.status),null;let n=await t.text();try{let e=JSON.parse(n);return typeof e.purged==`number`?e.purged:null}catch{return null}}catch(t){return e.b().warn(`[ComputeServerStats] Error purging cache:`,t),null}}async purgeAllChildren(){this.ensureNotDisposed();let t=await this.getActiveChildren({initialize:!1});if(t===null)return e.b().warn(`[ComputeServerStats] purgeAllChildren: could not read child count`),null;if(t===0)return{totalPurged:0,calls:0,children:0,confident:!0};let n=t*2,r=0;for(let e=0;e<n;e++){let e=await this.purgeCache();e!==null&&(r+=e)}return{totalPurged:r,calls:n,children:t,confident:t===1}}async getServerTime(){this.ensureNotDisposed();try{let t=await this.fetchWithTimeout(`${this.serverUrl}/servertime`);if(!t.ok)return e.b().warn(`[ComputeServerStats] Failed to fetch server time:`,t.status),null;let n=(await t.text()).trim().replace(/^"|"$/g,``),r=new Date(n);return isNaN(r.getTime())?null:r}catch(t){return e.b().warn(`[ComputeServerStats] Error fetching server time:`,t),null}}async getIdleSpan(){this.ensureNotDisposed();try{let t=await this.fetchWithTimeout(`${this.serverUrl}/idlespan`);if(!t.ok)return e.b().warn(`[ComputeServerStats] Failed to fetch idle span:`,t.status),null;let n=parseFloat((await t.text()).trim());return isNaN(n)?null:n}catch(t){return e.b().warn(`[ComputeServerStats] Error fetching idle span:`,t),null}}async launchChildren(){return this.postJson(`/launch-children`)}async launchChild(e){let t=e===void 0?`/launch-child`:`/launch-child?port=${e}`;return this.postJson(t)}async shutdownChildren(e){let t=e===void 0?`/shutdown-children`:`/shutdown-children?port=${e}`;return this.postJson(t)}async recycleChildren(e){let t=e===void 0?`/recycle-children`:`/recycle-children?port=${e}`;return this.postJson(t)}async postJson(n){this.ensureNotDisposed();try{let r=await this.fetchWithTimeout(`${this.serverUrl}${n}`,{method:`POST`},t.LIFECYCLE_TIMEOUT_MS);if(!r.ok)return e.b().warn(`[ComputeServerStats] POST ${n} failed:`,r.status),null;let i=await r.text();try{return JSON.parse(i)}catch{return null}}catch(t){return e.b().warn(`[ComputeServerStats] Error on POST ${n}:`,t),null}}monitor(n,r=5e3){if(this.ensureNotDisposed(),!Number.isFinite(r)||r<t.MIN_MONITOR_INTERVAL_MS)throw new e.S(`monitor() intervalMs must be a finite number >= ${t.MIN_MONITOR_INTERVAL_MS}ms, got ${r}. Sub-${t.MIN_MONITOR_INTERVAL_MS}ms polling would hot-loop the server.`,e.C.INVALID_CONFIG,{context:{intervalMs:r}});let i=!0,a=null;e.b().info(`🔄 Starting server stats monitoring every ${r}ms`);let o=async()=>{if(a!==null&&(this.activeTimeouts.delete(a),a=null),i&&!this.disposed){try{let t=await this.getServerStats();if(!i||this.disposed)return;try{n(t)}catch(t){e.b().error(`[ComputeServerStats] Monitor callback threw:`,t)}}catch(t){!i||this.disposed?e.b().debug(`[ComputeServerStats] Monitor poll cancelled during shutdown:`,t):e.b().error(`[ComputeServerStats] Failed to fetch stats during monitor:`,t)}i&&!this.disposed&&(a=setTimeout(()=>void o(),r),this.activeTimeouts.add(a))}},s=()=>{i=!1,a!==null&&(clearTimeout(a),this.activeTimeouts.delete(a),a=null),this.activeMonitors.delete(s)};return this.activeMonitors.add(s),o(),s}async dispose(){if(!this.disposed){this.disposed=!0;for(let e of this.activeMonitors)e();this.activeMonitors.clear();for(let e of this.activeTimeouts)clearTimeout(e);this.activeTimeouts.clear()}}ensureNotDisposed(){if(this.disposed)throw new e.S(`ComputeServerStats has been disposed and cannot be used`,e.C.INVALID_STATE,{context:{disposed:this.disposed}})}};const n=new Set;function r(){if(typeof window>`u`||globalThis.process?.versions?.node!=null)return!1;let e=globalThis.navigator,t=typeof e?.userAgent==`string`?e.userAgent:``;return!/jsdom/i.test(t)}function i(t,i){i||r()&&!n.has(t)&&(n.add(t),e.b().warn(`Warning: ${t} is running on the client side. For better performance and security, consider running this on the server side.`))}const a={definition_not_cached:e.C.DEFINITION_NOT_CACHED};function o(e){return{...e,serverErrorCodes:{...a,...e.serverErrorCodes}}}function s(t){return t instanceof e.S?t.code===e.C.DEFINITION_NOT_CACHED||t.message.includes(`Unable to load grasshopper definition`):!1}function c(t,n){if(!n)return;let r=e.v(t,`values`);if(!Array.isArray(r)||r.length===0)return;let i=[];for(let t of r){let n=e.v(t,`innerTree`);(!n||Object.keys(n).length===0)&&i.push(e.v(t,`paramName`)??`<unnamed>`)}if(i.length===0)return;let a=i.length===r.length?`all`:`${i.length}/${r.length}`;e.b().warn(`Solve returned empty output(s) (${a}): ${i.join(`, `)}. These parameters produced no data — check the definition's inputs and the branch feeding each.`)}async function l(e,t,n){i(`solveGrasshopperDefinition`,n.suppressBrowserWarning);let{response:r}=await p(m(await f(t),e),n);return r}async function u(e,t,n){return i(`solveGrasshopperDefinitionWithCacheKey`,n.suppressBrowserWarning),p(m(await f(t),e),n)}async function d(e,t,n,r){i(`solveByCacheKey`,r.suppressBrowserWarning);let a={algo:null,pointer:t,values:e};try{return{...await p(a,r),missed:!1}}catch(t){if(!s(t))throw t;return{...await p(m(await f(n),e),r),missed:!0}}}async function f(t){if(!e.o(t))return t;try{return await t.load()}catch(n){throw new e.S(`Failed to load definition bytes for ref '${t.key}'`,e.C.INVALID_INPUT,{context:{definitionKey:t.key},originalError:n instanceof Error?n:Error(String(n))})}}async function p(t,n){ee(t,n);let r=await e.s(`grasshopper`,t,o(n)),{pointer:i,algo:a,...s}=r,l=s,u=e.c(r);if(u!==void 0){let t=typeof a==`string`?a.length:0;e.l(l,Math.max(0,u-t))}return c(l,n.debug),{response:l,cacheKey:typeof i==`string`?i:null}}function m(t,n){let r={algo:null,pointer:null,values:n};return t instanceof Uint8Array?r.algo=e.u(t):/^https?:\/\//i.test(t)?r.pointer=t:r.algo=e.f(t)??e.p(t),r}function ee(e,t){t.cachesolve!=null&&(e.cachesolve=t.cachesolve),t.cacheerroredsolves!=null&&(e.cacheerroredsolves=t.cacheerroredsolves),t.modelunits!=null&&(e.modelunits=t.modelunits),t.angletolerance!=null&&(e.angletolerance=t.angletolerance),t.absolutetolerance!=null&&(e.absolutetolerance=t.absolutetolerance),t.dataversion!=null&&(e.dataversion=t.dataversion),t.selvaevents!=null&&(e.selvaevents=t.selvaevents)}function h(e){let t=new WeakSet,n=e=>{if(e===void 0)return`undefined`;if(e===null)return`null`;if(typeof e==`number`)return Number.isFinite(e)?String(e):`null`;if(typeof e==`string`||typeof e==`boolean`)return JSON.stringify(e);if(typeof e==`bigint`)return`${e}n`;if(e instanceof Uint8Array)return`{"__u8":${e.length},"hash":"${v(e)}"}`;if(Array.isArray(e)){if(t.has(e))return`"[Circular]"`;t.add(e);let r=[];for(let t=0;t<e.length;t++)r.push(n(e[t]));return t.delete(e),`[${r.join(`,`)}]`}if(typeof e==`object`){if(t.has(e))return`"[Circular]"`;t.add(e);let r;return r=typeof e.toJSON==`function`?n(e.toJSON()):e instanceof Map?`{"__map":[${[...e.entries()].map(([e,t])=>`[${n(e)},${n(t)}]`).sort().join(`,`)}]}`:e instanceof Set?`{"__set":[${[...e.values()].map(n).sort().join(`,`)}]}`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${n(e[t])}`).join(`,`)}}`,t.delete(e),r}return`null`};return n(e)}function g(e,t){let n=2166136261;for(let r=0;r<e;r++)n^=t(r),n=n+((n<<1)+(n<<4)+(n<<7)+(n<<8)+(n<<24))>>>0;return n.toString(16).padStart(8,`0`)}function _(e){return g(e.length,t=>e.charCodeAt(t))}function v(e){return g(e.length,t=>e[t])}function te(e,t){return y(b(e),t)}function y(e,t){let n=h(t);return`${e}|t:${n.length}:${_(n)}`}function b(t){return e.o(t)?`r:${t.key}`:typeof t==`string`?`s:${t.length}:${_(t)}`:`u8:${t.length}:${v(t)}`}function ne(e){return typeof e!=`string`||!/^https?:\/\//i.test(e)}function re(e){try{return JSON.stringify(e)?.length??0}catch{return 0}}var x=class{executor;baseConfig;mode;maxConcurrent;maxQueueDepth;queueWaitMs;timeoutMs;retry;cacheEnabled;cacheMaxBytes;cacheTtl;cacheErroredSolves;cache=new Map;cacheBytes=0;cacheHits=0;cacheMisses=0;cacheEvictions=0;cacheKeyExecutor;reuseServerDefinitionCache;serverCacheKeys=new Map;onStart;onSettle;onSuperseded;subscribers=new Set;inFlight=new Set;pendingForLatestWins=null;fifoQueue=[];_lastResult=null;_lastError=null;_lastDurationMs=null;solveSeq=0;lastStateSeq=0;disposed=!1;constructor(e,t,n={},r){this.executor=e,this.cacheKeyExecutor=r,this.baseConfig=t,this.mode=n.mode??`latest-wins`,this.maxConcurrent=Math.max(1,n.maxConcurrent??(this.mode===`parallel`?4:1)),this.maxQueueDepth=n.maxQueueDepth!==void 0&&n.maxQueueDepth>0?Math.floor(n.maxQueueDepth):void 0,this.queueWaitMs=n.queueWaitMs!==void 0&&n.queueWaitMs>0?n.queueWaitMs:void 0,this.timeoutMs=n.timeoutMs,this.retry=n.retry;let i=n.cache,a=typeof i==`object`?i:null;this.cacheMaxBytes=Math.max(0,a?.maxBytes??0),this.cacheEnabled=this.cacheMaxBytes>0,this.cacheTtl=a?.ttlMs??0,this.cacheErroredSolves=a?.cacheErroredSolves??!0,this.reuseServerDefinitionCache=!!r&&(n.reuseServerDefinitionCache??!0),this.onStart=n.onStart,this.onSettle=n.onSettle,this.onSuperseded=n.onSuperseded}get isSolving(){return this.inFlight.size>0}get hasPending(){return this.pendingForLatestWins!==null||this.fifoQueue.length>0}get inFlightCount(){return this.inFlight.size}get queueDepth(){return this.fifoQueue.length+ +!!this.pendingForLatestWins}get lastResult(){return this._lastResult}get lastError(){return this._lastError}get lastDurationMs(){return this._lastDurationMs}setMaxConcurrent(e){let t=Math.max(1,Math.floor(e));if(t===this.maxConcurrent)return;let n=t>this.maxConcurrent;this.maxConcurrent=t,n&&this.drainNext()}getMaxConcurrent(){return this.maxConcurrent}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){for(let t of this.subscribers)try{t()}catch(t){e.b().error(`[SolveScheduler] subscriber threw:`,t)}}solve(t,n,r){if(this.disposed)return Promise.reject(new e.S(`SolveScheduler has been disposed and cannot be used`,e.C.INVALID_STATE));let i=b(t),a=y(i,n),o=++this.solveSeq,s={key:a,enqueuedAt:Date.now(),startedAt:null};if(r?.signal?.aborted)return Promise.reject(this.makeAbortError(s));if(this.cacheEnabled){let e=this.readCache(a);if(e){this.mode===`latest-wins`&&this.supersedeCurrent();let t={status:`success`,response:e,durationMs:0,fromCache:!0};return this.writeLastState(o,{result:e,durationMs:0}),this.runHook(this.onStart,s),this.runHook(this.onSettle,s,t),this.notify(),Promise.resolve(e)}}return new Promise((e,a)=>{let c={definition:t,dataTree:n,definitionHash:i,ctx:s,seq:o,resolve:e,reject:a,externalSignal:r?.signal,selvaevents:r?.selvaevents};c.externalSignal&&(c.queuedAbortHandler=()=>this.abortQueuedItem(c),c.externalSignal.addEventListener(`abort`,c.queuedAbortHandler,{once:!0})),this.enqueue(c)})}writeLastState(e,t){return e<this.lastStateSeq?!1:(this.lastStateSeq=e,`result`in t?(this._lastResult=t.result,this._lastError=null):this._lastError=t.error,this._lastDurationMs=t.durationMs,!0)}supersedeCurrent(){this.pendingForLatestWins&&=(this.supersede(this.pendingForLatestWins),null);for(let e of this.inFlight)this.supersede(e),e.controller.abort()}abortQueuedItem(e){this.pendingForLatestWins===e&&(this.pendingForLatestWins=null);let t=this.fifoQueue.indexOf(e);t>=0&&this.fifoQueue.splice(t,1),this.rejectAsAborted(e),this.notify()}shedAsQueueFull(t){let n=new e.S(`Solve queue is full; request rejected (backpressure)`,e.C.QUEUE_FULL,{statusCode:503,context:{key:t.ctx.key,queueDepth:this.fifoQueue.length,maxQueueDepth:this.maxQueueDepth}});this.settleError(t,n)&&this.runHook(this.onSettle,t.ctx,{status:`error`,error:n,durationMs:0}),this.notify()}armQueueWaitTimer(t){if(this.queueWaitMs===void 0)return;let n=this.queueWaitMs;t.queueWaitTimer=setTimeout(()=>{if(t.settled)return;let r=this.fifoQueue.indexOf(t);r>=0&&this.fifoQueue.splice(r,1);let i=new e.S(`Solve waited longer than ${n}ms in queue; rejected (backpressure)`,e.C.QUEUE_TIMEOUT,{statusCode:503,context:{key:t.ctx.key,waitedMs:Date.now()-t.ctx.enqueuedAt,queueWaitMs:n}});this.settleError(t,i)&&this.runHook(this.onSettle,t.ctx,{status:`error`,error:i,durationMs:0}),this.notify()},n)}clearQueueWaitTimer(e){e.queueWaitTimer!==void 0&&(clearTimeout(e.queueWaitTimer),e.queueWaitTimer=void 0)}enqueue(e){switch(this.mode){case`latest-wins`:this.supersedeCurrent(),this.inFlight.size===0?this.execute(e):this.pendingForLatestWins=e;break;case`queue`:case`parallel`:this.inFlight.size<this.maxConcurrent?this.execute(e):this.maxQueueDepth!==void 0&&this.fifoQueue.length>=this.maxQueueDepth?this.shedAsQueueFull(e):(this.armQueueWaitTimer(e),this.fifoQueue.push(e))}this.notify()}async execute(e){let t=new AbortController,n=e;n.controller=t,this.inFlight.add(n),e.ctx.startedAt=Date.now(),this.clearQueueWaitTimer(e),this.removeQueuedAbortHandler(e);let r=()=>t.abort();e.externalSignal?.addEventListener(`abort`,r,{once:!0}),this.runHook(this.onStart,e.ctx),this.notify();let i=performance.now();try{let n={...this.baseConfig,signal:t.signal,...this.timeoutMs!==void 0&&{timeoutMs:this.timeoutMs},...this.retry!==void 0&&{retry:this.retry},...e.selvaevents!==void 0&&{selvaevents:e.selvaevents}},{response:r,definitionReuploaded:a}=await this.runExecutor(e.definition,e.dataTree,e.definitionHash,n),o=performance.now()-i;if(this.cacheEnabled&&this.writeCache(e.ctx.key,r),!this.settleSuccess(e,r))return;this.writeLastState(e.seq,{result:r,durationMs:o}),this.runHook(this.onSettle,e.ctx,{status:`success`,response:r,durationMs:o,fromCache:!1,definitionReuploaded:a})}catch(t){let r=performance.now()-i,a=this.normalizeExecutionError(t,n);this.writeLastState(e.seq,{error:a,durationMs:r}),this.settleError(e,a)&&this.runHook(this.onSettle,e.ctx,{status:`error`,error:a,durationMs:r})}finally{e.externalSignal?.removeEventListener(`abort`,r),this.inFlight.delete(n),this.drainNext(),this.notify()}}async runExecutor(e,t,n,r){if(!this.cacheKeyExecutor||!this.reuseServerDefinitionCache||!ne(e))return{response:await this.executor(e,t,r)};let i=n,a=this.serverCacheKeys.get(i)??null,o=await this.cacheKeyExecutor(e,t,a,r);if(o.cacheKey)for(this.serverCacheKeys.delete(i),this.serverCacheKeys.set(i,o.cacheKey);this.serverCacheKeys.size>100;){let e=this.serverCacheKeys.keys().next().value;if(e===void 0)break;this.serverCacheKeys.delete(e)}else this.serverCacheKeys.delete(i);return{response:o.response,definitionReuploaded:o.missed}}drainNext(){if(!this.disposed){if(this.mode===`latest-wins`){if(this.pendingForLatestWins&&this.inFlight.size===0){let e=this.pendingForLatestWins;this.pendingForLatestWins=null,this.execute(e)}return}for(;this.fifoQueue.length>0&&this.inFlight.size<this.maxConcurrent;){let e=this.fifoQueue.shift();this.execute(e)}}}supersede(t){let n=new e.S(`Superseded by newer solve`,e.C.SUPERSEDED,{context:{key:t.ctx.key,enqueuedAt:t.ctx.enqueuedAt}});this.settleError(t,n)&&this.runHook(this.onSuperseded,t.ctx)}makeAbortError(t){return new e.S(`Request aborted by caller`,e.C.ABORTED,{context:{key:t.key,enqueuedAt:t.enqueuedAt}})}settleError(e,t){return!e.settled&&(e.settled={error:t},this.clearQueueWaitTimer(e),this.removeQueuedAbortHandler(e),e.reject(t),!0)}settleSuccess(e,t){return!e.settled&&(e.settled={ok:!0},this.clearQueueWaitTimer(e),this.removeQueuedAbortHandler(e),e.resolve(t),!0)}removeQueuedAbortHandler(e){e.queuedAbortHandler&&e.externalSignal&&e.externalSignal.removeEventListener(`abort`,e.queuedAbortHandler),e.queuedAbortHandler=void 0}isAbortLikeError(e){if(e instanceof Error){if(e.name===`AbortError`)return!0;if(typeof DOMException<`u`&&e instanceof DOMException)return e.name===`AbortError`}return!1}normalizeExecutionError(t,n){return n.settled&&`error`in n.settled?n.settled.error:t instanceof e.S?t:this.isAbortLikeError(t)?this.makeAbortError(n.ctx):new e.S(t instanceof Error?t.message:String(t),e.C.UNKNOWN_ERROR,{originalError:t instanceof Error?t:Error(String(t))})}cancelAll(){for(this.pendingForLatestWins&&=(this.rejectAsAborted(this.pendingForLatestWins),null);this.fifoQueue.length>0;){let e=this.fifoQueue.shift();this.rejectAsAborted(e)}for(let e of this.inFlight){let t=this.makeAbortError(e.ctx);this.settleError(e,t)&&this.runHook(this.onSettle,e.ctx,{status:`error`,error:t,durationMs:e.ctx.startedAt?Date.now()-e.ctx.startedAt:0}),e.controller.abort()}this.notify()}rejectAsAborted(e){let t=this.makeAbortError(e.ctx);this.settleError(e,t)&&this.runHook(this.onSettle,e.ctx,{status:`error`,error:t,durationMs:0})}readCache(e){if(!this.cacheEnabled)return null;let t=this.cache.get(e);return t?this.cacheTtl>0&&Date.now()-t.insertedAt>this.cacheTtl?(this.dropCacheEntry(e),this.cacheMisses+=1,null):(this.cache.delete(e),this.cache.set(e,t),this.cacheHits+=1,t.response):(this.cacheMisses+=1,null)}writeCache(t,n){if(!this.cacheEnabled)return;let r=e.v(n,`errors`);if(!this.cacheErroredSolves&&Array.isArray(r)&&r.length>0)return;let i=e.c(n)??re(n);if(!(i>this.cacheMaxBytes))for(this.dropCacheEntry(t),this.cache.set(t,{response:n,insertedAt:Date.now(),sizeBytes:i}),this.cacheBytes+=i;this.cacheBytes>this.cacheMaxBytes&&this.cache.size>0;){let e=this.cache.keys().next().value;if(e===void 0)break;this.dropCacheEntry(e),this.cacheEvictions+=1}}dropCacheEntry(e){let t=this.cache.get(e);t&&(this.cache.delete(e),this.cacheBytes-=t.sizeBytes)}clearCache(){this.cache.clear(),this.cacheBytes=0}cacheStats(){return{entries:this.cache.size,bytes:this.cacheBytes,hits:this.cacheHits,misses:this.cacheMisses,evictions:this.cacheEvictions}}dispose(){this.disposed||(this.disposed=!0,this.cancelAll(),this.subscribers.clear(),this.clearCache())}runHook(t,...n){if(t)try{t(...n)}catch(t){e.b().error(`[SolveScheduler] hook threw:`,t)}}};function S(t){return e.o(t)?`ref:${t.key}`:typeof t==`string`&&t.length<200?t:`...content...`}function C(t){return Array.isArray(t)?t.map(t=>{let n=0,r=0,i=e.v(t,`innerTree`);if(i&&typeof i==`object`){for(let e of Object.values(i))if(Array.isArray(e)){n+=e.length;for(let t of e){let e=t?.data;typeof e==`string`&&(r+=e.length)}}}return{param:e.v(t,`paramName`)??`<unnamed>`,items:n,bytes:r}}):[]}var ie=class n{config;serverStats;disposed=!1;static CREATE_PROBE_TIMEOUT_MS=2e3;constructor(e){this.config=this.normalizeComputeConfig(e),this.serverStats=new t(this.config.serverUrl,this.config.apiKey)}static async create(t){let r=new n(t),i=Math.max(1,(t.retry?.attempts??2)+1),a=t.retry?.baseDelayMs??250,o=t.retry?.maxDelayMs??1e3,s,c=null,l=0;for(let t=0;t<i;t++){if(l=t+1,s=await r.serverStats.probeServer(n.CREATE_PROBE_TIMEOUT_MS),s.online)return r;if(c=e.m(s),c&&!c.retryable)break;if(t<i-1){let e=Math.min(a*2**t,o);await new Promise(t=>setTimeout(t,e))}}await r.dispose();let u=s?.status,d=c?`Rhino Compute server is not available. ${c.summary}`:`Rhino Compute server is not online`;throw new e.S(d,e.C.NETWORK_ERROR,{...u!==void 0&&{statusCode:u},context:{serverUrl:r.config.serverUrl,attempts:l,maxAttempts:i,...c&&{probeVerdict:c.verdict,probeRetryable:c.retryable},...u!==void 0&&{lastProbeStatus:u},...s?.error!==void 0&&{lastProbeError:s.error}}})}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(e){return this.ensureNotDisposed(),Z(e,this.config)}async getRawIO(e){return this.ensureNotDisposed(),Y(e,this.config)}async solve(t,n,r){this.ensureNotDisposed();try{if(typeof t==`string`&&!t?.trim())throw new e.S(`Definition URL/content is required`,e.C.INVALID_INPUT,{context:{receivedUrl:t}});if(t instanceof Uint8Array&&t.length===0)throw new e.S(`Definition content is empty`,e.C.INVALID_INPUT);if(e.o(t)&&!t.key.trim())throw new e.S(`DefinitionRef key is empty`,e.C.INVALID_INPUT);let i=await l(n,t,{...this.config,...r?.signal!==void 0&&{signal:r.signal},...r?.timeoutMs!==void 0&&{timeoutMs:r.timeoutMs},...r?.retry!==void 0&&{retry:r.retry},...r?.selvaevents!==void 0&&{selvaevents:r.selvaevents}}),a=e.v(i,`errors`);if(Array.isArray(a)&&a.length>0)throw new e.S(a.map(String).join(`; `)||`Computation failed`,e.C.COMPUTATION_ERROR,{context:{definition:S(t),inputSummary:C(n),errors:a,warnings:e.v(i,`warnings`),values:i.values}});return i}catch(r){throw this.config.debug&&e.b().error(`Compute failed:`,r),r instanceof e.S?r:new e.S(r instanceof Error?r.message:String(r),e.C.COMPUTATION_ERROR,{context:{definition:S(t),inputSummary:C(n)},originalError:r instanceof Error?r:Error(String(r))})}}createScheduler(e){return this.ensureNotDisposed(),new x((e,t,n)=>l(t,e,n),this.config,e,(e,t,n,r)=>n===null?u(t,e,r).then(e=>({...e,missed:!1})):d(t,n,e,r))}async dispose(){this.disposed||(this.disposed=!0,await this.serverStats.dispose())}ensureNotDisposed(){if(this.disposed)throw new e.S(`GrasshopperClient has been disposed and cannot be used`,e.C.INVALID_STATE)}normalizeComputeConfig(t){return{...t,serverUrl:e.g(t.serverUrl),apiKey:t.apiKey,authToken:t.authToken,debug:t.debug??!1,suppressBrowserWarning:t.suppressBrowserWarning}}};const w=new Map;function T(e,t){w.set(e,t)}T(`Rhino.Geometry.Point3d`,(e,t)=>{let n=t;return!n||typeof n.X!=`number`?null:new e.Point([n.X,n.Y,n.Z])}),T(`Rhino.Geometry.Line`,(e,t)=>{let n=t;return!n||!n.From||!n.To?null:new e.Line([n.From.X,n.From.Y,n.From.Z],[n.To.X,n.To.Y,n.To.Z])});function ae(e){if(w.has(e))return w.get(e);for(let[t,n]of w)if(e.startsWith(t))return n}function oe(e){return!!(e&&typeof e==`object`&&typeof e.data==`string`)}function E(e,t){return{__decodeError:!0,type:e,raw:t}}function se(t,n,r){let i=ae(n),a=!1;if(i)try{let e=i(r,t);if(e!=null)return e}catch(t){e.b().warn(`Failed to decode Rhino type ${n}:`,t),a=!0}try{if(oe(t))return r.CommonObject.decode(t)}catch(r){return e.b().warn(`Failed to decode ${n} with CommonObject:`,r),E(n,t)}return a?E(n,t):t}function ce(e){let t=new WeakSet,n=e=>{if(!e||typeof e!=`object`||t.has(e))return;t.add(e);let r=e.delete;if(typeof r==`function`){let t=e.isDeleted;(typeof t!=`function`||!t.call(e))&&r.call(e);return}if(Array.isArray(e)){for(let t of e)n(t);return}let i=Object.getPrototypeOf(e);if(i===Object.prototype||i===null)for(let t of Object.values(e))n(t)};n(e)}const D={STRING:`System.String`,INT:`System.Int32`,DOUBLE:`System.Double`,BOOL:`System.Boolean`},le=[`WebDisplay`],O=`FileData`;function k(e){return le.some(t=>e.includes(t))}function ue(e){if(typeof e!=`string`)return e;let t=e.trim();if(!(t.startsWith(`{`)||t.startsWith(`[`)||t.startsWith(`"`)))return e;try{let e=JSON.parse(t);if(typeof e==`string`)try{return JSON.parse(e)}catch{return e}return e}catch{return e}}function de(e,t,n){switch(t){case D.STRING:return typeof e==`string`?e.replace(/^"(.*)"$/,`$1`):e;case D.INT:return Number.parseInt(e,10);case D.DOUBLE:return Number.parseFloat(e);case D.BOOL:return String(e).toLowerCase()===`true`;default:return n&&t.startsWith(`Rhino.Geometry.`)?se(e,t,n):e}}const A=new WeakMap;function j(e){if(A.has(e))return A.get(e);let t=ue(e.data);return A.set(e,t),t}function M(e,t,n,r){if(typeof e.data!=`string`)return e.data;let i=n?j(e):e.data;return n&&t.includes(O)?N(i)??i:de(i,t,r)}const fe=e=>e===!0||typeof e==`string`&&e.trim().toLowerCase()===`true`;function N(t){if(!t||typeof t!=`object`)return null;let n=e.v(t,`fileName`),r=e.v(t,`fileType`),i=e.v(t,`subFolder`),a=e.v(t,`isBase64Encoded`);if(typeof n!=`string`||typeof r!=`string`||typeof i!=`string`||!e._(t,`data`)||typeof a!=`boolean`&&typeof a!=`string`)return null;let o=e.v(t,`metadata`);return{fileName:n,fileType:r,data:e.v(t,`data`),isBase64Encoded:fe(a),subFolder:i,...o?{metadata:o}:{}}}function P(t){let n=e.v(t,`values`);return Array.isArray(n)?n:[]}function F(e){return typeof e.type==`string`?e.type:``}function I(e,t){if(e&&typeof e==`object`){for(let n of Object.values(e))if(Array.isArray(n))for(let e of n)e&&typeof e==`object`&&t(e)}}function pe(t,n=!1,r={}){let{parseValues:i=!0,rhino:a,stringOnly:o=!1}=r,s={},c=new Set;for(let r of P(t)){let t=e.v(r,`paramName`);I(e.v(r,`innerTree`),e=>{let r=F(e);if(k(r)||o&&r!==D.STRING)return;let l=n?e.id:t;if(!l)return;let u=M(e,r,i,a);l in s?c.has(l)?s[l].push(u):(s[l]=[s[l],u],c.add(l)):s[l]=u})}return{values:s,dispose:()=>ce(s)}}function me(t){let n=[];for(let r of P(t))I(e.v(r,`innerTree`),e=>{if(!F(e).includes(O))return;let t=N(j(e));t&&n.push(t)});return n}function he(t,n,r={}){let{parseValues:i=!0,rhino:a,stringOnly:o=!1}=r;for(let r of P(t)){let t=e.v(r,`innerTree`),s=!1;if(`byName`in n){if(e.v(r,`paramName`)!==n.byName)continue;s=!0}let c=[];if(I(t,e=>{if(`byId`in n){if(e.id!==n.byId)return;s=!0}let t=F(e);k(t)||o&&t!==D.STRING||c.push(M(e,t,i,a))}),s)return c.length===0?void 0:c.length===1?c[0]:c}}var ge=class{response;debug;constructor(e,t=!1){this.response=e,this.debug=t}getValues(e=!1,t={}){return pe(this.response,e,t)}getValue(e,t){return he(this.response,e,t)}getFileData(){return me(this.response)}async getAndDownloadFiles(t,n){let r=this.getFileData();await e.t(r,t,n)}};const L=/^\{(-?\d+(?:;-?\d+)*)?\}$/;function R(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.entries(e);return t.length>0&&t.every(([e,t])=>L.test(e)&&Array.isArray(t))}function z(e,t,n){let r=Number(e.toFixed(t));return Math.abs(e-r)<n?r:e}function _e(e,t){if(!Number.isFinite(e)||e===0)return .1;let n=Math.abs(e);if(n>=1){let n=String(e).split(`.`)[1];if(n&&n.length>0){let e=Math.min(n.length,12),r=10**-e,i=Number(r.toFixed(e));return Math.abs(i-r)<t?i:r}return 1}let r=String(e),i=r.toLowerCase().match(/e(-?\d+)/);if(i){let e=Number(i[1]);if(e<0||r.toLowerCase().includes(`e-`)){let n=Math.abs(e),r=10**-n,i=Number(r.toFixed(n));return Math.abs(i-r)<t?i:r}return .1}let a=n.toFixed(12).replace(/0+$/,``),o=Math.min((a.split(`.`)[1]||``).length,12);if(o===0)return .1;let s=10**-o,c=Number(s.toFixed(o));return Math.abs(c-s)<t?c:s}function B(e){return typeof e.stepSize==`number`&&Number.isFinite(e.stepSize)&&e.stepSize>0?e.stepSize:void 0}function V(e,t,n){if(e==null)return e;if(Array.isArray(e)){let n=e.map(t).filter(e=>e!==null);return n.length>0?n:void 0}let r=t(e);return r===null?n?void 0:e:r}const H=e=>{if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`){let t=e.trim();if(t===``||/^[+-]?0[xbo]/i.test(t))return null;let n=Number(t);return Number.isFinite(n)?n:null}return null},U=e=>{if(typeof e==`boolean`)return e;if(typeof e==`string`){let t=e.trim().toLowerCase();if(t===`true`)return!0;if(t===`false`)return!1}return null},ve=e=>typeof e==`string`?e.length>=2&&e.startsWith(`"`)&&e.endsWith(`"`)?e.slice(1,-1):e.startsWith(`"`)?e.slice(1):e:null,ye=e=>{if(typeof e==`string`){let t=e.trim();return t.startsWith(`"`)&&t.endsWith(`"`)&&(t=t.slice(1,-1).trim()),t}return null};function W(t){return n=>{if(typeof n==`object`&&n)return n;if(typeof n==`string`&&n.trim()!==``)try{let r=JSON.parse(n);return typeof r==`object`&&r?r:(e.b().warn(`Parsed value for input ${t} is not an object`),null)}catch(r){return e.b().warn(`Failed to parse object value "${n}" for input ${t}`,r),null}return null}}function be(t,n=1e-8){let r=t.paramType===`Integer`,i=B(t);if(R(t.default))return{default:t.default,stepSize:i??(r?1:.1)};if(typeof t.default==`string`&&t.default.trim()!==``&&H(t.default)===null)throw new e.S(`Invalid numeric default "${t.default}" for input "${t.name||`unknown`}"`,e.C.VALIDATION_ERROR,{context:{inputName:t.name,default:t.default}});let a=V(t.default,H,!0);if(r)return Array.isArray(a)?a=a.map(e=>typeof e==`number`?Math.round(e):e):typeof a==`number`&&(a=Math.round(a)),{default:a,stepSize:i??1};let o=Array.isArray(a)?a[0]:a,s;typeof o==`number`&&Number.isFinite(o)&&o!==0?s=o:typeof t.minimum==`number`&&Number.isFinite(t.minimum)&&t.minimum!==0?s=t.minimum:typeof t.maximum==`number`&&Number.isFinite(t.maximum)&&t.maximum!==0&&(s=t.maximum);let c=i??(s===void 0?.1:_e(s,n)),l=0,u=String(c),d=u.toLowerCase().match(/e(-?\d+)/);if(l=d?Math.abs(Number(d[1])):u.split(`.`)[1]?.length??0,l===0&&typeof o==`number`&&o!==0&&Math.abs(o)<1){let e=Math.ceil(-Math.log10(Math.abs(o)));Number.isFinite(e)&&e>0&&(l=e)}return l=Math.min(Math.max(l,0),12),Array.isArray(a)?a=a.map(e=>typeof e==`number`?z(e,l,n):e):typeof a==`number`&&(a=z(a,l,n)),{default:a,stepSize:c}}const xe={types:[`Number`,`Integer`],parse(e,t){let{default:n,stepSize:r}=be(e);return{...t,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,stepSize:r,default:n}},fallback(e,t){let n=(e.atMost??1)>1,r=typeof e.minimum==`number`&&Number.isFinite(e.minimum)&&e.minimum>0?e.minimum:0;return{...t,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,stepSize:B(e)??(e.paramType===`Integer`?1:.1),default:n?[r]:r}}},Se={types:[`Boolean`],parse(t,n){if(R(t.default))return{...n,paramType:`Boolean`,default:t.default};let r=V(t.default,U,!1);if(r!=null&&typeof r!=`boolean`&&!Array.isArray(r))throw new e.S(`Invalid boolean default "${String(r)}" for input "${t.name||`unknown`}"`,e.C.VALIDATION_ERROR,{context:{inputName:t.name,default:t.default}});return{...n,paramType:`Boolean`,default:r}},fallback(e,t){let n=(e.atMost??1)>1;return{...t,paramType:`Boolean`,default:n?[!1]:!1}}},Ce={types:[`Text`],parse(e,t){let n=V(e.default,ve,!1);return{...t,paramType:`Text`,default:n}},fallback(e,t){let n=(e.atMost??1)>1;return{...t,paramType:`Text`,default:n?[``]:``}}},we={types:[`ValueList`],parse(t,n,r){if(!t.values||typeof t.values!=`object`||Object.keys(t.values).length===0)throw e.S.missingValues(t.nickname||`unnamed`,`ValueList`);let i=t.default;if(t.default!==void 0&&t.default!==null){if(typeof t.default==`object`)throw new e.S(`ValueList input "${t.nickname||`unnamed`}" default is not a string-able value`,e.C.VALIDATION_ERROR,{context:{inputName:t.name,default:t.default}});let n=String(t.default).toLowerCase(),a=Object.keys(t.values).find(e=>e.toLowerCase()===n);if(a!==void 0)i=a;else{let n=`ValueList input "${t.nickname||`unnamed`}" default value "${t.default}" is not in available values`;e.b().warn(n),r?.({code:e.C.VALIDATION_ERROR,message:n})}}return{...n,paramType:`ValueList`,values:t.values,default:i}},fallback(e,t){return{...t,paramType:`ValueList`,values:e.values&&typeof e.values==`object`?e.values:{},default:void 0}}},G={types:[`Geometry`],parse(e,t){let n=V(e.default,W(e.nickname||`unnamed`),!0);return{...t,paramType:`Geometry`,default:n}},fallback(e,t){let n=(e.atMost??1)>1;return{...t,paramType:`Geometry`,default:n?[null]:null}}},K=new Map([xe,Se,Ce,we,G,{types:[`File`],parse(e,t){let n=V(e.default,W(e.nickname||`unnamed`),!0);return{...t,paramType:`File`,acceptedFormats:e.acceptedFormats,default:n}},fallback(e,t){let n=(e.atMost??1)>1;return{...t,paramType:`File`,default:n?[null]:null}}},{types:[`Color`],parse(e,t){let n=V(e.default,ye,!1);return{...t,paramType:`Color`,default:n}},fallback(e,t){let n=(e.atMost??1)>1;return{...t,paramType:`Color`,default:n?[`0, 0, 0`]:`0, 0, 0`}}}].flatMap(e=>e.types.map(t=>[t,e]))),Te=G;function q(t){return e.v(t,`data`)}function Ee(t){return e.v(t,`type`)}const De=new Set([`System.Double`,`System.Single`,`System.Decimal`,`System.Int32`,`System.Int64`]),Oe=new Set([`System.Int32`,`System.Int64`]);function ke(t){if(typeof t.default!=`object`||t.default===null||Array.isArray(t.default))return{schema:t};if(!e._(t.default,`innerTree`)){let n=`Input "${t.name??`unknown`}" default had an unrecognized shape (no innerTree key); the default was dropped.`;return e.b().warn(`Unexpected structure in input.default:`,t.default),{schema:{...t,default:null},warning:{code:`MALFORMED_DEFAULT`,message:n}}}let n=e.v(t.default,`innerTree`)??{};if(Object.keys(n).length===0)return{schema:{...t,default:void 0}};if(t.treeAccess||t.atMost&&t.atMost>1){let r={},i=[];for(let[a,o]of Object.entries(n)){if(!Array.isArray(o)){let n=`Input "${t.name??`unknown`}" default had a non-array innerTree branch ("${a}"); the default was dropped.`;return e.b().warn(`Unexpected structure in input.default innerTree:`,t.default),{schema:{...t,default:null},warning:{code:`MALFORMED_DEFAULT`,message:n}}}let n=[];for(let e of o){let t=q(e),r=Ee(e);if(r&&De.has(r)){if(typeof t==`string`&&t.trim()===``)continue;let e=H(t);if(e===null){i.push(`"${String(t)}" (${r})`);continue}n.push(Oe.has(r)?Math.round(e):e);continue}if(r===`System.Boolean`){let e=U(t);if(e===null){i.push(`"${String(t)}" (${r})`);continue}n.push(e);continue}if(typeof t==`string`&&r?.startsWith(`Rhino.Geometry`)){try{n.push(JSON.parse(t))}catch{n.push(t)}continue}n.push(t)}r[a]=n}let a;if(i.length>0){let n=`Input "${t.name??`unknown`}" default contained ${i.length} tree value(s) that could not be parsed and were dropped: ${i.join(`, `)}.`;e.b().warn(n),a={code:`MALFORMED_DEFAULT`,message:n}}return{schema:{...t,default:r},...a&&{warning:a}}}let r=[];for(let t of Object.values(n))Array.isArray(t)&&t.forEach(t=>{t&&typeof t==`object`&&e._(t,`data`)&&r.push(q(t))});return r.length===0?{schema:{...t,default:void 0}}:r.length===1?{schema:{...t,default:r[0]}}:{schema:{...t,default:r}}}const Ae=new Map([...K.keys()].map(e=>[e.toLowerCase(),e]));function je(e){return Ae.get(e?.toLowerCase())??e}function Me(e){return J(e).input}function J(t){let n={description:t.description,name:t.name,nickname:t.nickname,treeAccess:t.treeAccess,groupName:t.groupName??void 0,id:t.id},r=je(t.paramType),i={...t,paramType:r},a;try{let{schema:e,warning:n}=ke(i);i=e,a=n&&{inputName:t.name||`unknown`,paramType:t.paramType,message:n.message,code:n.code}}catch(e){i={...i,default:null},a={inputName:t.name||`unknown`,paramType:t.paramType,message:`Input "${t.name??`unknown`}" default could not be normalized and was dropped: ${e instanceof Error?e.message:String(e)}`,code:`MALFORMED_DEFAULT`}}let o=K.get(r),s=[],c=e=>s.push({inputName:t.name||`unknown`,paramType:t.paramType,message:e.message,code:e.code});try{if(!o)throw e.S.unknownParamType(r,t.name);let l=o.parse(i,n,c),u=a?[a,...s]:s;return{input:l,error:a,...u.length>0&&{errors:u}}}catch(c){if(c instanceof e.S){e.b().error(`Validation error for input ${t.name||`unknown`}:`,c.message);let r={inputName:t.name||`unknown`,paramType:t.paramType,message:c.message,code:c.code};return{input:(o??Te).fallback(i,n),error:r,errors:[...a?[a]:[],...s,r]}}throw new e.S(c instanceof Error?c.message:String(c),`VALIDATION_ERROR`,{context:{paramName:t.name,paramType:r},originalError:c instanceof Error?c:Error(String(c))})}}function Ne(e){let t=[],n=[];for(let r of e){let{input:e,errors:i}=J(r);t.push(e),i&&n.push(...i)}return{inputs:t,parseErrors:n}}function Pe(t){let n=e.v(t,`stepSize`);return{id:e.v(t,`id`)??``,name:e.v(t,`name`)??``,nickname:e.v(t,`nickname`)??null,description:e.v(t,`description`)??``,paramType:e.v(t,`paramType`)??``,treeAccess:e.v(t,`treeAccess`)??!1,minimum:e.v(t,`minimum`)??null,maximum:e.v(t,`maximum`)??null,atLeast:e.v(t,`atLeast`)??1,atMost:e.v(t,`atMost`)??1,stepSize:typeof n==`number`&&Number.isFinite(n)?n:void 0,default:e.v(t,`default`),values:e.v(t,`values`),acceptedFormats:e.v(t,`acceptedFormats`),groupName:e.v(t,`groupName`)??null}}function Fe(t){return{name:e.v(t,`name`)??``,nickname:e.v(t,`nickname`)??null,paramType:e.v(t,`paramType`)??``,id:e.v(t,`id`)??``}}async function Y(t,n){let r=m(t,[]),i={};if(r.algo&&(i.algo=r.algo),r.pointer&&(i.pointer=r.pointer),!i.algo&&!i.pointer)throw new e.S(`Definition must resolve to either a URL pointer or base64 algo`,e.C.INVALID_INPUT,{context:{definition:t}});let a=await e.s(`io`,i,o(n));if(!a||typeof a!=`object`)throw new e.S(`Invalid IO response structure`,e.C.INVALID_INPUT,{context:{response:a,definition:t}});let s=X(e.v(a,`warnings`)),c=X(e.v(a,`errors`)),l=e.v(a,`inputs`),u=e.v(a,`outputs`);return{inputs:Array.isArray(l)?l.map(Pe):[],outputs:Array.isArray(u)?u.map(Fe):[],...s&&{loadWarnings:s},...c&&{loadErrors:c}}}function X(e){if(!Array.isArray(e))return;let t=e.map(Ie).filter(e=>e!==void 0);return t.length>0?t:void 0}function Ie(t){if(t==null)return;let n;if(typeof t==`string`)n=t;else if(typeof t==`object`){let r=e.v(t,`message`);if(typeof r==`string`&&r.trim().length>0)n=r;else try{n=JSON.stringify(t)??String(t)}catch{n=String(t)}}else n=String(t);return n.trim().length>0?n:void 0}async function Z(e,t){i(`fetchParsedDefinitionIO`,t.suppressBrowserWarning);let{inputs:n,outputs:r,loadWarnings:a,loadErrors:o}=await Y(e,t),{inputs:s,parseErrors:c}=Ne(n);return{inputs:s,outputs:r,...c.length>0&&{parseErrors:c},...a&&{loadWarnings:a},...o&&{loadErrors:o}}}function Le(t){return(Array.isArray(t)?t:[t]).map(t=>({schemas:e.v(t,`schemas`),error:e.v(t,`error`)}))}const Re=new Set([`options`,`defaultOptions`,`values`]),Q=e=>e>=`A`&&e<=`Z`;function ze(e){if(e.length===0||!Q(e[0]))return e;let t=0;for(;t<e.length&&Q(e[t]);)t++;return t>1&&t<e.length&&t--,e.slice(0,t).toLowerCase()+e.slice(t)}function Be(e){return $(e)}function $(e){if(Array.isArray(e))return e.map($);if(typeof e!=`object`||!e)return e;let t={};for(let[n,r]of Object.entries(e)){let e=ze(n);t[e]=Re.has(e)?r:$(r)}return t}var Ve=class t{innerTree;paramName;constructor(e){this.paramName=e,this.innerTree={}}append(e,n){let r=t.formatPathString(e);this.innerTree[r]||(this.innerTree[r]=[]);let i=n.map(e=>({data:t.serializeValue(e)}));return this.innerTree[r].push(...i),this}appendSingle(e,t){return this.append(e,[t])}fromDataTreeDefault(e){this.innerTree={};for(let[n,r]of Object.entries(e)){if(!Array.isArray(r))continue;let e=t.parsePathString(n);this.append(e,r)}return this}appendFlat(e){let t=Array.isArray(e)?e:[e];return this.append([0],t)}flatten(){let e=[];for(let n of Object.values(this.innerTree))if(Array.isArray(n))for(let r of n)e.push(t.deserializeValue(r.data));return e}getPaths(){return Object.keys(this.innerTree)}getPath(e){let n=t.formatPathString(e),r=this.innerTree[n];if(r)return r.map(e=>t.deserializeValue(e.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(e){return e.filter(e=>t.hasValidValue(e.default)).map(e=>{let n=new t(e.nickname||`unnamed`),r=e.default;if(e.treeAccess&&R(r))n.fromDataTreeDefault(r),t.isNumericInput(e)&&n.applyNumericConstraints(e.minimum,e.maximum,e.nickname||`unnamed`);else{let i=Array.isArray(r)?r:[r],a=t.processValues(i,e);n.appendFlat(a)}return n.toComputeFormat()})}static fromInputParam(e){if(t.hasValidValue(e.default))return t.fromInputParams([e])[0]}static replaceTreeValue(e,n,r){let i=e.length>0&&e[0]instanceof t,a=t.buildFromValue(n,r);if(i){let t=e.slice(),r=t.findIndex(e=>e.getParamName()===n);return r===-1?t.push(a):t[r]=a,t}let o=e.slice(),s=a.toComputeFormat(),c=o.findIndex(e=>e.ParamName===n);return c===-1?o.push(s):o[c]=s,o}static buildFromValue(e,n){let r=new t(e);return R(n)?r.fromDataTreeDefault(n):r.appendFlat(n),r}static getTreeValue(e,n){let r=e.length>0&&e[0]instanceof t?t.readFromBuilders(e,n):t.readFromDataTrees(e,n);return r===null||r.length===0?null:r.length===1?r[0]:r}static readFromBuilders(e,t){let n=e.find(e=>e.getParamName()===t);return n?n.flatten():null}static readFromDataTrees(e,n){let r=e.find(e=>e.ParamName===n);if(!r?.InnerTree)return null;let i=Object.keys(r.InnerTree)[0];if(!i)return null;let a=r.InnerTree[i];return Array.isArray(a)?a.map(e=>e?.data===void 0?null:t.deserializeValue(e.data)):a?.data===void 0?a===void 0?null:[a]:[t.deserializeValue(a.data)]}static parsePathString(t){let n=t.match(L);if(!n)throw new e.S(`Invalid Grasshopper tree path: "${t}". Expected "{}", "{0}", or "{0;1;2}" (negative indices allowed, no empty segments).`,e.C.INVALID_INPUT,{context:{pathStr:t}});return n[1]?n[1].split(`;`).map(Number):[]}static formatPathString(e){return`{${e.join(`;`)}}`}applyNumericConstraints(e,n,r){for(let i of Object.values(this.innerTree))if(Array.isArray(i))for(let a of i){let i=t.deserializeValue(a.data);if(typeof i==`number`){let o=t.clampValue(i,e,n,r);a.data=t.serializeValue(o)}}}static serializeValue(e){return typeof e==`boolean`||typeof e==`number`||typeof e==`string`?e:typeof e==`object`&&e?JSON.stringify(e):String(e)}static deserializeValue(e){if(typeof e==`boolean`||typeof e==`number`||typeof e!=`string`)return e;if(e.startsWith(`{`)||e.startsWith(`[`))try{return JSON.parse(e)}catch{return e}let t=Number(e);return Number.isFinite(t)&&String(t)===e?t:e===`true`||e!==`false`&&e}static hasValidValue(e){return e==null?!1:typeof e==`string`||!(Array.isArray(e)&&e.length===0||typeof e==`object`&&!Array.isArray(e)&&Object.keys(e).length===0)}static isNumericInput(e){return e.paramType===`Number`||e.paramType===`Integer`}static processValues(e,n){return e.map(e=>t.isNumericInput(n)&&typeof e==`number`?t.clampValue(e,n.minimum,n.maximum,n.nickname||`unnamed`):e).filter(e=>e!=null)}static clampValue(t,n,r,i){let a=t;return n!=null&&a<n&&(e.b().warn(`${i}: ${t} below min ${n}, clamping`),a=n),r!=null&&a>r&&(e.b().warn(`${i}: ${t} above max ${r}, clamping`),a=r),a}};exports.ComputeServerStats=t,exports.GrasshopperClient=ie,exports.GrasshopperResponseProcessor=ge,exports.SolveScheduler=x,exports.TreeBuilder=Ve,exports.downloadFileData=e.t,exports.extractFilesFromComputeResponse=e.r,exports.fetchDefinitionIO=Y,exports.fetchParsedDefinitionIO=Z,exports.hashDefinition=b,exports.hashSolveInput=te,exports.isDefinitionRef=e.o,exports.normalizeUISchemaCasing=Be,exports.processInput=Me,exports.readSchemaResults=Le,exports.solveGrasshopperDefinition=l,exports.stableStringify=h;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core-XZk7EVP3.cjs");var t=class t{serverUrl;headers;disposed=!1;activeMonitors=new Set;static DEFAULT_TIMEOUT_MS=5e3;static LIFECYCLE_TIMEOUT_MS=6e4;static MIN_MONITOR_INTERVAL_MS=100;constructor(t,n){this.serverUrl=e.y(t),this.headers={...e._(typeof n==`string`?{apiKey:n}:n??{}),"Content-Type":`application/json`}}fetchWithTimeout(e,n={},r=t.DEFAULT_TIMEOUT_MS){let i={...n,headers:this.headers};return r>0&&!i.signal&&(i.signal=AbortSignal.timeout(r)),fetch(e,i)}async getText(n,r={},i=t.DEFAULT_TIMEOUT_MS){this.ensureNotDisposed();let a=`${r.method??`GET`} ${n}`;try{let t=await this.fetchWithTimeout(`${this.serverUrl}${n}`,r,i);return t.ok?await t.text():(e.C().warn(`[ComputeServerStats] ${a} failed:`,t.status),null)}catch(t){return e.C().warn(`[ComputeServerStats] ${a} errored:`,t),null}}async isServerOnline(e=t.DEFAULT_TIMEOUT_MS){return(await this.probeServer(e)).online}async probeServer(n=t.DEFAULT_TIMEOUT_MS){this.ensureNotDisposed();let r=`${this.serverUrl}/`;try{let e=await this.fetchWithTimeout(r,{method:`GET`,redirect:`manual`},n),t=e.type===`opaqueredirect`||e.status>=300&&e.status<400;return{online:e.ok||t,status:e.status}}catch(t){return e.C().debug(`[ComputeServerStats] Fetch error:`,t),{online:!1,error:t instanceof Error?`${t.name}: ${t.message}`:String(t)}}}async getActiveChildren(n={}){let{initialize:r=!0}=n,i=r?await this.getText(`/activechildren`,{},t.LIFECYCLE_TIMEOUT_MS):await this.getText(`/activechildren?initialize=false`);if(i===null)return null;let a=i.trim();return/^\d+$/.test(a)?parseInt(a,10):(e.C().warn(`[ComputeServerStats] /activechildren answered with a non-numeric body`),null)}async getVersion(){let e=await this.getText(`/version`);if(e===null)return null;let t=n(e);return t==null?{rhino:e,compute:``,git_sha:null}:{rhino:t.rhino??``,compute:t.compute??``,git_sha:t.git_sha??null}}async getInstalledPlugins(e=`gh`){let t=await this.getText(`/plugins/${e}/installed`),r=t===null?void 0:n(t);return r&&typeof r==`object`?r:null}async getServerStats(){if(this.ensureNotDisposed(),!await this.isServerOnline())return{isOnline:!1};let[e,t]=await Promise.all([this.getVersion(),this.getActiveChildren({initialize:!1})]);return{isOnline:!0,...e&&{version:e},...t!==null&&{activeChildren:t}}}async purgeCache(){let e=await this.getText(`/cache/purge`,{method:`POST`}),t=(e===null?void 0:n(e))?.purged;return typeof t==`number`?t:null}async purgeAllChildren(){this.ensureNotDisposed();let t=await this.getActiveChildren({initialize:!1});if(t===null)return e.C().warn(`[ComputeServerStats] purgeAllChildren: could not read child count`),null;if(t===0)return{totalPurged:0,calls:0,children:0,confident:!0};let n=t*2,r=0;for(let e=0;e<n;e++){let e=await this.purgeCache();e!==null&&(r+=e)}return{totalPurged:r,calls:n,children:t,confident:t===1}}async getServerTime(){let e=await this.getText(`/servertime`);if(e===null)return null;let t=new Date(e.trim().replace(/^"|"$/g,``));return isNaN(t.getTime())?null:t}async getIdleSpan(){let e=await this.getText(`/idlespan`);if(e===null)return null;let t=parseFloat(e.trim());return isNaN(t)?null:t}async launchChildren(){return this.postJson(`/launch-children`)}async launchChild(e){let t=e===void 0?`/launch-child`:`/launch-child?port=${e}`;return this.postJson(t)}async shutdownChildren(e){let t=e===void 0?`/shutdown-children`:`/shutdown-children?port=${e}`;return this.postJson(t)}async recycleChildren(e){let t=e===void 0?`/recycle-children`:`/recycle-children?port=${e}`;return this.postJson(t)}async postJson(e){let r=await this.getText(e,{method:`POST`},t.LIFECYCLE_TIMEOUT_MS);return r===null?null:n(r)??null}monitor(n,r=5e3){if(this.ensureNotDisposed(),!Number.isFinite(r)||r<t.MIN_MONITOR_INTERVAL_MS)throw new e.T(`monitor() intervalMs must be a finite number >= ${t.MIN_MONITOR_INTERVAL_MS}ms, got ${r}. Sub-${t.MIN_MONITOR_INTERVAL_MS}ms polling would hot-loop the server.`,e.E.INVALID_CONFIG,{context:{intervalMs:r}});let i=!0,a=null;e.C().info(`🔄 Starting server stats monitoring every ${r}ms`);let o=async()=>{if(a=null,i&&!this.disposed){try{let t=await this.getServerStats();if(!i||this.disposed)return;try{n(t)}catch(t){e.C().error(`[ComputeServerStats] Monitor callback threw:`,t)}}catch(t){!i||this.disposed?e.C().debug(`[ComputeServerStats] Monitor poll cancelled during shutdown:`,t):e.C().error(`[ComputeServerStats] Failed to fetch stats during monitor:`,t)}i&&!this.disposed&&(a=setTimeout(()=>void o(),r))}},s=()=>{i=!1,a!==null&&(clearTimeout(a),a=null),this.activeMonitors.delete(s)};return this.activeMonitors.add(s),o(),s}async dispose(){if(!this.disposed){this.disposed=!0;for(let e of this.activeMonitors)e();this.activeMonitors.clear()}}ensureNotDisposed(){if(this.disposed)throw new e.T(`ComputeServerStats has been disposed and cannot be used`,e.E.INVALID_STATE)}};function n(e){try{return JSON.parse(e)}catch{return}}const r=new Set;function i(){if(typeof window>`u`||globalThis.process?.versions?.node!=null)return!1;let e=globalThis.navigator,t=typeof e?.userAgent==`string`?e.userAgent:``;return!/jsdom/i.test(t)}function a(t,n){n||i()&&!r.has(t)&&(r.add(t),e.C().warn(`Warning: ${t} is running on the client side. For better performance and security, consider running this on the server side.`))}const o={definition_not_cached:e.E.DEFINITION_NOT_CACHED};function s(e){return{...e,serverErrorCodes:{...o,...e.serverErrorCodes}}}function c(t){return t instanceof e.T?t.code===e.E.DEFINITION_NOT_CACHED||t.message.includes(`Unable to load grasshopper definition`):!1}function l(t,n){if(!n)return;let r=e.x(t,`values`);if(!Array.isArray(r)||r.length===0)return;let i=[];for(let t of r){let n=e.x(t,`innerTree`);(!n||Object.keys(n).length===0)&&i.push(e.x(t,`paramName`)??`<unnamed>`)}if(i.length===0)return;let a=i.length===r.length?`all`:`${i.length}/${r.length}`;e.C().warn(`Solve returned empty output(s) (${a}): ${i.join(`, `)}. These parameters produced no data — check the definition's inputs and the branch feeding each.`)}async function u(e,t,n){return a(`solveGrasshopperDefinition`,n.suppressBrowserWarning),(await f(e,t,n)).response}async function d(e,t,n,r){if(a(`solveWithServerCacheKey`,r.suppressBrowserWarning),t!==null)try{return{...await p({algo:null,pointer:t,values:e},r),missed:!1}}catch(e){if(!c(e))throw e}return{...await f(e,n,r),missed:!0}}async function f(e,t,n){return p(m(await ee(t),e),n)}async function ee(t){if(!e.s(t))return t;try{return await t.load()}catch(n){throw new e.T(`Failed to load definition bytes for ref '${t.key}'`,e.E.INVALID_INPUT,{context:{definitionKey:t.key},originalError:n})}}async function p(t,n){te(t,n);let r=await e.l(`grasshopper`,t,s(n)),{pointer:i,algo:a,...o}=r,c=o,u=e.u(r);if(u!==void 0){let t=typeof a==`string`?a.length:0;e.d(c,Math.max(0,u-t))}return l(c,n.debug),{response:c,cacheKey:typeof i==`string`?i:null}}function m(t,n){let r={algo:null,pointer:null,values:n};return t instanceof Uint8Array?r.algo=e.f(t):e.c(t)?r.pointer=t:r.algo=e.m(t)??e.h(t),r}function te(e,t){t.cachesolve!=null&&(e.cachesolve=t.cachesolve),t.cacheerroredsolves!=null&&(e.cacheerroredsolves=t.cacheerroredsolves),t.modelunits!=null&&(e.modelunits=t.modelunits),t.angletolerance!=null&&(e.angletolerance=t.angletolerance),t.absolutetolerance!=null&&(e.absolutetolerance=t.absolutetolerance),t.dataversion!=null&&(e.dataversion=t.dataversion),t.selvaevents!=null&&(e.selvaevents=t.selvaevents)}const h=/^\{(-?\d+(?:;-?\d+)*)?\}$/;function g(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.entries(e);return t.length>0&&t.every(([e,t])=>h.test(e)&&Array.isArray(t))}function _(e,t,n){if(e==null)return e;if(Array.isArray(e)){let n=e.map(t).filter(e=>e!==null);return n.length>0?n:void 0}let r=t(e);return r===null?n?void 0:e:r}const v=e=>{if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`){let t=e.trim();if(t===``||/^[+-]?0[xbo]/i.test(t))return null;let n=Number(t);return Number.isFinite(n)?n:null}return null},y=e=>{if(typeof e==`boolean`)return e;if(typeof e==`string`){let t=e.trim().toLowerCase();if(t===`true`)return!0;if(t===`false`)return!1}return null},ne=e=>typeof e==`string`?e.length>=2&&e.startsWith(`"`)&&e.endsWith(`"`)?e.slice(1,-1):e.startsWith(`"`)?e.slice(1):e:null,re=e=>{if(typeof e==`string`){let t=e.trim();return t.startsWith(`"`)&&t.endsWith(`"`)&&(t=t.slice(1,-1).trim()),t}return null};function ie(t){return n=>{if(typeof n==`object`&&n)return n;if(typeof n==`string`&&n.trim()!==``)try{let r=JSON.parse(n);return typeof r==`object`&&r?r:(e.C().warn(`Parsed value for input ${t} is not an object`),null)}catch(r){return e.C().warn(`Failed to parse object value "${n}" for input ${t}`,r),null}return null}}const ae=new Set([`System.Double`,`System.Single`,`System.Decimal`,`System.Int32`,`System.Int64`]),oe=new Set([`System.Int32`,`System.Int64`]);function b(t,n){return e.C().warn(n),{schema:{...t,default:null},warning:{code:e.E.MALFORMED_DEFAULT,message:n}}}function se(t,n){if(typeof t.default!=`object`||t.default===null||Array.isArray(t.default)||g(t.default))return{schema:t};if(!e.b(t.default,`innerTree`))return b(t,`Input "${n}" default had an unrecognized shape (no innerTree key); the default was dropped.`);let r=e.x(t.default,`innerTree`)??{};if(Object.keys(r).length===0)return{schema:{...t,default:void 0}};if(t.treeAccess||t.atMost&&t.atMost>1){let i={},a=[];for(let[o,s]of Object.entries(r)){if(!Array.isArray(s))return b(t,`Input "${n}" default had a non-array innerTree branch ("${o}"); the default was dropped.`);let r=[];for(let t of s){let n=e.x(t,`data`),i=e.x(t,`type`);if(i&&ae.has(i)){if(typeof n==`string`&&n.trim()===``)continue;let e=v(n);if(e===null){a.push(`"${String(n)}" (${i})`);continue}r.push(oe.has(i)?Math.round(e):e);continue}if(i===`System.Boolean`){let e=y(n);if(e===null){a.push(`"${String(n)}" (${i})`);continue}r.push(e);continue}if(typeof n==`string`&&i?.startsWith(`Rhino.Geometry`)){try{r.push(JSON.parse(n))}catch{r.push(n)}continue}r.push(n)}i[o]=r}if(a.length>0){let r=`Input "${n}" default contained ${a.length} tree value(s) that could not be parsed and were dropped: ${a.join(`, `)}.`;return e.C().warn(r),{schema:{...t,default:i},warning:{code:e.E.MALFORMED_DEFAULT,message:r}}}return{schema:{...t,default:i}}}let i=[];for(let t of Object.values(r))if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&e.b(n,`data`)&&i.push(e.x(n,`data`));return{schema:{...t,default:i.length>1?i:i[0]}}}function ce(e,t){let n=Number(e.toFixed(t));return Math.abs(e-n)<1e-8?n:e}function x(e){if(!Number.isFinite(e))return 0;let[t,n]=String(Math.abs(e)).split(`e`),r=n===void 0?Math.abs(e).toFixed(12).replace(/0+$/,``).split(`.`)[1]?.length??0:(t.split(`.`)[1]?.length??0)-Number(n);return Math.min(Math.max(r,0),12)}function le(e){if(!Number.isFinite(e)||e===0)return .1;let t=x(e);return t===0?Math.abs(e)>=1?1:.1:Number((10**-t).toFixed(t))}function ue(e){return typeof e.stepSize==`number`&&Number.isFinite(e.stepSize)&&e.stepSize>0?e.stepSize:void 0}const S=(e,t)=>(e.atMost??1)>1?[t]:t,C=e=>ue(e)??(e.paramType===`Integer`?1:.1),w=(e,t)=>Array.isArray(e)?e.map(e=>typeof e==`number`?t(e):e):typeof e==`number`?t(e):e;function de(t){if(g(t.default))return{default:t.default,stepSize:C(t)};if(typeof t.default==`string`&&t.default.trim()!==``&&v(t.default)===null)throw new e.T(`Invalid numeric default "${t.default}" for input "${t.name||`unknown`}"`,e.E.VALIDATION_ERROR,{context:{inputName:t.name,default:t.default}});let n=_(t.default,v,!0);if(t.paramType===`Integer`)return{default:w(n,Math.round),stepSize:C(t)};let r=Array.isArray(n)?n[0]:n,i=[r,t.minimum,t.maximum].find(e=>typeof e==`number`&&Number.isFinite(e)&&e!==0),a=ue(t)??(i===void 0?.1:le(i)),o=x(a);if(o===0&&typeof r==`number`&&r!==0&&Math.abs(r)<1){let e=Math.ceil(-Math.log10(Math.abs(r)));Number.isFinite(e)&&e>0&&(o=e)}return o=Math.min(Math.max(o,0),12),{default:w(n,e=>ce(e,o)),stepSize:a}}const T={parse(e,t){let{default:n,stepSize:r}=de(e);return{...t,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,stepSize:r,default:n}},fallback(e,t){let n=typeof e.minimum==`number`&&Number.isFinite(e.minimum)&&e.minimum>0?e.minimum:0;return{...t,paramType:e.paramType,minimum:e.minimum,maximum:e.maximum,atLeast:e.atLeast,atMost:e.atMost,stepSize:C(e),default:S(e,n)}}},fe={parse(t,n){if(g(t.default))return{...n,paramType:`Boolean`,default:t.default};let r=_(t.default,y,!1);if(r!=null&&typeof r!=`boolean`&&!Array.isArray(r))throw new e.T(`Invalid boolean default "${String(r)}" for input "${t.name||`unknown`}"`,e.E.VALIDATION_ERROR,{context:{inputName:t.name,default:t.default}});return{...n,paramType:`Boolean`,default:r}},fallback(e,t){return{...t,paramType:`Boolean`,default:S(e,!1)}}},pe={parse(e,t){let n=_(e.default,ne,!1);return{...t,paramType:`Text`,default:n}}},me={parse(t,n,r){if(!t.values||typeof t.values!=`object`||Object.keys(t.values).length===0){let n=t.nickname||`unnamed`;throw new e.T(`Input "${n}" has no values defined (expected ValueList)`,e.E.INVALID_INPUT,{context:{inputName:n,expectedType:`ValueList`}})}let i=t.default;if(t.default!==void 0&&t.default!==null){if(typeof t.default==`object`)throw new e.T(`ValueList input "${t.nickname||`unnamed`}" default is not a string-able value`,e.E.VALIDATION_ERROR,{context:{inputName:t.name,default:t.default}});let n=String(t.default).toLowerCase(),a=Object.keys(t.values).find(e=>e.toLowerCase()===n);if(a!==void 0)i=a;else{let n=`ValueList input "${t.nickname||`unnamed`}" default value "${t.default}" is not in available values`;e.C().warn(n),r?.({code:e.E.VALIDATION_ERROR,message:n})}}return{...n,paramType:`ValueList`,values:t.values,default:i}},fallback(e,t){return{...t,paramType:`ValueList`,values:e.values&&typeof e.values==`object`?e.values:{},default:void 0}}};function E(e,t){return{...t,paramType:`Geometry`,default:S(e,null)}}const D=new Map([[`Number`,T],[`Integer`,T],[`Boolean`,fe],[`Text`,pe],[`ValueList`,me],[`Geometry`,{parse(e,t){let n=_(e.default,ie(e.nickname||`unnamed`),!0);return{...t,paramType:`Geometry`,default:n}},fallback:E}],[`File`,{parse(e,t){let n=_(e.default,ie(e.nickname||`unnamed`),!0);return{...t,paramType:`File`,acceptedFormats:e.acceptedFormats,default:n}}}],[`Color`,{parse(e,t){let n=_(e.default,re,!1);return{...t,paramType:`Color`,default:n}}}]]),he=E,ge=new Map([...D.keys()].map(e=>[e.toLowerCase(),e]));function _e(e){return ge.get(e?.toLowerCase())??e}function ve(e){return O(e).input}function O(t){let n=t.name||`unknown`,r=[],i=({code:e,message:i})=>{r.push({inputName:n,paramType:t.paramType,message:i,code:e})},a={description:t.description,name:t.name,nickname:t.nickname,treeAccess:t.treeAccess,groupName:t.groupName??void 0,id:t.id},o=_e(t.paramType),s={...t,paramType:o};try{let{schema:e,warning:t}=se(s,n);s=e,t&&i(t)}catch(t){s={...s,default:null},i({code:e.E.MALFORMED_DEFAULT,message:`Input "${n}" default could not be normalized and was dropped: ${t instanceof Error?t.message:String(t)}`})}let c=D.get(o);try{if(!c)throw new e.T(`Unknown paramType: ${o}`,e.E.VALIDATION_ERROR,{context:{receivedParamType:o,paramName:t.name}});return{input:c.parse(s,a,i),errors:r}}catch(l){if(!(l instanceof e.T))throw new e.T(l instanceof Error?l.message:String(l),e.E.VALIDATION_ERROR,{context:{paramName:t.name,paramType:o},originalError:l});return e.C().error(`Validation error for input ${n}:`,l.message),i(l),{input:(c?.fallback??he)(s,a),errors:r}}}function ye(e){let t=[],n=[];for(let r of e){let{input:e,errors:i}=O(r);t.push(e),n.push(...i)}return{inputs:t,parseErrors:n}}function be(t){let n=e.x(t,`stepSize`);return{id:e.x(t,`id`)??``,name:e.x(t,`name`)??``,nickname:e.x(t,`nickname`)??null,description:e.x(t,`description`)??``,paramType:e.x(t,`paramType`)??``,treeAccess:e.x(t,`treeAccess`)??!1,minimum:e.x(t,`minimum`)??null,maximum:e.x(t,`maximum`)??null,atLeast:e.x(t,`atLeast`)??1,atMost:e.x(t,`atMost`)??1,stepSize:typeof n==`number`&&Number.isFinite(n)?n:void 0,default:e.x(t,`default`),values:e.x(t,`values`),acceptedFormats:e.x(t,`acceptedFormats`),groupName:e.x(t,`groupName`)??null}}function xe(t){return{name:e.x(t,`name`)??``,nickname:e.x(t,`nickname`)??null,paramType:e.x(t,`paramType`)??``,id:e.x(t,`id`)??``}}async function k(t,n){a(`fetchDefinitionIO`,n.suppressBrowserWarning);let{algo:r,pointer:i}=m(t,[]);if(!r&&!i)throw new e.T(`Definition must resolve to either a URL pointer or base64 algo`,e.E.INVALID_INPUT);let o=await e.l(`io`,r?{algo:r}:{pointer:i},s(n));if(!o||typeof o!=`object`)throw new e.T(`Invalid IO response structure`,e.E.INVALID_INPUT,{context:{response:o}});let c=A(e.x(o,`warnings`)),l=A(e.x(o,`errors`)),u=e.x(o,`inputs`),d=e.x(o,`outputs`);return{inputs:Array.isArray(u)?u.map(be):[],outputs:Array.isArray(d)?d.map(xe):[],...c&&{loadWarnings:c},...l&&{loadErrors:l}}}function A(e){if(!Array.isArray(e))return;let t=e.map(Se).filter(e=>e!==void 0);return t.length>0?t:void 0}function Se(t){if(t==null)return;let n;if(typeof t==`string`)n=t;else if(typeof t==`object`){let r=e.x(t,`message`);if(typeof r==`string`&&r.trim().length>0)n=r;else try{n=JSON.stringify(t)??String(t)}catch{n=String(t)}}else n=String(t);return n.trim().length>0?n:void 0}async function j(e,t){let{inputs:n,outputs:r,loadWarnings:i,loadErrors:a}=await k(e,t),{inputs:o,parseErrors:s}=ye(n);return{inputs:o,outputs:r,...s.length>0&&{parseErrors:s},...i&&{loadWarnings:i},...a&&{loadErrors:a}}}function M(e){let t=new WeakSet,n=e=>{if(e===void 0)return`undefined`;if(e===null)return`null`;if(typeof e==`number`)return Number.isFinite(e)?String(e):`null`;if(typeof e==`string`||typeof e==`boolean`)return JSON.stringify(e);if(typeof e==`bigint`)return`${e}n`;if(e instanceof Uint8Array)return`{"__u8":${e.length},"hash":"${F(e)}"}`;if(Array.isArray(e)){if(t.has(e))return`"[Circular]"`;t.add(e);let r=[];for(let t=0;t<e.length;t++)r.push(n(e[t]));return t.delete(e),`[${r.join(`,`)}]`}if(typeof e==`object`){if(t.has(e))return`"[Circular]"`;t.add(e);let r;return r=typeof e.toJSON==`function`?n(e.toJSON()):e instanceof Map?`{"__map":[${[...e.entries()].map(([e,t])=>`[${n(e)},${n(t)}]`).sort().join(`,`)}]}`:e instanceof Set?`{"__set":[${[...e.values()].map(n).sort().join(`,`)}]}`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${n(e[t])}`).join(`,`)}}`,t.delete(e),r}return`null`};return n(e)}function N(e,t){let n=2166136261;for(let r=0;r<e;r++)n^=t(r),n=Math.imul(n,16777619)>>>0;return n.toString(16).padStart(8,`0`)}function P(e){return N(e.length,t=>e.charCodeAt(t))}function F(e){return N(e.length,t=>e[t])}function Ce(e,t){return I(L(e),t)}function I(e,t){let n=M(t);return`${e}|t:${n.length}:${P(n)}`}function L(t){return e.s(t)?`r:${t.key}`:typeof t==`string`?`s:${t.length}:${P(t)}`:`u8:${t.length}:${F(t)}`}const R=new WeakMap;function we(e){if(!(e instanceof Uint8Array))return L(e);let t=R.get(e);return t===void 0&&(t=L(e),R.set(e,t)),t}function Te(e){try{return JSON.stringify(e)?.length??0}catch{return 0}}var z=class{executor;baseConfig;mode;maxConcurrent;maxQueueDepth;queueWaitMs;timeoutMs;retry;cacheEnabled;cacheMaxBytes;cacheTtl;cacheErroredSolves;cache=new Map;cacheBytes=0;cacheHits=0;cacheMisses=0;cacheEvictions=0;reuseServerDefinitionCache;serverCacheKeys=new Map;onStart;onSettle;onSuperseded;subscribers=new Set;inFlight=new Set;pendingForLatestWins=null;fifoQueue=[];_lastResult=null;_lastError=null;_lastDurationMs=null;solveSeq=0;lastStateSeq=0;disposed=!1;constructor(t,n,r={}){if(this.executor=t,this.baseConfig=n,this.mode=r.mode??`latest-wins`,this.mode!==`latest-wins`&&this.mode!==`queue`)throw new e.T(`Unknown scheduler mode '${String(this.mode)}'. For concurrent solves use { mode: 'queue', maxConcurrent: 4 }.`,e.E.INVALID_CONFIG,{context:{mode:this.mode}});this.maxConcurrent=Math.max(1,r.maxConcurrent??1),this.maxQueueDepth=r.maxQueueDepth!==void 0&&r.maxQueueDepth>0?Math.floor(r.maxQueueDepth):void 0,this.queueWaitMs=r.queueWaitMs!==void 0&&r.queueWaitMs>0?r.queueWaitMs:void 0,this.timeoutMs=r.timeoutMs,this.retry=r.retry;let i=r.cache,a=typeof i==`object`?i:null;this.cacheMaxBytes=Math.max(0,a?.maxBytes??0),this.cacheEnabled=this.cacheMaxBytes>0,this.cacheTtl=a?.ttlMs??0,this.cacheErroredSolves=a?.cacheErroredSolves??!0,this.reuseServerDefinitionCache=r.reuseServerDefinitionCache??!0,this.onStart=r.onStart,this.onSettle=r.onSettle,this.onSuperseded=r.onSuperseded}get isSolving(){return this.inFlight.size>0}get hasPending(){return this.pendingForLatestWins!==null||this.fifoQueue.length>0}get inFlightCount(){return this.inFlight.size}get queueDepth(){return this.fifoQueue.length+ +!!this.pendingForLatestWins}get lastResult(){return this._lastResult}get lastError(){return this._lastError}get lastDurationMs(){return this._lastDurationMs}setMaxConcurrent(e){let t=Math.max(1,Math.floor(e));if(t===this.maxConcurrent)return;let n=t>this.maxConcurrent;this.maxConcurrent=t,n&&this.drainNext()}getMaxConcurrent(){return this.maxConcurrent}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){for(let t of this.subscribers)try{t()}catch(t){e.C().error(`[SolveScheduler] subscriber threw:`,t)}}solve(e,t,n){return this.solveDetailed(e,t,n).then(e=>e.response)}solveDetailed(t,n,r){if(this.disposed)return Promise.reject(new e.T(`SolveScheduler has been disposed and cannot be used`,e.E.INVALID_STATE));let i=we(t),a=I(i,n),o=++this.solveSeq,s={key:a,enqueuedAt:Date.now(),startedAt:null};if(r?.signal?.aborted)return Promise.reject(this.makeAbortError(s));let c=this.readCache(a);if(c){this.mode===`latest-wins`&&this.supersedeCurrent();let e={status:`success`,response:c,durationMs:0,fromCache:!0};return this.writeLastState(o,{result:c,durationMs:0}),this.runHook(this.onStart,s),this.runHook(this.onSettle,s,e),this.notify(),Promise.resolve({response:c,fromCache:!0,durationMs:0})}return new Promise((e,a)=>{let c={definition:t,dataTree:n,definitionHash:i,ctx:s,seq:o,resolve:e,reject:a,externalSignal:r?.signal,selvaevents:r?.selvaevents,onServerTiming:r?.onServerTiming};c.externalSignal&&(c.queuedAbortHandler=()=>this.abortQueuedItem(c),c.externalSignal.addEventListener(`abort`,c.queuedAbortHandler,{once:!0})),this.enqueue(c)})}writeLastState(e,t){e<this.lastStateSeq||(this.lastStateSeq=e,`result`in t?(this._lastResult=t.result,this._lastError=null):this._lastError=t.error,this._lastDurationMs=t.durationMs)}supersedeCurrent(){this.pendingForLatestWins&&=(this.supersede(this.pendingForLatestWins),null);for(let e of this.inFlight)this.supersede(e),e.controller.abort()}dequeue(e){this.pendingForLatestWins===e&&(this.pendingForLatestWins=null);let t=this.fifoQueue.indexOf(e);t>=0&&this.fifoQueue.splice(t,1)}abortQueuedItem(e){this.dequeue(e),this.fail(e,this.makeAbortError(e.ctx)),this.notify()}shedAsQueueFull(t){let n=new e.T(`Solve queue is full; request rejected (backpressure)`,e.E.QUEUE_FULL,{statusCode:503,context:{key:t.ctx.key,queueDepth:this.fifoQueue.length,maxQueueDepth:this.maxQueueDepth}});this.fail(t,n),this.notify()}armQueueWaitTimer(t){if(this.queueWaitMs===void 0)return;let n=this.queueWaitMs;t.queueWaitTimer=setTimeout(()=>{if(t.settled)return;this.dequeue(t);let r=new e.T(`Solve waited longer than ${n}ms in queue; rejected (backpressure)`,e.E.QUEUE_TIMEOUT,{statusCode:503,context:{key:t.ctx.key,waitedMs:Date.now()-t.ctx.enqueuedAt,queueWaitMs:n}});this.fail(t,r),this.notify()},n)}clearQueueWaitTimer(e){e.queueWaitTimer!==void 0&&(clearTimeout(e.queueWaitTimer),e.queueWaitTimer=void 0)}enqueue(e){switch(this.mode){case`latest-wins`:this.supersedeCurrent(),this.inFlight.size===0?this.execute(e):this.pendingForLatestWins=e;break;case`queue`:this.inFlight.size<this.maxConcurrent?this.execute(e):this.maxQueueDepth!==void 0&&this.fifoQueue.length>=this.maxQueueDepth?this.shedAsQueueFull(e):(this.armQueueWaitTimer(e),this.fifoQueue.push(e))}this.notify()}async execute(e){let t=new AbortController,n=e;n.controller=t,this.inFlight.add(n),e.ctx.startedAt=Date.now(),this.clearQueueWaitTimer(e),this.removeQueuedAbortHandler(e);let r=()=>t.abort();e.externalSignal?.addEventListener(`abort`,r,{once:!0}),this.runHook(this.onStart,e.ctx),this.notify();let i=performance.now();try{let n={...this.baseConfig,signal:t.signal,...this.timeoutMs!==void 0&&{timeoutMs:this.timeoutMs},...this.retry!==void 0&&{retry:this.retry},...e.selvaevents!==void 0&&{selvaevents:e.selvaevents}},r=e.onServerTiming;if(r){let e=this.baseConfig.onServerTiming;n.onServerTiming=(t,n)=>{try{e?.(t,n)}finally{r(t,n)}}}let{response:a,definitionReuploaded:o}=await this.runExecutor(e.definition,e.dataTree,e.definitionHash,n),s=performance.now()-i;if(this.writeCache(e.ctx.key,a),!this.settleSuccess(e,{response:a,fromCache:!1,definitionReuploaded:o,durationMs:s}))return;this.writeLastState(e.seq,{result:a,durationMs:s}),this.runHook(this.onSettle,e.ctx,{status:`success`,response:a,durationMs:s,fromCache:!1,definitionReuploaded:o})}catch(t){let r=performance.now()-i,a=this.normalizeExecutionError(t,n);this.writeLastState(e.seq,{error:a,durationMs:r}),this.fail(e,a,r)}finally{e.externalSignal?.removeEventListener(`abort`,r),this.inFlight.delete(n),this.drainNext(),this.notify()}}async runExecutor(t,n,r,i){if(!this.reuseServerDefinitionCache||e.c(t)){let{response:e}=await this.executor(t,n,null,i);return{response:e}}let a=this.serverCacheKeys.get(r)??null,o=await this.executor(t,n,a,i);return this.serverCacheKeys.delete(r),o.cacheKey&&(this.serverCacheKeys.set(r,o.cacheKey),this.serverCacheKeys.size>100&&this.serverCacheKeys.delete(this.serverCacheKeys.keys().next().value)),{response:o.response,definitionReuploaded:o.missed}}drainNext(){if(!this.disposed){if(this.mode===`latest-wins`){if(this.pendingForLatestWins&&this.inFlight.size===0){let e=this.pendingForLatestWins;this.pendingForLatestWins=null,this.execute(e)}return}for(;this.fifoQueue.length>0&&this.inFlight.size<this.maxConcurrent;){let e=this.fifoQueue.shift();this.execute(e)}}}supersede(t){let n=new e.T(`Superseded by newer solve`,e.E.SUPERSEDED,{context:{key:t.ctx.key,enqueuedAt:t.ctx.enqueuedAt}});this.settleError(t,n)&&this.runHook(this.onSuperseded,t.ctx)}makeAbortError(t){return new e.T(`Request aborted by caller`,e.E.ABORTED,{context:{key:t.key,enqueuedAt:t.enqueuedAt}})}settleError(e,t){return!e.settled&&(e.settled={error:t},this.clearQueueWaitTimer(e),this.removeQueuedAbortHandler(e),e.reject(t),!0)}fail(e,t,n=0){this.settleError(e,t)&&this.runHook(this.onSettle,e.ctx,{status:`error`,error:t,durationMs:n})}settleSuccess(e,t){return!e.settled&&(e.settled={ok:!0},this.clearQueueWaitTimer(e),this.removeQueuedAbortHandler(e),e.resolve(t),!0)}removeQueuedAbortHandler(e){e.queuedAbortHandler&&e.externalSignal&&e.externalSignal.removeEventListener(`abort`,e.queuedAbortHandler),e.queuedAbortHandler=void 0}normalizeExecutionError(t,n){return n.settled&&`error`in n.settled?n.settled.error:t instanceof e.T?t:t instanceof Error&&t.name===`AbortError`?this.makeAbortError(n.ctx):new e.T(t instanceof Error?t.message:String(t),e.E.UNKNOWN_ERROR,{originalError:t})}cancelAll(){for(this.pendingForLatestWins&&=(this.fail(this.pendingForLatestWins,this.makeAbortError(this.pendingForLatestWins.ctx)),null);this.fifoQueue.length>0;){let e=this.fifoQueue.shift();this.fail(e,this.makeAbortError(e.ctx))}for(let e of this.inFlight){let t=e.ctx.startedAt?Date.now()-e.ctx.startedAt:0;this.fail(e,this.makeAbortError(e.ctx),t),e.controller.abort()}this.notify()}readCache(e){if(!this.cacheEnabled)return null;let t=this.cache.get(e);return t?this.cacheTtl>0&&Date.now()-t.insertedAt>this.cacheTtl?(this.dropCacheEntry(e),this.cacheMisses+=1,null):(this.cache.delete(e),this.cache.set(e,t),this.cacheHits+=1,t.response):(this.cacheMisses+=1,null)}writeCache(t,n){if(!this.cacheEnabled)return;let r=e.x(n,`errors`);if(!this.cacheErroredSolves&&Array.isArray(r)&&r.length>0)return;let i=e.u(n)??Te(n);if(!(i>this.cacheMaxBytes))for(this.dropCacheEntry(t),this.cache.set(t,{response:n,insertedAt:Date.now(),sizeBytes:i}),this.cacheBytes+=i;this.cacheBytes>this.cacheMaxBytes&&this.cache.size>0;){let e=this.cache.keys().next().value;if(e===void 0)break;this.dropCacheEntry(e),this.cacheEvictions+=1}}dropCacheEntry(e){let t=this.cache.get(e);t&&(this.cache.delete(e),this.cacheBytes-=t.sizeBytes)}clearCache(){this.cache.clear(),this.cacheBytes=0}cacheStats(){return{entries:this.cache.size,bytes:this.cacheBytes,hits:this.cacheHits,misses:this.cacheMisses,evictions:this.cacheEvictions}}dispose(){this.disposed||(this.disposed=!0,this.cancelAll(),this.subscribers.clear(),this.clearCache())}runHook(t,...n){if(t)try{t(...n)}catch(t){e.C().error(`[SolveScheduler] hook threw:`,t)}}};function B(t){return e.s(t)?`ref:${t.key}`:typeof t==`string`&&t.length<200?t:`...content...`}function V(t){return Array.isArray(t)?t.map(t=>{let n=0,r=0,i=e.x(t,`innerTree`);if(i&&typeof i==`object`){for(let e of Object.values(i))if(Array.isArray(e)){n+=e.length;for(let t of e){let e=t?.data;typeof e==`string`&&(r+=e.length)}}}return{param:e.x(t,`paramName`)??`<unnamed>`,items:n,bytes:r}}):[]}var Ee=class n{config;serverStats;disposed=!1;static CREATE_PROBE_TIMEOUT_MS=2e3;constructor(n){this.config={...n,serverUrl:e.y(n.serverUrl),debug:n.debug??!1},this.serverStats=new t(this.config.serverUrl,this.config)}static async create(t,r={}){let i=new n(t),a=Math.max(1,(r.probe?.attempts??2)+1),o=r.probe?.baseDelayMs??250,s=r.probe?.maxDelayMs??1e3,c,l=null,u=0;for(let t=0;t<a;t++){if(u=t+1,c=await i.serverStats.probeServer(n.CREATE_PROBE_TIMEOUT_MS),c.online)return i;if(l=e.g(c),l&&!l.retryable)break;if(t<a-1){let e=Math.min(o*2**t,s);await new Promise(t=>setTimeout(t,e))}}await i.dispose();let d=c?.status,f=l?`Rhino Compute server is not available. ${l.summary}`:`Rhino Compute server is not online`;throw new e.T(f,e.E.NETWORK_ERROR,{...d!==void 0&&{statusCode:d},context:{serverUrl:i.config.serverUrl,attempts:u,maxAttempts:a,...l&&{probeVerdict:l.verdict,probeRetryable:l.retryable},...d!==void 0&&{lastProbeStatus:d},...c?.error!==void 0&&{lastProbeError:c.error}}})}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(e){return this.ensureNotDisposed(),j(e,this.config)}async getRawIO(e){return this.ensureNotDisposed(),k(e,this.config)}async solve(t,n,r){this.ensureNotDisposed();try{if(typeof t==`string`&&!t.trim())throw new e.T(`Definition URL/content is required`,e.E.INVALID_INPUT,{context:{receivedUrl:t}});if(t instanceof Uint8Array&&t.length===0)throw new e.T(`Definition content is empty`,e.E.INVALID_INPUT);if(e.s(t)&&!t.key.trim())throw new e.T(`DefinitionRef key is empty`,e.E.INVALID_INPUT);let i=await u(n,t,{...this.config,...r?.signal!==void 0&&{signal:r.signal},...r?.timeoutMs!==void 0&&{timeoutMs:r.timeoutMs},...r?.retry!==void 0&&{retry:r.retry},...r?.selvaevents!==void 0&&{selvaevents:r.selvaevents}}),a=e.x(i,`errors`);if(Array.isArray(a)&&a.length>0)throw new e.T(a.map(String).join(`; `)||`Computation failed`,e.E.COMPUTATION_ERROR,{context:{definition:B(t),inputSummary:V(n),errors:a,warnings:e.x(i,`warnings`),values:i.values}});return i}catch(r){throw this.config.debug&&e.C().error(`Compute failed:`,r),r instanceof e.T?r:new e.T(r instanceof Error?r.message:String(r),e.E.COMPUTATION_ERROR,{context:{definition:B(t),inputSummary:V(n)},originalError:r})}}createScheduler(e){return this.ensureNotDisposed(),new z((e,t,n,r)=>d(t,n,e,r),this.config,e)}async dispose(){this.disposed||(this.disposed=!0,await this.serverStats.dispose())}ensureNotDisposed(){if(this.disposed)throw new e.T(`GrasshopperClient has been disposed and cannot be used`,e.E.INVALID_STATE)}};function De(e){return typeof e==`object`&&!!e&&e.__decodeError===!0}function H(e,t){return{__decodeError:!0,type:e,raw:t}}function U(e){let t=new WeakSet,n=e=>{if(!e||typeof e!=`object`||t.has(e))return;t.add(e);let r=e.delete;if(typeof r==`function`){let t=e.isDeleted;(typeof t!=`function`||!t.call(e))&&r.call(e);return}if(Array.isArray(e)){for(let t of e)n(t);return}let i=Object.getPrototypeOf(e);if(i===Object.prototype||i===null)for(let t of Object.values(e))n(t)};n(e)}const W=new Map([[`Rhino.Geometry.Point3d`,(e,t)=>{let n=t;return!n||typeof n.X!=`number`?null:new e.Point([n.X,n.Y,n.Z])}],[`Rhino.Geometry.Line`,(e,t)=>{let n=t;return!n||!n.From||!n.To?null:new e.Line([n.From.X,n.From.Y,n.From.Z],[n.To.X,n.To.Y,n.To.Z])}]]);function Oe(e){if(W.has(e))return W.get(e);for(let[t,n]of W)if(e.startsWith(t))return n}function ke(e){return!!(e&&typeof e==`object`&&typeof e.data==`string`)}function Ae(t,n,r){let i=Oe(n),a=!1;if(i)try{let e=i(r,t);if(e!=null)return e}catch(t){e.C().warn(`Failed to decode Rhino type ${n}:`,t),a=!0}try{if(ke(t))return r.CommonObject.decode(t)}catch(r){return e.C().warn(`Failed to decode ${n} with CommonObject:`,r),H(n,t)}return a?H(n,t):t}const G={STRING:`System.String`,INT:`System.Int32`,DOUBLE:`System.Double`,BOOL:`System.Boolean`},K=`FileData`;function q(e,t){return e.includes(`WebDisplay`)||t&&e!==G.STRING}function J(e){if(typeof e!=`string`)return e;let t=e.trim();if(!(t.startsWith(`{`)||t.startsWith(`[`)||t.startsWith(`"`)))return e;try{let e=JSON.parse(t);if(typeof e==`string`)try{return JSON.parse(e)}catch{return e}return e}catch{return e}}function je(e,t,n){switch(t){case G.STRING:return typeof e==`string`?e.replace(/^"(.*)"$/,`$1`):e;case G.INT:return Number.parseInt(String(e),10);case G.DOUBLE:return Number.parseFloat(String(e));case G.BOOL:return String(e).toLowerCase()===`true`;default:return n&&t.startsWith(`Rhino.Geometry.`)?Ae(e,t,n):e}}function Y(e,t,n,r){if(typeof e.data!=`string`)return e.data;let i=n?J(e.data):e.data;return n&&t.includes(K)?Me(i)??i:je(i,t,r)}function Me(t){if(!t||typeof t!=`object`)return null;let n=e.x(t,`fileName`),r=e.x(t,`fileType`),i=e.x(t,`subFolder`),a=e.x(t,`isBase64Encoded`);if(typeof n!=`string`||typeof r!=`string`||typeof i!=`string`||!e.b(t,`data`)||typeof a!=`boolean`&&typeof a!=`string`)return null;let o=e.x(t,`metadata`);return{fileName:n,fileType:r,data:e.x(t,`data`),isBase64Encoded:e.i(a),subFolder:i,...o?{metadata:o}:{}}}function X(t){let n=e.x(t,`values`);return Array.isArray(n)?n:[]}function Z(e){return typeof e.type==`string`?e.type:``}function Q(e,t){if(e&&typeof e==`object`){for(let n of Object.values(e))if(Array.isArray(n))for(let e of n)e&&typeof e==`object`&&t(e)}}function Ne(t,n=!1,r={}){let{parseValues:i=!0,rhino:a,stringOnly:o=!1}=r,s={},c=new Set;for(let r of X(t)){let t=e.x(r,`paramName`);Q(e.x(r,`innerTree`),e=>{let r=Z(e);if(q(r,o))return;let l=n?e.id:t;if(!l)return;let u=Y(e,r,i,a);l in s?c.has(l)?s[l].push(u):(s[l]=[s[l],u],c.add(l)):s[l]=u})}return{values:s,dispose:()=>U(s)}}function Pe(t){let n=[];for(let r of X(t))Q(e.x(r,`innerTree`),e=>{if(!Z(e).includes(K))return;let t=Me(J(e.data));t&&n.push(t)});return n}function Fe(t,n,r={}){let{parseValues:i=!0,rhino:a,stringOnly:o=!1}=r;for(let r of X(t)){let t=e.x(r,`innerTree`),s=!1;if(`byName`in n){if(e.x(r,`paramName`)!==n.byName)continue;s=!0}let c=[];if(Q(t,e=>{if(`byId`in n){if(e.id!==n.byId)return;s=!0}let t=Z(e);q(t,o)||c.push(Y(e,t,i,a))}),s)return c.length===0?void 0:c.length===1?c[0]:c}}var Ie=class{response;constructor(e){this.response=e}getValues(e=!1,t={}){return Ne(this.response,e,t)}getValue(e,t){return Fe(this.response,e,t)}async getAndDownloadFiles(t,n){await e.t(Pe(this.response),t,n)}};function Le(t){return(Array.isArray(t)?t:[t]).map(t=>({schemas:e.x(t,`schemas`),error:e.x(t,`error`)}))}const Re=new Set([`options`,`defaultOptions`,`values`]),ze=e=>e>=`A`&&e<=`Z`;function Be(e){if(e.length===0||!ze(e[0]))return e;let t=0;for(;t<e.length&&ze(e[t]);)t++;return t>1&&t<e.length&&t--,e.slice(0,t).toLowerCase()+e.slice(t)}function Ve(e){return $(e)}function $(e){if(Array.isArray(e))return e.map($);if(typeof e!=`object`||!e)return e;let t={};for(let[n,r]of Object.entries(e)){let e=Be(n);t[e]=Re.has(e)?r:$(r)}return t}var He=class t{innerTree;paramName;constructor(e){this.paramName=e,this.innerTree={}}append(e,n){let r=t.formatPathString(e);this.innerTree[r]||(this.innerTree[r]=[]);let i=n.map(e=>({data:t.serializeValue(e)}));return this.innerTree[r].push(...i),this}fromDataTreeDefault(e){this.innerTree={};for(let[n,r]of Object.entries(e)){if(!Array.isArray(r))continue;let e=t.parsePathString(n);this.append(e,r)}return this}appendFlat(e){let t=Array.isArray(e)?e:[e];return this.append([0],t)}flatten(){let e=[];for(let n of Object.values(this.innerTree))if(Array.isArray(n))for(let r of n)e.push(t.deserializeValue(r.data));return e}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getParamName(){return this.paramName}static fromInputParams(e){return t.fromValues(e.map(e=>({paramName:e.nickname||`unnamed`,paramType:e.paramType,value:e.default,...`minimum`in e&&{minimum:e.minimum,maximum:e.maximum}})))}static fromValues(n){let r=[];for(let i of n){let n=new t(i.paramName),a=t.itemCoercer(i);for(let[r,o]of t.branchesOf(i.value)){let t=[];for(let n of o){if(n==null)continue;let r=a(n);r===null?e.C().warn(`${i.paramName}: dropped an item that is not a valid ${i.paramType}`):t.push(r)}t.length>0&&n.append(r,t)}Object.keys(n.innerTree).length>0&&r.push(n.toComputeFormat())}return r}static branchesOf(e){return t.hasValidValue(e)?g(e)?Object.entries(e).map(([e,n])=>[t.parsePathString(e),n]):[[[0],Array.isArray(e)?e:[e]]]:[]}static itemCoercer(e){let{paramName:n,minimum:r,maximum:i}=e,a=e.paramType.toLowerCase();return a===`number`||a===`integer`?e=>{let o=v(e);if(o===null)return null;let s=a===`integer`?Math.round(o):o;return t.clampValue(s,r,i,n)}:a===`boolean`?y:e=>e}static replaceTreeValue(e,n,r){let i=t.buildFromValue(n,r).toComputeFormat(),a=e.slice(),o=a.findIndex(e=>t.paramNameOf(e)===n);return o===-1?a.push(i):a[o]=i,a}static buildFromValue(e,n){let r=new t(e);return g(n)?r.fromDataTreeDefault(n):r.appendFlat(n),r}static getTree(n,r){let i=n.find(e=>t.paramNameOf(e)===r);if(!i)return null;let a=new Map,o=e.x(i,`InnerTree`);if(!o||typeof o!=`object`)return a;for(let[e,n]of Object.entries(o))Array.isArray(n)&&a.set(e,n.map(e=>e?.data===void 0?null:t.deserializeValue(e.data)));return a}static getTreeValue(n,r){let i=t.getTree(n,r);if(!i||i.size===0)return null;if(i.size>1)throw new e.T(`"${r}" has ${i.size} branches; read it with TreeBuilder.getTree`,e.E.INVALID_INPUT,{context:{paramName:r,branchCount:i.size}});let[a]=i.values();return a.length===0?null:a.length===1?a[0]:a}static paramNameOf(t){return e.x(t,`ParamName`)}static parsePathString(t){let n=t.match(h);if(!n)throw new e.T(`Invalid Grasshopper tree path: "${t}". Expected "{}", "{0}", or "{0;1;2}" (negative indices allowed, no empty segments).`,e.E.INVALID_INPUT,{context:{pathStr:t}});return n[1]?n[1].split(`;`).map(Number):[]}static formatPathString(e){return`{${e.join(`;`)}}`}static serializeValue(e){return typeof e==`boolean`||typeof e==`number`||typeof e==`string`?e:typeof e==`object`&&e?JSON.stringify(e):String(e)}static deserializeValue(e){if(typeof e!=`string`)return e;if(e.startsWith(`{`)||e.startsWith(`[`))try{return JSON.parse(e)}catch{return e}let t=Number(e);return Number.isFinite(t)&&String(t)===e?t:e===`true`||e!==`false`&&e}static hasValidValue(e){return e==null?!1:typeof e==`string`||!(Array.isArray(e)&&e.length===0||typeof e==`object`&&!Array.isArray(e)&&Object.keys(e).length===0)}static clampValue(t,n,r,i){let a=t;return n!=null&&a<n&&(e.C().warn(`${i}: ${t} below min ${n}, clamping`),a=n),r!=null&&a>r&&(e.C().warn(`${i}: ${t} above max ${r}, clamping`),a=r),a}};exports.ComputeServerStats=t,exports.GrasshopperClient=Ee,exports.GrasshopperResponseProcessor=Ie,exports.SolveScheduler=z,exports.TreeBuilder=He,exports.disposeRhinoObjects=U,exports.fetchDefinitionIO=k,exports.fetchParsedDefinitionIO=j,exports.hashDefinition=L,exports.hashSolveInput=Ce,exports.isRhinoDecodeError=De,exports.normalizeUISchemaCasing=Ve,exports.processInput=ve,exports.readSchemaResults=Le,exports.solveGrasshopperDefinition=u,exports.stableStringify=M;
2
2
  //# sourceMappingURL=grasshopper.cjs.map