@selvajs/compute 4.0.0-beta.0 → 4.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/chunk-AYH5O3VG.js +4 -0
- package/dist/chunk-AYH5O3VG.js.map +1 -0
- package/dist/chunk-MLPWPV6F.cjs +4 -0
- package/dist/chunk-MLPWPV6F.cjs.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +81 -56
- package/dist/core.d.ts +81 -56
- package/dist/core.js +1 -1
- package/dist/grasshopper.cjs +1 -1
- package/dist/grasshopper.cjs.map +1 -1
- package/dist/grasshopper.d.cts +400 -81
- package/dist/grasshopper.d.ts +400 -81
- package/dist/grasshopper.js +1 -1
- package/dist/grasshopper.js.map +1 -1
- package/dist/handle-files-DMK9bCOW.d.cts +231 -0
- package/dist/handle-files-DMK9bCOW.d.ts +231 -0
- package/dist/index.cjs +1 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +0 -1
- package/package.json +1 -1
- package/dist/chunk-G7NVQAK5.cjs +0 -2
- package/dist/chunk-G7NVQAK5.cjs.map +0 -1
- package/dist/chunk-LLUNR66G.cjs +0 -4
- package/dist/chunk-LLUNR66G.cjs.map +0 -1
- package/dist/chunk-RFFCVRKM.js +0 -2
- package/dist/chunk-RFFCVRKM.js.map +0 -1
- package/dist/chunk-XT3XWDDV.js +0 -4
- package/dist/chunk-XT3XWDDV.js.map +0 -1
- package/dist/handle-files-DcA24IkS.d.cts +0 -478
- package/dist/handle-files-DcA24IkS.d.ts +0 -478
package/dist/grasshopper.d.cts
CHANGED
|
@@ -1,5 +1,309 @@
|
|
|
1
|
-
import { C as ComputeConfig,
|
|
2
|
-
export { c as FileData, P as ProcessedFile, f as downloadFileData, g as extractFilesFromComputeResponse } from './handle-files-
|
|
1
|
+
import { C as ComputeConfig, R as RetryPolicy, a as ComputeError, e as SolveDefinition, F as FileBaseInfo } from './handle-files-DMK9bCOW.cjs';
|
|
2
|
+
export { D as DefinitionRef, c as FileData, P as ProcessedFile, f as downloadFileData, g as extractFilesFromComputeResponse, i as isDefinitionRef } from './handle-files-DMK9bCOW.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ComputeServerStats provides methods to query Rhino Compute server statistics.
|
|
6
|
+
*
|
|
7
|
+
* @public Use this for server health monitoring and statistics.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const stats = new ComputeServerStats('http://localhost:6500', 'your-api-key');
|
|
12
|
+
*
|
|
13
|
+
* try {
|
|
14
|
+
* const isOnline = await stats.isServerOnline();
|
|
15
|
+
* const children = await stats.getActiveChildren();
|
|
16
|
+
* const version = await stats.getVersion();
|
|
17
|
+
*
|
|
18
|
+
* // Or get everything at once
|
|
19
|
+
* const allStats = await stats.getServerStats();
|
|
20
|
+
* } finally {
|
|
21
|
+
* await stats.dispose(); // Clean up resources
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare class ComputeServerStats {
|
|
26
|
+
private readonly serverUrl;
|
|
27
|
+
private readonly apiKey?;
|
|
28
|
+
private disposed;
|
|
29
|
+
private activeMonitors;
|
|
30
|
+
private activeTimeouts;
|
|
31
|
+
/** Timeout (ms) for the fast read/monitoring endpoints. */
|
|
32
|
+
private static readonly DEFAULT_TIMEOUT_MS;
|
|
33
|
+
/** Timeout (ms) for child-lifecycle POSTs — a cold Windows child can take ~30s to spawn. */
|
|
34
|
+
private static readonly LIFECYCLE_TIMEOUT_MS;
|
|
35
|
+
/** Floor for `monitor()`'s `intervalMs` — anything lower hot-loops the server. */
|
|
36
|
+
private static readonly MIN_MONITOR_INTERVAL_MS;
|
|
37
|
+
/**
|
|
38
|
+
* @param serverUrl - Base URL of the Rhino Compute server with http:// or https:// scheme (e.g., 'http://localhost:6500')
|
|
39
|
+
* @param apiKey - Optional API key for authentication
|
|
40
|
+
*/
|
|
41
|
+
constructor(serverUrl: string, apiKey?: string);
|
|
42
|
+
/**
|
|
43
|
+
* Build request headers with optional API key.
|
|
44
|
+
*/
|
|
45
|
+
private buildHeaders;
|
|
46
|
+
/**
|
|
47
|
+
* `fetch` wrapper that aborts after `timeoutMs` so a hung connection can't stall
|
|
48
|
+
* a probe (or the `monitor()` loop) forever. Pass `0` to disable the timeout.
|
|
49
|
+
*/
|
|
50
|
+
private fetchWithTimeout;
|
|
51
|
+
/**
|
|
52
|
+
* Check if the server is online.
|
|
53
|
+
*
|
|
54
|
+
* This is a single-sample probe: it returns `true` only on a 2xx from the
|
|
55
|
+
* proxy liveness root `/`, and `false` for every other outcome (non-2xx,
|
|
56
|
+
* network error, or timeout). A cold or briefly-busy-but-up server can therefore
|
|
57
|
+
* read as offline — callers that gate on this (e.g. client construction)
|
|
58
|
+
* should retry rather than treat a single `false` as authoritative.
|
|
59
|
+
*
|
|
60
|
+
* @param timeoutMs - Abort the probe after this many ms (default: 5000).
|
|
61
|
+
* Pass `0` to disable the timeout. Prevents a hung connection from
|
|
62
|
+
* stalling the caller indefinitely.
|
|
63
|
+
*/
|
|
64
|
+
isServerOnline(timeoutMs?: number): Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Get the number of active child processes on the server.
|
|
67
|
+
*
|
|
68
|
+
* By default the proxy's `/activechildren` endpoint will *spawn* children up
|
|
69
|
+
* to the configured count if none are running, then report the count — which
|
|
70
|
+
* wakes (and bills) an idle server. Pass `{ initialize: false }` for a passive
|
|
71
|
+
* read that reports the current count without spawning; use this for
|
|
72
|
+
* monitoring or before a purge/probe where you must not wake the server.
|
|
73
|
+
*
|
|
74
|
+
* @param options.initialize - When `false`, append `?initialize=false` so the
|
|
75
|
+
* server reports without spawning. Defaults to `true` (the server's default).
|
|
76
|
+
* @returns Number of active children, or null if unavailable
|
|
77
|
+
*/
|
|
78
|
+
getActiveChildren(options?: {
|
|
79
|
+
initialize?: boolean;
|
|
80
|
+
}): Promise<number | null>;
|
|
81
|
+
/**
|
|
82
|
+
* Get the server version information.
|
|
83
|
+
*
|
|
84
|
+
* @returns Version object with rhino, compute, and git_sha, or null if unavailable
|
|
85
|
+
*/
|
|
86
|
+
getVersion(): Promise<{
|
|
87
|
+
rhino: string;
|
|
88
|
+
compute: string;
|
|
89
|
+
git_sha: string | null;
|
|
90
|
+
} | null>;
|
|
91
|
+
/**
|
|
92
|
+
* Get the plugins installed on the server.
|
|
93
|
+
*
|
|
94
|
+
* Returns a `name → version` map of non-core plugins the server has loaded,
|
|
95
|
+
* or `null` if the request failed. Pass `kind` to choose which inventory:
|
|
96
|
+
* `'gh'` (default) lists Grasshopper add-on assemblies via
|
|
97
|
+
* `/plugins/gh/installed`; `'rhino'` lists Rhino plugins via
|
|
98
|
+
* `/plugins/rhino/installed`. Plugins that ship with Rhino / are core
|
|
99
|
+
* libraries are excluded by the server.
|
|
100
|
+
*
|
|
101
|
+
* @param kind - `'gh'` for Grasshopper add-ons (default) or `'rhino'` for Rhino plugins.
|
|
102
|
+
* @returns Map of plugin name to version, or `null` on failure.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* const gh = await stats.getInstalledPlugins(); // Grasshopper add-ons
|
|
107
|
+
* const selvaVersion = gh?.['Selva'] ?? null;
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
getInstalledPlugins(kind?: 'gh' | 'rhino'): Promise<Record<string, string> | null>;
|
|
111
|
+
/**
|
|
112
|
+
* Get comprehensive server statistics.
|
|
113
|
+
* Fetches all available server information in parallel.
|
|
114
|
+
*
|
|
115
|
+
* @returns Object containing server status and available stats
|
|
116
|
+
*/
|
|
117
|
+
getServerStats(): Promise<{
|
|
118
|
+
isOnline: boolean;
|
|
119
|
+
version?: {
|
|
120
|
+
rhino: string;
|
|
121
|
+
compute: string;
|
|
122
|
+
git_sha: string | null;
|
|
123
|
+
};
|
|
124
|
+
activeChildren?: number;
|
|
125
|
+
}>;
|
|
126
|
+
/**
|
|
127
|
+
* Purge the server's solve-results / URL-data cache.
|
|
128
|
+
*
|
|
129
|
+
* POSTs to `cache/purge` and returns the number of entries removed, or `null`
|
|
130
|
+
* if the request failed. This clears cached solve responses and fetched
|
|
131
|
+
* definition-URL data; it does NOT evict the definition cache (active
|
|
132
|
+
* `pointer` references stay valid).
|
|
133
|
+
*
|
|
134
|
+
* **Caveat:** `cache/purge` is forwarded by the rhino.compute proxy to a
|
|
135
|
+
* single round-robin-selected child, so in a multi-child deployment one call
|
|
136
|
+
* purges one child's cache. Call repeatedly (or size the pool to 1) if you
|
|
137
|
+
* need a fleet-wide purge.
|
|
138
|
+
*
|
|
139
|
+
* @returns Number of entries removed, or `null` on failure.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const removed = await stats.purgeCache();
|
|
144
|
+
* if (removed !== null) console.log(`Purged ${removed} cached solves`);
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
purgeCache(): Promise<number | null>;
|
|
148
|
+
/**
|
|
149
|
+
* Best-effort fleet-wide cache purge across a multi-child deployment.
|
|
150
|
+
*
|
|
151
|
+
* A single {@link purgeCache} POST is forwarded by the rhino.compute proxy to
|
|
152
|
+
* just ONE round-robin-selected child, so the other children keep serving
|
|
153
|
+
* stale cached solves. There is no proxy endpoint that addresses children
|
|
154
|
+
* individually, so this method reads the active child count (passively, never
|
|
155
|
+
* spawning) and fires `2 × count` sequential purges, relying on the proxy's
|
|
156
|
+
* round-robin to spread the hits across the pool.
|
|
157
|
+
*
|
|
158
|
+
* **This is best-effort, not a guarantee.** Round-robin can revisit one child
|
|
159
|
+
* and skip another; under concurrent traffic the rotation drifts. The result's
|
|
160
|
+
* `confident` flag is `true` only when the server reports a single child (where
|
|
161
|
+
* one purge is exact) — surface it so callers don't over-promise. For a hard
|
|
162
|
+
* fleet-wide guarantee, run the deployment at `--childcount 1` or add a
|
|
163
|
+
* server-side fan-out endpoint.
|
|
164
|
+
*
|
|
165
|
+
* @returns `{ totalPurged, calls, children, confident }`, or `null` if the
|
|
166
|
+
* child count couldn't be read (server unreachable). `totalPurged` sums the
|
|
167
|
+
* per-call counts; `calls` is how many purges were issued; `children` is the
|
|
168
|
+
* reported pool size; `confident` is `true` only at a single-child pool.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* const r = await stats.purgeAllChildren();
|
|
173
|
+
* if (r && !r.confident) {
|
|
174
|
+
* console.warn(`Purged ~${r.totalPurged} across ${r.children} children (best-effort)`);
|
|
175
|
+
* }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
purgeAllChildren(): Promise<{
|
|
179
|
+
totalPurged: number;
|
|
180
|
+
calls: number;
|
|
181
|
+
children: number;
|
|
182
|
+
confident: boolean;
|
|
183
|
+
} | null>;
|
|
184
|
+
/**
|
|
185
|
+
* Get the server's current UTC clock.
|
|
186
|
+
*
|
|
187
|
+
* GETs `/servertime`, which the server emits as a JSON-encoded ISO-8601
|
|
188
|
+
* timestamp (e.g. `"2026-06-18T08:30:00Z"`). Useful for detecting clock skew
|
|
189
|
+
* between caller and server. Returns `null` if the request failed or the body
|
|
190
|
+
* isn't a parseable date.
|
|
191
|
+
*
|
|
192
|
+
* @returns A `Date` for the server's UTC time, or `null` on failure.
|
|
193
|
+
*/
|
|
194
|
+
getServerTime(): Promise<Date | null>;
|
|
195
|
+
/**
|
|
196
|
+
* Get how long the rhino.compute proxy has been idle.
|
|
197
|
+
*
|
|
198
|
+
* GETs `/idlespan` on the proxy, which returns the seconds elapsed since the
|
|
199
|
+
* last request was forwarded to a compute child. This is a proxy-level metric
|
|
200
|
+
* (not proxied to a child) used by autoscalers to decide when a node can be
|
|
201
|
+
* drained. Returns `null` if unavailable.
|
|
202
|
+
*
|
|
203
|
+
* @returns Idle time in seconds, or `null` on failure.
|
|
204
|
+
*/
|
|
205
|
+
getIdleSpan(): Promise<number | null>;
|
|
206
|
+
/**
|
|
207
|
+
* Fill the compute child pool up to the server's configured baseline.
|
|
208
|
+
*
|
|
209
|
+
* POSTs `/launch-children`. No-op when the pool is already at or above the
|
|
210
|
+
* configured `--childcount`. Returns `{ spawned, active }` — how many children
|
|
211
|
+
* were started and the resulting child count — or `null` on failure.
|
|
212
|
+
*
|
|
213
|
+
* To raise capacity above the baseline use {@link launchChild}; the baseline
|
|
214
|
+
* itself can only be changed by restarting rhino.compute.
|
|
215
|
+
*
|
|
216
|
+
* @returns `{ spawned, active }`, or `null` on failure.
|
|
217
|
+
*/
|
|
218
|
+
launchChildren(): Promise<{
|
|
219
|
+
spawned: number[];
|
|
220
|
+
active: number;
|
|
221
|
+
} | null>;
|
|
222
|
+
/**
|
|
223
|
+
* Add a single compute child to the pool, optionally on a specific port.
|
|
224
|
+
*
|
|
225
|
+
* POSTs `/launch-child` (with `?port=N` when `port` is given). Unlike
|
|
226
|
+
* {@link launchChildren}, this can push the pool above the baseline, up to the
|
|
227
|
+
* server's `MaxChildren` cap. Returns `{ spawned: [port] }` on success, or
|
|
228
|
+
* `null` on failure (server replies 400 for a bad port, 409 if the port is in
|
|
229
|
+
* use, 503 at the max-children cap).
|
|
230
|
+
*
|
|
231
|
+
* @param port - Optional specific port to launch on; otherwise the next free one.
|
|
232
|
+
* @returns `{ spawned }` listing the launched port, or `null` on failure.
|
|
233
|
+
*/
|
|
234
|
+
launchChild(port?: number): Promise<{
|
|
235
|
+
spawned: number[];
|
|
236
|
+
} | null>;
|
|
237
|
+
/**
|
|
238
|
+
* Gracefully shut down compute children without respawning them.
|
|
239
|
+
*
|
|
240
|
+
* POSTs `/shutdown-children`. With no `port` it shuts down every child; with
|
|
241
|
+
* `port` it targets just that one. Children do not respawn, but the next
|
|
242
|
+
* `/grasshopper` request auto-spawns the pool back to the baseline. Returns
|
|
243
|
+
* `{ shutdown, active }` — how many were stopped and the remaining count — or
|
|
244
|
+
* `null` on failure.
|
|
245
|
+
*
|
|
246
|
+
* @param port - Optional port to target; omit to shut down all children.
|
|
247
|
+
* @returns `{ shutdown, active }`, or `null` on failure.
|
|
248
|
+
*/
|
|
249
|
+
shutdownChildren(port?: number): Promise<{
|
|
250
|
+
shutdown: number;
|
|
251
|
+
active: number;
|
|
252
|
+
} | null>;
|
|
253
|
+
/**
|
|
254
|
+
* Shut down compute children and respawn replacements (rolling restart).
|
|
255
|
+
*
|
|
256
|
+
* POSTs `/recycle-children`. With no `port` it recycles every child; with
|
|
257
|
+
* `port` it recycles just that one. The server recycles sequentially (each
|
|
258
|
+
* replacement is serving before the next child is stopped) so the pool never
|
|
259
|
+
* drops to zero mid-recycle. Returns `{ shutdown, spawned, active }`, or
|
|
260
|
+
* `null` on failure.
|
|
261
|
+
*
|
|
262
|
+
* @param port - Optional port to target; omit to recycle all children.
|
|
263
|
+
* @returns `{ shutdown, spawned, active }`, or `null` on failure.
|
|
264
|
+
*/
|
|
265
|
+
recycleChildren(port?: number): Promise<{
|
|
266
|
+
shutdown: number;
|
|
267
|
+
spawned: number[];
|
|
268
|
+
active: number;
|
|
269
|
+
} | null>;
|
|
270
|
+
/**
|
|
271
|
+
* POST a control endpoint that replies with a JSON object and return it,
|
|
272
|
+
* degrading to `null` on any non-2xx, non-JSON, or network failure. Shared by
|
|
273
|
+
* the child-lifecycle methods so their failure semantics stay identical. Uses
|
|
274
|
+
* the longer lifecycle timeout since a spawn/recycle can take ~30s.
|
|
275
|
+
*/
|
|
276
|
+
private postJson;
|
|
277
|
+
/**
|
|
278
|
+
* Continuously monitor server stats at specified interval.
|
|
279
|
+
*
|
|
280
|
+
* @param callback - Function called with stats on each interval
|
|
281
|
+
* @param intervalMs - Milliseconds between checks (default: 5000). Must be a
|
|
282
|
+
* finite number of at least 100 ms — lower values would hot-loop the server.
|
|
283
|
+
* @returns Function to stop monitoring
|
|
284
|
+
* @throws {RangeError} If `intervalMs` is not a finite number >= 100.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* const stopMonitoring = stats.monitor((data) => {
|
|
289
|
+
* console.log('Server stats:', data);
|
|
290
|
+
* }, 3000);
|
|
291
|
+
*
|
|
292
|
+
* // Later...
|
|
293
|
+
* stopMonitoring();
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
monitor(callback: (stats: Awaited<ReturnType<typeof this.getServerStats>>) => void, intervalMs?: number): () => void;
|
|
297
|
+
/**
|
|
298
|
+
* Disposes of all resources and stops all active monitors.
|
|
299
|
+
* Call this when you're done using the stats instance.
|
|
300
|
+
*/
|
|
301
|
+
dispose(): Promise<void>;
|
|
302
|
+
/**
|
|
303
|
+
* Ensures the instance hasn't been disposed.
|
|
304
|
+
*/
|
|
305
|
+
private ensureNotDisposed;
|
|
306
|
+
}
|
|
3
307
|
|
|
4
308
|
type DataTreePath = `{${string}}`;
|
|
5
309
|
interface DataItem {
|
|
@@ -124,6 +428,7 @@ interface ColorInputType extends BaseInputType {
|
|
|
124
428
|
*/
|
|
125
429
|
type InputParam = NumericInputType | BooleanInputType | TextInputType | ValueListInputType | GeometryInputType | FileInputType | ColorInputType;
|
|
126
430
|
|
|
431
|
+
type RhinoModelUnit = 'None' | 'Microns' | 'Millimeters' | 'Centimeters' | 'Decimeters' | 'Meters' | 'Kilometers' | 'Mils' | 'Inches' | 'Feet' | 'Yards' | 'Miles' | 'CustomUnits' | 'Unset';
|
|
127
432
|
/**
|
|
128
433
|
* Base Grasshopper schema properties shared by config, args, and response
|
|
129
434
|
*/
|
|
@@ -301,9 +606,9 @@ interface InputParseError {
|
|
|
301
606
|
inputName: string;
|
|
302
607
|
/** The declared paramType from the raw schema. */
|
|
303
608
|
paramType: string;
|
|
304
|
-
/** Human-readable reason from the underlying
|
|
609
|
+
/** Human-readable reason from the underlying ComputeError. */
|
|
305
610
|
message: string;
|
|
306
|
-
/** Error code from the underlying
|
|
611
|
+
/** Error code from the underlying ComputeError, if available. */
|
|
307
612
|
code?: string;
|
|
308
613
|
}
|
|
309
614
|
/**
|
|
@@ -331,50 +636,6 @@ interface GrasshopperParsedIO {
|
|
|
331
636
|
loadErrors?: string[];
|
|
332
637
|
}
|
|
333
638
|
|
|
334
|
-
/**
|
|
335
|
-
* By-reference definition form for solves.
|
|
336
|
-
*
|
|
337
|
-
* Lets a caller that already knows a definition's identity (e.g. a stored
|
|
338
|
-
* version's UUID) schedule solves without materializing the multi-MB bytes:
|
|
339
|
-
* cache keys and the server-pointer map are derived from `key` alone, and
|
|
340
|
-
* `load()` is only called when an upload is genuinely unavoidable (first solve
|
|
341
|
-
* of a definition, or a server-side pointer miss).
|
|
342
|
-
*/
|
|
343
|
-
/**
|
|
344
|
-
* A definition identified by a stable key, with bytes materialized on demand.
|
|
345
|
-
*
|
|
346
|
-
* **Immutability contract — read this before constructing one.** `key` must
|
|
347
|
-
* identify IMMUTABLE bytes: every `load()` for a given `key` must return the
|
|
348
|
-
* same content, forever. All caching (the scheduler's result cache, the
|
|
349
|
-
* server-pointer map, and any durable cache built on these keys) trusts the
|
|
350
|
-
* key as the definition's identity WITHOUT looking at the bytes. If two
|
|
351
|
-
* different byte contents ever share a key, cached solves from one are served
|
|
352
|
-
* for the other — silent cache poisoning with no diagnostic. Use an identity
|
|
353
|
-
* that can never be reused for different content (e.g. a version UUID), never
|
|
354
|
-
* a mutable name or path.
|
|
355
|
-
*/
|
|
356
|
-
interface DefinitionRef {
|
|
357
|
-
/**
|
|
358
|
-
* Identity of immutable bytes (e.g. a version UUID). Two different byte
|
|
359
|
-
* contents must never share a key — cache poisoning otherwise.
|
|
360
|
-
*/
|
|
361
|
-
key: string;
|
|
362
|
-
/**
|
|
363
|
-
* Materialize the bytes. Called ONLY when an upload is unavoidable — inside
|
|
364
|
-
* the solve execution, so it counts toward the solve's abort semantics.
|
|
365
|
-
*/
|
|
366
|
-
load: () => Promise<Uint8Array>;
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Every definition form accepted by the solve entry points:
|
|
370
|
-
* - a URL, base64 string, or plain string (content-hashed for caching)
|
|
371
|
-
* - raw `.gh` bytes (content-hashed)
|
|
372
|
-
* - a {@link DefinitionRef} (identity-keyed; bytes loaded lazily)
|
|
373
|
-
*/
|
|
374
|
-
type SolveDefinition = string | Uint8Array | DefinitionRef;
|
|
375
|
-
/** Narrow a {@link SolveDefinition} to the by-reference form. */
|
|
376
|
-
declare function isDefinitionRef(definition: SolveDefinition): definition is DefinitionRef;
|
|
377
|
-
|
|
378
639
|
/**
|
|
379
640
|
* Scheduling mode — controls how concurrent `solve()` calls interact.
|
|
380
641
|
*
|
|
@@ -387,19 +648,29 @@ declare function isDefinitionRef(definition: SolveDefinition): definition is Def
|
|
|
387
648
|
*/
|
|
388
649
|
type SchedulerMode = 'latest-wins' | 'queue' | 'parallel';
|
|
389
650
|
interface CacheOptions {
|
|
390
|
-
/**
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
651
|
+
/**
|
|
652
|
+
* Total byte budget for retained responses, evicted LRU. The only size bound
|
|
653
|
+
* there is: responses range KB→100s of MB, so memory is the constraint that
|
|
654
|
+
* matters and an entry count would only obscure it.
|
|
655
|
+
*
|
|
656
|
+
* Sizing uses the response's wire size (JSON text length, recorded at the
|
|
657
|
+
* fetch boundary — no re-serialization); a response without that hint
|
|
658
|
+
* (custom executor) is sized by a one-off `JSON.stringify`. A single
|
|
659
|
+
* response larger than the whole budget is served but never retained.
|
|
660
|
+
*
|
|
661
|
+
* Required and must be > 0 — to disable caching, pass `cache: false`.
|
|
662
|
+
*/
|
|
663
|
+
maxBytes: number;
|
|
664
|
+
/**
|
|
665
|
+
* Time-to-live in ms. Set to `0` for no expiry (default, and the right
|
|
666
|
+
* choice for a solve keyed by immutable definition+inputs — expiry there
|
|
667
|
+
* only buys a paid re-solve of an identical answer). Meaningful only when a
|
|
668
|
+
* definition reaches outside its inputs (external data source, clock), where
|
|
669
|
+
* a stale result is genuinely wrong rather than merely old.
|
|
670
|
+
*
|
|
671
|
+
* Expiry is evaluated lazily on read: an expired entry keeps its bytes
|
|
672
|
+
* counted against `maxBytes` until that exact key is next consulted.
|
|
673
|
+
*/
|
|
403
674
|
ttlMs?: number;
|
|
404
675
|
/**
|
|
405
676
|
* Cache responses that carry Grasshopper `errors`. Default `true`: an
|
|
@@ -417,7 +688,7 @@ interface SolveSchedulerOptions {
|
|
|
417
688
|
/**
|
|
418
689
|
* Backpressure — cap on how many calls may wait in the FIFO queue (i.e.
|
|
419
690
|
* excluding the ones already in flight). When the queue is full, a new
|
|
420
|
-
* `solve()` is
|
|
691
|
+
* `solve()` is rejected immediately with `code: QUEUE_FULL` (retryable, meant to
|
|
421
692
|
* map to HTTP 503 + Retry-After) instead of piling up unbounded. Bounds the
|
|
422
693
|
* miss path under load. Only applies to `queue` / `parallel` modes —
|
|
423
694
|
* `latest-wins` has an intrinsic depth of 1. Default: unbounded.
|
|
@@ -425,7 +696,7 @@ interface SolveSchedulerOptions {
|
|
|
425
696
|
maxQueueDepth?: number;
|
|
426
697
|
/**
|
|
427
698
|
* Backpressure — max time (ms) a call may sit queued before it starts
|
|
428
|
-
* executing. If it's still waiting after this long it's
|
|
699
|
+
* executing. If it's still waiting after this long it's rejected with
|
|
429
700
|
* `code: QUEUE_TIMEOUT` rather than burning compute on a stale request.
|
|
430
701
|
* Bounds tail latency. Only applies to `queue` / `parallel` modes. Default:
|
|
431
702
|
* no deadline.
|
|
@@ -433,8 +704,12 @@ interface SolveSchedulerOptions {
|
|
|
433
704
|
queueWaitMs?: number;
|
|
434
705
|
timeoutMs?: number;
|
|
435
706
|
retry?: RetryPolicy;
|
|
436
|
-
/**
|
|
437
|
-
|
|
707
|
+
/**
|
|
708
|
+
* Response caching keyed by hash of (definition, dataTree). Omit or pass
|
|
709
|
+
* `false` to disable; otherwise a byte budget is required, so an unbounded
|
|
710
|
+
* cache can't be enabled by accident.
|
|
711
|
+
*/
|
|
712
|
+
cache?: false | CacheOptions;
|
|
438
713
|
/**
|
|
439
714
|
* Reuse the server's definition cache key so a large (base64/binary)
|
|
440
715
|
* definition is uploaded once and subsequent solves reference it by
|
|
@@ -476,7 +751,7 @@ type SolveResult = {
|
|
|
476
751
|
definitionReuploaded?: boolean;
|
|
477
752
|
} | {
|
|
478
753
|
status: 'error';
|
|
479
|
-
error:
|
|
754
|
+
error: ComputeError;
|
|
480
755
|
durationMs: number;
|
|
481
756
|
} | {
|
|
482
757
|
status: 'superseded';
|
|
@@ -535,13 +810,17 @@ declare class SolveScheduler {
|
|
|
535
810
|
private readonly executor;
|
|
536
811
|
private readonly baseConfig;
|
|
537
812
|
private readonly mode;
|
|
538
|
-
|
|
813
|
+
/**
|
|
814
|
+
* Mutable via {@link setMaxConcurrent}: the compute server's worker pool can grow
|
|
815
|
+
* or shrink while this scheduler is alive, and the dispatch loops re-read this on
|
|
816
|
+
* every pass rather than capturing it.
|
|
817
|
+
*/
|
|
818
|
+
private maxConcurrent;
|
|
539
819
|
private readonly maxQueueDepth;
|
|
540
820
|
private readonly queueWaitMs;
|
|
541
821
|
private readonly timeoutMs;
|
|
542
822
|
private readonly retry;
|
|
543
823
|
private readonly cacheEnabled;
|
|
544
|
-
private readonly cacheMax;
|
|
545
824
|
private readonly cacheMaxBytes;
|
|
546
825
|
private readonly cacheTtl;
|
|
547
826
|
private readonly cacheErroredSolves;
|
|
@@ -583,15 +862,26 @@ declare class SolveScheduler {
|
|
|
583
862
|
get inFlightCount(): number;
|
|
584
863
|
get queueDepth(): number;
|
|
585
864
|
get lastResult(): GrasshopperComputeResponse | null;
|
|
586
|
-
get lastError():
|
|
865
|
+
get lastError(): ComputeError | null;
|
|
587
866
|
get lastDurationMs(): number | null;
|
|
867
|
+
/**
|
|
868
|
+
* Adjust how many solves may run at once, for when the compute server's worker
|
|
869
|
+
* pool changes size after this scheduler was built.
|
|
870
|
+
*
|
|
871
|
+
* Raising it drains queued work immediately. Lowering it never interrupts work
|
|
872
|
+
* already in flight — those finish above the new limit, and the cap applies from
|
|
873
|
+
* the next dispatch. Values below 1 are clamped, since 0 would wedge the queue.
|
|
874
|
+
*/
|
|
875
|
+
setMaxConcurrent(value: number): void;
|
|
876
|
+
/** Current concurrency cap — reflects any {@link setMaxConcurrent} adjustment. */
|
|
877
|
+
getMaxConcurrent(): number;
|
|
588
878
|
/** Subscribe to state changes. */
|
|
589
879
|
subscribe(listener: () => void): () => void;
|
|
590
880
|
private notify;
|
|
591
881
|
/**
|
|
592
882
|
* Schedule a solve. Returns a promise that:
|
|
593
883
|
* - Resolves with the compute response on success.
|
|
594
|
-
* - Rejects with `
|
|
884
|
+
* - Rejects with `ComputeError` on failure.
|
|
595
885
|
* - Rejects with `code: ErrorCodes.SUPERSEDED` when the call was canceled because
|
|
596
886
|
* newer values arrived (latest-wins mode).
|
|
597
887
|
* - Rejects with `code: ErrorCodes.ABORTED` when the call was canceled via
|
|
@@ -633,8 +923,8 @@ declare class SolveScheduler {
|
|
|
633
923
|
private shedAsQueueFull;
|
|
634
924
|
/**
|
|
635
925
|
* Arm the queue-wait deadline for an item about to be queued. If the item is
|
|
636
|
-
* still waiting when it fires, it's
|
|
637
|
-
* queue. Cleared on execute/settle via {@link clearQueueWaitTimer}.
|
|
926
|
+
* still waiting when it fires, it's rejected as QUEUE_TIMEOUT and removed from
|
|
927
|
+
* the queue. Cleared on execute/settle via {@link clearQueueWaitTimer}.
|
|
638
928
|
*/
|
|
639
929
|
private armQueueWaitTimer;
|
|
640
930
|
/** Clear a queued item's wait-deadline timer, if one is pending. */
|
|
@@ -759,9 +1049,9 @@ declare class GrasshopperClient {
|
|
|
759
1049
|
* exponential backoff before giving up. Each probe is also bounded by a
|
|
760
1050
|
* timeout so a hung connection can't stall construction.
|
|
761
1051
|
*
|
|
762
|
-
* @throws {
|
|
1052
|
+
* @throws {ComputeError} with code NETWORK_ERROR if the server stays
|
|
763
1053
|
* unreachable across all attempts
|
|
764
|
-
* @throws {
|
|
1054
|
+
* @throws {ComputeError} with code INVALID_CONFIG if configuration is invalid
|
|
765
1055
|
*/
|
|
766
1056
|
static create(config: GrasshopperComputeConfig): Promise<GrasshopperClient>;
|
|
767
1057
|
/**
|
|
@@ -777,9 +1067,9 @@ declare class GrasshopperClient {
|
|
|
777
1067
|
/**
|
|
778
1068
|
* Run a compute job with a Grasshopper definition.
|
|
779
1069
|
*
|
|
780
|
-
* @throws {
|
|
781
|
-
* @throws {
|
|
782
|
-
* @throws {
|
|
1070
|
+
* @throws {ComputeError} with code INVALID_INPUT if definition is empty
|
|
1071
|
+
* @throws {ComputeError} with code NETWORK_ERROR if server is offline
|
|
1072
|
+
* @throws {ComputeError} with code COMPUTATION_ERROR if computation fails.
|
|
783
1073
|
* On a partial-success response (some outputs computed, some errored) the
|
|
784
1074
|
* error's `context.values` carries the outputs that did compute — pass
|
|
785
1075
|
* `{ values } as GrasshopperComputeResponse` to the response processors to
|
|
@@ -814,7 +1104,7 @@ declare class GrasshopperClient {
|
|
|
814
1104
|
/**
|
|
815
1105
|
* Validates and normalizes a compute configuration.
|
|
816
1106
|
*
|
|
817
|
-
* @throws {
|
|
1107
|
+
* @throws {ComputeError} with code INVALID_CONFIG if configuration is invalid
|
|
818
1108
|
*/
|
|
819
1109
|
private normalizeComputeConfig;
|
|
820
1110
|
}
|
|
@@ -1042,7 +1332,7 @@ declare function solveGrasshopperDefinition(dataTree: DataTree[], definition: So
|
|
|
1042
1332
|
* @param definition - The Grasshopper definition (URL, base64 string, or Uint8Array)
|
|
1043
1333
|
* @param config - Compute configuration (server URL, API key, etc.)
|
|
1044
1334
|
* @returns Key-normalized inputs and outputs with no per-type processing
|
|
1045
|
-
* @throws {
|
|
1335
|
+
* @throws {ComputeError} If fetch fails or response is invalid
|
|
1046
1336
|
*
|
|
1047
1337
|
* @public Use `fetchParsedDefinitionIO()` for processed, type-safe inputs
|
|
1048
1338
|
*/
|
|
@@ -1056,7 +1346,7 @@ declare function fetchDefinitionIO(definition: string | Uint8Array, config: Comp
|
|
|
1056
1346
|
* @param definition - The Grasshopper definition (URL, base64 string, or Uint8Array)
|
|
1057
1347
|
* @param config - Compute configuration (server URL, API key, etc.)
|
|
1058
1348
|
* @returns Processed inputs with discriminated union types and outputs
|
|
1059
|
-
* @throws {
|
|
1349
|
+
* @throws {ComputeError} If fetch fails or response is invalid
|
|
1060
1350
|
*
|
|
1061
1351
|
* @example
|
|
1062
1352
|
* ```typescript
|
|
@@ -1075,6 +1365,35 @@ declare function fetchDefinitionIO(definition: string | Uint8Array, config: Comp
|
|
|
1075
1365
|
*/
|
|
1076
1366
|
declare function fetchParsedDefinitionIO(definition: string | Uint8Array, config: ComputeConfig): Promise<GrasshopperParsedIO>;
|
|
1077
1367
|
|
|
1368
|
+
/** One entry of the schema endpoint's response, after wrapper-key normalization. */
|
|
1369
|
+
interface SchemaEndpointResult<TSchema = unknown> {
|
|
1370
|
+
/** Schemas embedded in that file. Absent when the file yielded none. */
|
|
1371
|
+
schemas?: TSchema[];
|
|
1372
|
+
/** Per-file diagnosis. Compute reports this and still answers 200. */
|
|
1373
|
+
error?: string;
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Read compute's `/grasshopper/schema` body: `[{ FileName, Schemas }]` per
|
|
1377
|
+
* uploaded file, or a bare object for a single file.
|
|
1378
|
+
*
|
|
1379
|
+
* Use this rather than unwrapping the body by hand. The wrapper's casing varies
|
|
1380
|
+
* by server branch — mcneel serializes `FileName`/`Schemas`, the VektorNode fork
|
|
1381
|
+
* `fileName`/`schemas` — so a fixed-key read silently yields `undefined` against
|
|
1382
|
+
* half the servers, and the endpoint answers 200 either way. The failure looks
|
|
1383
|
+
* like "this definition has no schemas", which sends you debugging the wrong
|
|
1384
|
+
* thing entirely.
|
|
1385
|
+
*
|
|
1386
|
+
* A blanket key-rewrite (the old `camelcaseKeys` approach) is NOT the fix: it
|
|
1387
|
+
* reaches inside the schemas and mangles user-authored names — `"Display3d"` →
|
|
1388
|
+
* `"display3d"`, value-list labels like `"Option A"` → `"optionA"`. Only the two
|
|
1389
|
+
* wrapper keys are read here; schema CONTENTS pass through untouched, which is
|
|
1390
|
+
* why `TSchema` is a pass-through type parameter this module never inspects.
|
|
1391
|
+
*
|
|
1392
|
+
* @typeParam TSchema - Your schema type (e.g. `UISchema`). Not inspected.
|
|
1393
|
+
* @param raw - The parsed JSON body.
|
|
1394
|
+
*/
|
|
1395
|
+
declare function readSchemaResults<TSchema = unknown>(raw: unknown): SchemaEndpointResult<TSchema>[];
|
|
1396
|
+
|
|
1078
1397
|
/**
|
|
1079
1398
|
* Parse one raw Grasshopper input schema into a typed {@link InputParam}.
|
|
1080
1399
|
* Validation failures are swallowed and replaced with a safe default; use
|
|
@@ -1356,4 +1675,4 @@ declare class TreeBuilder {
|
|
|
1356
1675
|
private static clampValue;
|
|
1357
1676
|
}
|
|
1358
1677
|
|
|
1359
|
-
export { type BooleanInputType, type CacheOptions, type DataItem, type DataTree, type DataTreeDefault, type DataTreePath, type DataTreeValue, type DefaultValue,
|
|
1678
|
+
export { type BooleanInputType, type CacheOptions, ComputeServerStats, type DataItem, type DataTree, type DataTreeDefault, type DataTreePath, type DataTreeValue, type DefaultValue, FileBaseInfo, type FileInputType, type GeometryInputType, type GetValuesOptions, type GetValuesResult, GrasshopperClient, type GrasshopperComputeConfig, type GrasshopperComputeResponse, type GrasshopperParsedIO, type GrasshopperParsedIORaw, type GrasshopperRequestSchema, GrasshopperResponseProcessor, type InnerTreeData, type InputParam, type InputParamSchema, type NumericInputType, type OutputParamSchema, type OutputType, type ParsedContext, type RhinoModelUnit, type SchedulerMode, type SchemaEndpointResult, type SolveContext, SolveDefinition, type SolveOptions, type SolveResult, SolveScheduler, type SolveSchedulerOptions, type TextInputType, TreeBuilder, type ValueListInputType, fetchDefinitionIO, fetchParsedDefinitionIO, hashDefinition, hashSolveInput, processInput, readSchemaResults, solveGrasshopperDefinition, stableStringify };
|