@selvajs/compute 4.3.0-beta.1 → 5.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 +107 -100
- package/dist/core-BMeRVFJI.js +3 -0
- package/dist/core-BMeRVFJI.js.map +1 -0
- package/dist/core-D2HyYEM_.cjs +3 -0
- package/dist/core-D2HyYEM_.cjs.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/grasshopper.cjs +1 -1
- package/dist/grasshopper.cjs.map +1 -1
- package/dist/grasshopper.d.cts +252 -650
- package/dist/grasshopper.d.ts +252 -650
- package/dist/grasshopper.js +1 -1
- package/dist/grasshopper.js.map +1 -1
- package/dist/index-CyKrrYnz.d.cts +427 -0
- package/dist/index-CyKrrYnz.d.ts +427 -0
- package/package.json +6 -43
- package/dist/core-rp3fyoca.js +0 -3
- package/dist/core-rp3fyoca.js.map +0 -1
- package/dist/core-zk0-pvdL.cjs +0 -3
- package/dist/core-zk0-pvdL.cjs.map +0 -1
- package/dist/index-BR_XZvjj.d.cts +0 -574
- package/dist/index-BR_XZvjj.d.ts +0 -574
- package/dist/index.cjs +0 -0
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
package/dist/grasshopper.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as ServerTiming, D as ComputeConfig, E as ComputeAuth, O as RetryPolicy, g as SolveDefinition, j as ComputeError, o as FileBaseInfo } from "./index-CyKrrYnz.js";
|
|
2
2
|
//#region src/grasshopper/server/compute-server-stats.d.ts
|
|
3
|
+
interface ServerVersion {
|
|
4
|
+
rhino: string;
|
|
5
|
+
compute: string;
|
|
6
|
+
git_sha: string | null;
|
|
7
|
+
}
|
|
8
|
+
interface ServerStats {
|
|
9
|
+
isOnline: boolean;
|
|
10
|
+
version?: ServerVersion;
|
|
11
|
+
activeChildren?: number;
|
|
12
|
+
}
|
|
3
13
|
/**
|
|
4
14
|
* ComputeServerStats provides methods to query Rhino Compute server statistics.
|
|
5
15
|
*
|
|
@@ -26,13 +36,14 @@ declare class ComputeServerStats {
|
|
|
26
36
|
private readonly headers;
|
|
27
37
|
private disposed;
|
|
28
38
|
private activeMonitors;
|
|
29
|
-
private activeTimeouts;
|
|
30
39
|
/** Timeout (ms) for the fast read/monitoring endpoints. */
|
|
31
40
|
private static readonly DEFAULT_TIMEOUT_MS;
|
|
32
41
|
/** Timeout (ms) for child-lifecycle POSTs — a cold Windows child can take ~30s to spawn. */
|
|
33
42
|
private static readonly LIFECYCLE_TIMEOUT_MS;
|
|
34
43
|
/** Floor for `monitor()`'s `intervalMs` — anything lower hot-loops the server. */
|
|
35
44
|
private static readonly MIN_MONITOR_INTERVAL_MS;
|
|
45
|
+
/** Every control-plane answer is a count, a version or a short map. */
|
|
46
|
+
private static readonly MAX_BODY_BYTES;
|
|
36
47
|
/**
|
|
37
48
|
* @param serverUrl - Base URL of the Rhino Compute server with http:// or https:// scheme (e.g., 'http://localhost:6500')
|
|
38
49
|
* @param auth - An API key, or the same auth fields a solve's `ComputeConfig` carries
|
|
@@ -40,10 +51,15 @@ declare class ComputeServerStats {
|
|
|
40
51
|
*/
|
|
41
52
|
constructor(serverUrl: string, auth?: string | ComputeAuth);
|
|
42
53
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
54
|
+
* Aborts after `timeoutMs` so a hung connection can't stall a probe or `monitor()`; `0` disables
|
|
55
|
+
* it. Redirects are not followed: fetch would carry the API key header to the target.
|
|
45
56
|
*/
|
|
46
57
|
private fetchWithTimeout;
|
|
58
|
+
/**
|
|
59
|
+
* The response body of `path`, or `null` (logged) on a non-2xx or a network
|
|
60
|
+
* failure. Throws only when disposed.
|
|
61
|
+
*/
|
|
62
|
+
private getText;
|
|
47
63
|
/**
|
|
48
64
|
* Check if the server is online.
|
|
49
65
|
*
|
|
@@ -97,11 +113,7 @@ declare class ComputeServerStats {
|
|
|
97
113
|
*
|
|
98
114
|
* @returns Version object with rhino, compute, and git_sha, or null if unavailable
|
|
99
115
|
*/
|
|
100
|
-
getVersion(): Promise<
|
|
101
|
-
rhino: string;
|
|
102
|
-
compute: string;
|
|
103
|
-
git_sha: string | null;
|
|
104
|
-
} | null>;
|
|
116
|
+
getVersion(): Promise<ServerVersion | null>;
|
|
105
117
|
/**
|
|
106
118
|
* Get the plugins installed on the server.
|
|
107
119
|
*
|
|
@@ -128,15 +140,7 @@ declare class ComputeServerStats {
|
|
|
128
140
|
*
|
|
129
141
|
* @returns Object containing server status and available stats
|
|
130
142
|
*/
|
|
131
|
-
getServerStats(): Promise<
|
|
132
|
-
isOnline: boolean;
|
|
133
|
-
version?: {
|
|
134
|
-
rhino: string;
|
|
135
|
-
compute: string;
|
|
136
|
-
git_sha: string | null;
|
|
137
|
-
};
|
|
138
|
-
activeChildren?: number;
|
|
139
|
-
}>;
|
|
143
|
+
getServerStats(): Promise<ServerStats>;
|
|
140
144
|
/**
|
|
141
145
|
* Purge the server's solve-results / URL-data cache.
|
|
142
146
|
*
|
|
@@ -281,12 +285,7 @@ declare class ComputeServerStats {
|
|
|
281
285
|
spawned: number[];
|
|
282
286
|
active: number;
|
|
283
287
|
} | null>;
|
|
284
|
-
/**
|
|
285
|
-
* POST a control endpoint that replies with a JSON object and return it,
|
|
286
|
-
* degrading to `null` on any non-2xx, non-JSON, or network failure. Shared by
|
|
287
|
-
* the child-lifecycle methods so their failure semantics stay identical. Uses
|
|
288
|
-
* the longer lifecycle timeout since a spawn/recycle can take ~30s.
|
|
289
|
-
*/
|
|
288
|
+
/** A child-lifecycle POST: a spawn or recycle can take ~30 s. */
|
|
290
289
|
private postJson;
|
|
291
290
|
/**
|
|
292
291
|
* Continuously monitor server stats at specified interval.
|
|
@@ -307,15 +306,12 @@ declare class ComputeServerStats {
|
|
|
307
306
|
* stopMonitoring();
|
|
308
307
|
* ```
|
|
309
308
|
*/
|
|
310
|
-
monitor(callback: (stats:
|
|
309
|
+
monitor(callback: (stats: ServerStats) => void, intervalMs?: number): () => void;
|
|
311
310
|
/**
|
|
312
311
|
* Disposes of all resources and stops all active monitors.
|
|
313
312
|
* Call this when you're done using the stats instance.
|
|
314
313
|
*/
|
|
315
314
|
dispose(): Promise<void>;
|
|
316
|
-
/**
|
|
317
|
-
* Ensures the instance hasn't been disposed.
|
|
318
|
-
*/
|
|
319
315
|
private ensureNotDisposed;
|
|
320
316
|
}
|
|
321
317
|
//#endregion
|
|
@@ -331,17 +327,9 @@ type InnerTreeData = { [path in DataTreePath]: DataItem[]; };
|
|
|
331
327
|
/**
|
|
332
328
|
* Tree with parameter metadata (used in compute requests and responses).
|
|
333
329
|
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
* camelCase-serializing forks return `paramName`/`innerTree` instead. This
|
|
338
|
-
* client always *sends* PascalCase (see `DataTree.toCompute()` in
|
|
339
|
-
* `data-tree.ts`), so the PascalCase fields remain the canonical/required
|
|
340
|
-
* shape; the optional camelCase fields exist so responses from camelCase
|
|
341
|
-
* forks are representable without casts. Code that must read trees across
|
|
342
|
-
* both server families should use `readField`/`hasField`
|
|
343
|
-
* (`@/core/utils/read-field`, case-insensitive) rather than direct property
|
|
344
|
-
* access — `warnOnEmptyInnerTrees` in `solve.ts` is the reference example.
|
|
330
|
+
* This client sends PascalCase (`TreeBuilder.toComputeFormat()`), so those
|
|
331
|
+
* fields are required; a response's casing varies by server branch, so read
|
|
332
|
+
* one with `readField` rather than by property.
|
|
345
333
|
*/
|
|
346
334
|
interface DataTree {
|
|
347
335
|
/** PascalCase — stock mcneel servers, and the request shape this client sends. */
|
|
@@ -353,7 +341,6 @@ interface DataTree {
|
|
|
353
341
|
/** camelCase — sent instead of `ParamName` by camelCase server forks. */
|
|
354
342
|
paramName?: string;
|
|
355
343
|
}
|
|
356
|
-
type OutputType = 'System.String' | 'System.Double' | 'System.Int32' | 'System.Boolean' | 'Rhino.Geometry.Point3d' | 'Rhino.Geometry.Line' | 'Rhino.Geometry.Circle' | 'Rhino.Geometry.Arc' | 'Rhino.Geometry.NurbsCurve' | 'Rhino.Geometry.Brep' | 'Rhino.Geometry.Mesh' | 'Rhino.Geometry.Vector3d' | 'Rhino.Geometry.Plane' | 'Rhino.Geometry.Box' | (string & {});
|
|
357
344
|
/**
|
|
358
345
|
* Union type for all possible default value types
|
|
359
346
|
*/
|
|
@@ -428,7 +415,7 @@ interface FileInputType extends BaseInputType {
|
|
|
428
415
|
default: DefaultValue<object | string>;
|
|
429
416
|
}
|
|
430
417
|
/**
|
|
431
|
-
* Color input type (
|
|
418
|
+
* Color input type. Values are `"R, G, B"` strings (`"255, 0, 0"`), not hex.
|
|
432
419
|
*/
|
|
433
420
|
interface ColorInputType extends BaseInputType {
|
|
434
421
|
paramType: 'Color';
|
|
@@ -487,55 +474,19 @@ interface GrasshopperDefinitionSource {
|
|
|
487
474
|
filename?: string | null;
|
|
488
475
|
}
|
|
489
476
|
/**
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
* Note: The definition source (pointer/algo) is NOT part of config.
|
|
494
|
-
* Instead, pass the definition directly to methods like solve(), getIO(), etc.
|
|
495
|
-
*/
|
|
496
|
-
interface GrasshopperComputeConfig extends ComputeConfig {
|
|
497
|
-
/** Absolute tolerance used in computation */
|
|
498
|
-
absolutetolerance?: number | null;
|
|
499
|
-
/** Angular tolerance used in computation */
|
|
500
|
-
angletolerance?: number | null;
|
|
501
|
-
/** Model units used */
|
|
502
|
-
modelunits?: RhinoModelUnit | null;
|
|
503
|
-
/** Data version (7 or 8) */
|
|
504
|
-
dataversion?: 7 | 8 | null;
|
|
505
|
-
/** Whether to use cached solution */
|
|
506
|
-
cachesolve?: boolean | null;
|
|
507
|
-
/**
|
|
508
|
-
* Opt-in: cache a solve even when the definition reported GH errors. See
|
|
509
|
-
* {@link GrasshopperBaseSchema.cacheerroredsolves}. Only meaningful with
|
|
510
|
-
* `cachesolve`.
|
|
511
|
-
*/
|
|
512
|
-
cacheerroredsolves?: boolean | null;
|
|
513
|
-
/** Per-solve live-event callback; see {@link SelvaEventTarget}. */
|
|
514
|
-
selvaevents?: SelvaEventTarget | null;
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Arguments sent to Grasshopper compute endpoint
|
|
518
|
-
* Includes config options + definition source + input values
|
|
477
|
+
* Server config plus the Grasshopper solve settings. The definition is not part
|
|
478
|
+
* of it: pass that to `solve()` and friends.
|
|
519
479
|
*/
|
|
520
|
-
interface
|
|
521
|
-
/** Input values organized by parameter */
|
|
522
|
-
values?: DataTree[];
|
|
480
|
+
interface GrasshopperComputeConfig extends ComputeConfig, GrasshopperBaseSchema {
|
|
523
481
|
/** Per-solve live-event callback; see {@link SelvaEventTarget}. */
|
|
524
482
|
selvaevents?: SelvaEventTarget | null;
|
|
525
483
|
}
|
|
526
484
|
/**
|
|
527
|
-
* Response from Grasshopper compute server
|
|
528
|
-
* Includes all schema fields + computed results
|
|
529
|
-
*
|
|
530
|
-
* `pointer` is deliberately excluded (`Omit`): the solve layer (`runSolve` in
|
|
531
|
-
* `solve.ts`) splits the server's echoed `pointer` off as the solve's
|
|
532
|
-
* `cacheKey` and strips it from the returned response, so client-returned
|
|
533
|
-
* responses never carry it.
|
|
485
|
+
* Response from Grasshopper compute server.
|
|
534
486
|
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
* rely on them without a fallback.
|
|
487
|
+
* No `pointer`: the solve returns the server's echoed pointer as its `cacheKey`
|
|
488
|
+
* instead. The echoed settings (`cachesolve`, `dataversion`) stay optional:
|
|
489
|
+
* nothing client-side enforces them.
|
|
539
490
|
*/
|
|
540
491
|
interface GrasshopperComputeResponse extends GrasshopperBaseSchema, Omit<GrasshopperDefinitionSource, 'pointer'> {
|
|
541
492
|
/**
|
|
@@ -545,12 +496,7 @@ interface GrasshopperComputeResponse extends GrasshopperBaseSchema, Omit<Grassho
|
|
|
545
496
|
* hand-built mock may omit it at runtime.
|
|
546
497
|
*/
|
|
547
498
|
modelunits: RhinoModelUnit;
|
|
548
|
-
/**
|
|
549
|
-
* The server echoes the request's full base64 definition back as `algo`, but the client strips
|
|
550
|
-
* it before returning — retaining it would pin a multi-MB copy of the definition per response,
|
|
551
|
-
* multiplied by every cache that holds responses. Always `undefined` on client-returned
|
|
552
|
-
* responses (inherited optional field from {@link GrasshopperDefinitionSource}).
|
|
553
|
-
*/
|
|
499
|
+
/** Always `undefined` on a client-returned response: the solve strips it. */
|
|
554
500
|
algo?: string | null;
|
|
555
501
|
/** Filename of the definition (always present in response) */
|
|
556
502
|
filename: string | null;
|
|
@@ -617,20 +563,19 @@ interface InputParamSchema {
|
|
|
617
563
|
}
|
|
618
564
|
//#endregion
|
|
619
565
|
//#region src/grasshopper/types/outputs.d.ts
|
|
620
|
-
/**
|
|
621
|
-
* Parsed input/output structure with raw schemas.
|
|
622
|
-
*
|
|
623
|
-
* `loadWarnings` / `loadErrors` carry the server's definition-load diagnostics
|
|
624
|
-
* (missing plugin, broken component, etc.) from the `/io` response. They are
|
|
625
|
-
* distinct from per-input parse failures (`InputParseError`): these come from
|
|
626
|
-
* the server loading the definition, those from the client typing an input.
|
|
627
|
-
*/
|
|
566
|
+
/** Input/output schemas as the `/io` endpoint reports them, keys canonicalized. */
|
|
628
567
|
interface GrasshopperParsedIORaw {
|
|
629
568
|
inputs: InputParamSchema[];
|
|
630
569
|
outputs: OutputParamSchema[];
|
|
631
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* Warnings the server raised loading the definition (e.g. an obsolete
|
|
572
|
+
* component). Distinct from `parseErrors`, the client failing to type an input.
|
|
573
|
+
*/
|
|
632
574
|
loadWarnings?: string[];
|
|
633
|
-
/**
|
|
575
|
+
/**
|
|
576
|
+
* Errors the server raised loading the definition (e.g. a missing plugin).
|
|
577
|
+
* When present, `inputs`/`outputs` may be incomplete.
|
|
578
|
+
*/
|
|
634
579
|
loadErrors?: string[];
|
|
635
580
|
}
|
|
636
581
|
/**
|
|
@@ -649,43 +594,26 @@ interface InputParseError {
|
|
|
649
594
|
/** Error code from the underlying ComputeError, if available. */
|
|
650
595
|
code?: string;
|
|
651
596
|
}
|
|
652
|
-
/**
|
|
653
|
-
|
|
654
|
-
*
|
|
655
|
-
* `parseErrors` is populated when one or more inputs failed validation and
|
|
656
|
-
* fell back to a safe default. The result is still usable, but the UI should
|
|
657
|
-
* surface these so the user can fix their definition.
|
|
658
|
-
*/
|
|
659
|
-
interface GrasshopperParsedIO {
|
|
597
|
+
/** {@link GrasshopperParsedIORaw} with each input parsed into its typed {@link InputParam}. */
|
|
598
|
+
interface GrasshopperParsedIO extends Omit<GrasshopperParsedIORaw, 'inputs'> {
|
|
660
599
|
inputs: InputParam[];
|
|
661
|
-
outputs: OutputParamSchema[];
|
|
662
|
-
parseErrors?: InputParseError[];
|
|
663
600
|
/**
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
* list. Distinct from `parseErrors` (client-side input typing failures).
|
|
601
|
+
* Inputs that failed validation and got a safe default. The result is still
|
|
602
|
+
* usable, but surface these so the user can fix their definition.
|
|
667
603
|
*/
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* Server-side definition-load errors from the `/io` response (e.g. a missing
|
|
671
|
-
* plugin that left inputs unresolved). When present, the inputs/outputs may
|
|
672
|
-
* be incomplete — the user needs to fix their server/definition.
|
|
673
|
-
*/
|
|
674
|
-
loadErrors?: string[];
|
|
604
|
+
parseErrors?: InputParseError[];
|
|
675
605
|
}
|
|
676
606
|
//#endregion
|
|
677
607
|
//#region src/grasshopper/scheduler/types.d.ts
|
|
678
608
|
/**
|
|
679
|
-
*
|
|
609
|
+
* How concurrent `solve()` calls interact.
|
|
680
610
|
*
|
|
681
|
-
* - `latest-wins`:
|
|
682
|
-
*
|
|
683
|
-
* - `queue`: FIFO
|
|
684
|
-
*
|
|
685
|
-
* - `parallel`: No scheduling — calls run concurrently up to `maxConcurrent`.
|
|
686
|
-
* Closest to plain `client.solve()` but with shared cancel/state.
|
|
611
|
+
* - `latest-wins`: one in flight at a time. A new call supersedes the pending
|
|
612
|
+
* one and aborts the one in flight. For slider scrubs and live UIs.
|
|
613
|
+
* - `queue`: FIFO, every call runs to completion, up to `maxConcurrent` at
|
|
614
|
+
* once (default 1). For "submit job" flows where every request matters.
|
|
687
615
|
*/
|
|
688
|
-
type SchedulerMode = 'latest-wins' | 'queue'
|
|
616
|
+
type SchedulerMode = 'latest-wins' | 'queue';
|
|
689
617
|
interface CacheOptions {
|
|
690
618
|
/**
|
|
691
619
|
* Total byte budget for retained responses, evicted LRU. The only size bound
|
|
@@ -696,6 +624,8 @@ interface CacheOptions {
|
|
|
696
624
|
* fetch boundary — no re-serialization); a response without that hint
|
|
697
625
|
* (custom executor) is sized by a one-off `JSON.stringify`. A single
|
|
698
626
|
* response larger than the whole budget is served but never retained.
|
|
627
|
+
* Parsed, a response of many small items holds more heap than its wire size,
|
|
628
|
+
* so leave headroom.
|
|
699
629
|
*
|
|
700
630
|
* Required and must be > 0 — to disable caching, pass `cache: false`.
|
|
701
631
|
*/
|
|
@@ -729,7 +659,7 @@ interface SolveSchedulerOptions {
|
|
|
729
659
|
* excluding the ones already in flight). When the queue is full, a new
|
|
730
660
|
* `solve()` is rejected immediately with `code: QUEUE_FULL` (retryable, meant to
|
|
731
661
|
* map to HTTP 503 + Retry-After) instead of piling up unbounded. Bounds the
|
|
732
|
-
* miss path under load. Only applies to `queue`
|
|
662
|
+
* miss path under load. Only applies to `queue` mode —
|
|
733
663
|
* `latest-wins` has an intrinsic depth of 1. Default: unbounded.
|
|
734
664
|
*/
|
|
735
665
|
maxQueueDepth?: number;
|
|
@@ -737,8 +667,7 @@ interface SolveSchedulerOptions {
|
|
|
737
667
|
* Backpressure — max time (ms) a call may sit queued before it starts
|
|
738
668
|
* executing. If it's still waiting after this long it's rejected with
|
|
739
669
|
* `code: QUEUE_TIMEOUT` rather than burning compute on a stale request.
|
|
740
|
-
* Bounds tail latency. Only applies to `queue`
|
|
741
|
-
* no deadline.
|
|
670
|
+
* Bounds tail latency. Only applies to `queue` mode. Default: no deadline.
|
|
742
671
|
*/
|
|
743
672
|
queueWaitMs?: number;
|
|
744
673
|
timeoutMs?: number;
|
|
@@ -750,15 +679,11 @@ interface SolveSchedulerOptions {
|
|
|
750
679
|
*/
|
|
751
680
|
cache?: false | CacheOptions;
|
|
752
681
|
/**
|
|
753
|
-
*
|
|
754
|
-
*
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
* Requires a `cacheKeyExecutor` to be supplied (the client wires one). Has no
|
|
759
|
-
* effect for URL-pointer definitions (already a reference). On a server-side
|
|
760
|
-
* cache miss the executor transparently falls back to a full upload, so this
|
|
761
|
-
* is safe to leave on. Default: `true` when a `cacheKeyExecutor` is present.
|
|
682
|
+
* Upload a definition once, then solve it by the server's cache key (`pointer`)
|
|
683
|
+
* instead of re-sending the bytes; a `DefinitionRef` also skips its `load()`.
|
|
684
|
+
* When the server has evicted the key, the solve falls back to a full upload,
|
|
685
|
+
* so this is safe to leave on. No effect for URL definitions, which are
|
|
686
|
+
* already a reference. Default `true`.
|
|
762
687
|
*/
|
|
763
688
|
reuseServerDefinitionCache?: boolean;
|
|
764
689
|
/** Lifecycle hooks — fired in order. Errors thrown by hooks are logged, not rethrown. */
|
|
@@ -780,12 +705,10 @@ type SolveResult = {
|
|
|
780
705
|
durationMs: number;
|
|
781
706
|
fromCache: boolean;
|
|
782
707
|
/**
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
* fast path didn't run (reuse disabled, or a non-reusable definition such
|
|
788
|
-
* as a remote URL).
|
|
708
|
+
* Whether this solve uploaded the full definition: `true` on its first
|
|
709
|
+
* solve or after the server evicted the cache key, `false` when the server
|
|
710
|
+
* reused its cached copy via the pointer. `undefined` for a `fromCache`
|
|
711
|
+
* hit, or when reuse is off or the definition is a URL.
|
|
789
712
|
*/
|
|
790
713
|
definitionReuploaded?: boolean;
|
|
791
714
|
} | {
|
|
@@ -795,39 +718,45 @@ type SolveResult = {
|
|
|
795
718
|
} | {
|
|
796
719
|
status: 'superseded';
|
|
797
720
|
};
|
|
798
|
-
type SolveExecutor = (definition: SolveDefinition, dataTree: DataTree[], config: GrasshopperComputeConfig) => Promise<GrasshopperComputeResponse>;
|
|
799
721
|
/**
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
803
|
-
* scheduler can update its definition→key map, plus whether the fast path
|
|
804
|
-
* `missed` (for telemetry). When `cacheKey` is null it's a first solve — upload
|
|
805
|
-
* fully and capture the key the server assigns.
|
|
806
|
-
*
|
|
807
|
-
* Supplied by the client (which owns the solve primitives); the scheduler stays
|
|
808
|
-
* decoupled from the transport.
|
|
722
|
+
* Solves by `cacheKey` when given one, otherwise uploads. Reports the server's
|
|
723
|
+
* (possibly new) key and whether the full definition was uploaded (`missed`).
|
|
724
|
+
* The scheduler passes `null` whenever server-definition reuse is off.
|
|
809
725
|
*/
|
|
810
|
-
type
|
|
726
|
+
type SolveExecutor = (definition: SolveDefinition, dataTree: DataTree[], cacheKey: string | null, config: GrasshopperComputeConfig) => Promise<{
|
|
811
727
|
response: GrasshopperComputeResponse;
|
|
812
728
|
cacheKey: string | null;
|
|
813
729
|
missed: boolean;
|
|
814
730
|
}>;
|
|
731
|
+
interface SchedulerSolveOptions {
|
|
732
|
+
signal?: AbortSignal;
|
|
733
|
+
/** Per-solve live-event callback. Not part of the cache key: it names where events go, not what is solved. */
|
|
734
|
+
selvaevents?: SelvaEventTarget;
|
|
735
|
+
/**
|
|
736
|
+
* This call's `Server-Timing` breakdown, after the client config's own `onServerTiming`.
|
|
737
|
+
* Never fires for a `fromCache` hit, which sends no request.
|
|
738
|
+
*/
|
|
739
|
+
onServerTiming?: (timing: ServerTiming, requestId: string) => void;
|
|
740
|
+
}
|
|
741
|
+
/** What `solveDetailed()` resolves with: the response plus how this call got it. */
|
|
742
|
+
interface SolveDetail {
|
|
743
|
+
response: GrasshopperComputeResponse;
|
|
744
|
+
/** Served from the scheduler's response cache without a request. */
|
|
745
|
+
fromCache: boolean;
|
|
746
|
+
/** Same meaning as on {@link SolveResult}. */
|
|
747
|
+
definitionReuploaded?: boolean;
|
|
748
|
+
/** Executor wall time; `0` for a `fromCache` hit. */
|
|
749
|
+
durationMs: number;
|
|
750
|
+
}
|
|
815
751
|
//#endregion
|
|
816
752
|
//#region src/grasshopper/scheduler/solve-scheduler.d.ts
|
|
817
753
|
/**
|
|
818
|
-
*
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
* - Configurable scheduling (latest-wins for sliders, queue for jobs)
|
|
823
|
-
* - Backpressure (bounded queue depth + queue-wait deadline) for the miss path
|
|
824
|
-
* - In-flight cancellation (per-call signal + cancelAll)
|
|
754
|
+
* Adds to a plain solve call:
|
|
755
|
+
* - Scheduling (latest-wins for sliders, queue for jobs)
|
|
756
|
+
* - Backpressure (bounded queue depth + queue-wait deadline)
|
|
757
|
+
* - Cancellation (per-call signal + cancelAll)
|
|
825
758
|
* - Optional response caching for repeated inputs
|
|
826
|
-
* - Lifecycle hooks
|
|
827
|
-
* - State observability via subscribe()
|
|
828
|
-
*
|
|
829
|
-
* Multiple schedulers can share a single GrasshopperClient — typically one
|
|
830
|
-
* per UI surface (e.g. one for slider scrubs, one for long-running submits).
|
|
759
|
+
* - Lifecycle hooks (start / settle / superseded) and state via subscribe()
|
|
831
760
|
*
|
|
832
761
|
* @example
|
|
833
762
|
* ```ts
|
|
@@ -850,11 +779,6 @@ export declare class SolveScheduler {
|
|
|
850
779
|
private readonly executor;
|
|
851
780
|
private readonly baseConfig;
|
|
852
781
|
private readonly mode;
|
|
853
|
-
/**
|
|
854
|
-
* Mutable via {@link setMaxConcurrent}: the compute server's worker pool can grow
|
|
855
|
-
* or shrink while this scheduler is alive, and the dispatch loops re-read this on
|
|
856
|
-
* every pass rather than capturing it.
|
|
857
|
-
*/
|
|
858
782
|
private maxConcurrent;
|
|
859
783
|
private readonly maxQueueDepth;
|
|
860
784
|
private readonly queueWaitMs;
|
|
@@ -865,38 +789,30 @@ export declare class SolveScheduler {
|
|
|
865
789
|
private readonly cacheTtl;
|
|
866
790
|
private readonly cacheErroredSolves;
|
|
867
791
|
private readonly cache;
|
|
868
|
-
/** Sum of `sizeBytes` across retained cache entries. */
|
|
869
792
|
private cacheBytes;
|
|
870
|
-
/**
|
|
871
|
-
* Cumulative hit/miss/eviction counters for {@link cacheStats}. Deliberately
|
|
872
|
-
* NOT reset by `clearCache()` — they measure this scheduler's whole lifetime,
|
|
873
|
-
* so a hit rate stays comparable across a session rather than restarting at
|
|
874
|
-
* every clear.
|
|
875
|
-
*/
|
|
876
793
|
private cacheHits;
|
|
877
794
|
private cacheMisses;
|
|
878
795
|
private cacheEvictions;
|
|
879
|
-
/** Optional cache-key-aware executor and whether server-def-cache reuse is on. */
|
|
880
|
-
private readonly cacheKeyExecutor?;
|
|
881
796
|
private readonly reuseServerDefinitionCache;
|
|
882
|
-
/**
|
|
797
|
+
/** Definition hash → the server's cache key (`pointer`) for it. */
|
|
883
798
|
private readonly serverCacheKeys;
|
|
799
|
+
/** A string definition re-sent unchanged is compared with this, far cheaper than hashing it. */
|
|
800
|
+
private lastStringDefinition;
|
|
884
801
|
private readonly onStart?;
|
|
885
802
|
private readonly onSettle?;
|
|
886
803
|
private readonly onSuperseded?;
|
|
887
804
|
private readonly subscribers;
|
|
888
805
|
private readonly inFlight;
|
|
889
806
|
private pendingForLatestWins;
|
|
890
|
-
private readonly
|
|
807
|
+
private readonly fifo;
|
|
891
808
|
private _lastResult;
|
|
892
809
|
private _lastError;
|
|
893
810
|
private _lastDurationMs;
|
|
894
|
-
/** Ordinal handed to each solve() call. */
|
|
895
811
|
private solveSeq;
|
|
896
|
-
/** seq of the solve that last wrote _lastResult
|
|
812
|
+
/** seq of the solve that last wrote `_lastResult`/`_lastError`. */
|
|
897
813
|
private lastStateSeq;
|
|
898
814
|
private disposed;
|
|
899
|
-
constructor(executor: SolveExecutor, baseConfig: GrasshopperComputeConfig, options?: SolveSchedulerOptions
|
|
815
|
+
constructor(executor: SolveExecutor, baseConfig: GrasshopperComputeConfig, options?: SolveSchedulerOptions);
|
|
900
816
|
get isSolving(): boolean;
|
|
901
817
|
get hasPending(): boolean;
|
|
902
818
|
get inFlightCount(): number;
|
|
@@ -925,23 +841,16 @@ export declare class SolveScheduler {
|
|
|
925
841
|
* - Rejects with `code: ErrorCodes.SUPERSEDED` when the call was canceled because
|
|
926
842
|
* newer values arrived (latest-wins mode).
|
|
927
843
|
* - Rejects with `code: ErrorCodes.ABORTED` when the call was canceled via
|
|
928
|
-
*
|
|
844
|
+
* its own `signal` (queued or running) or `cancelAll()`.
|
|
929
845
|
* - Rejects with `code: ErrorCodes.QUEUE_FULL` when `maxQueueDepth` is set and
|
|
930
846
|
* the queue was already full (backpressure; `statusCode: 503`).
|
|
931
847
|
* - Rejects with `code: ErrorCodes.QUEUE_TIMEOUT` when `queueWaitMs` is set and
|
|
932
848
|
* the call sat queued longer than that before starting (`statusCode: 503`).
|
|
933
849
|
*
|
|
934
|
-
*
|
|
935
|
-
*
|
|
936
|
-
*
|
|
937
|
-
*
|
|
938
|
-
* server-pointer map alike) without materializing bytes — `load()` runs only
|
|
939
|
-
* when an upload is unavoidable. Its immutability contract is trusted here:
|
|
940
|
-
* a reused key serves the other content's cached solve.
|
|
941
|
-
*
|
|
942
|
-
* Responses served from the cache (and via `lastResult`) are shared objects,
|
|
943
|
-
* not copies — treat them as immutable. Mutating one poisons every later
|
|
944
|
-
* cache hit for that key.
|
|
850
|
+
* Don't mutate a `Uint8Array` definition after solving it. Responses served
|
|
851
|
+
* from the cache (and via `lastResult`) are shared objects, not copies —
|
|
852
|
+
* treat them as immutable. Mutating one poisons every later cache hit for
|
|
853
|
+
* that key.
|
|
945
854
|
*
|
|
946
855
|
* Partial-success contract: unlike `GrasshopperClient.solve()`, which throws
|
|
947
856
|
* `COMPUTATION_ERROR` when the response carries solver errors, this RESOLVES
|
|
@@ -949,79 +858,45 @@ export declare class SolveScheduler {
|
|
|
949
858
|
* success must not be treated as a result (see `cacheErroredSolves` for the
|
|
950
859
|
* caching side of the same distinction).
|
|
951
860
|
*/
|
|
952
|
-
solve(definition: SolveDefinition, dataTree: DataTree[], options?:
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
/**
|
|
957
|
-
* Record last-result state, but only if no newer solve has written since —
|
|
958
|
-
* a slow solve settling late must not overwrite the state a newer solve
|
|
959
|
-
* (or cache hit) already published.
|
|
960
|
-
*/
|
|
861
|
+
solve(definition: SolveDefinition, dataTree: DataTree[], options?: SchedulerSolveOptions): Promise<GrasshopperComputeResponse>;
|
|
862
|
+
/** {@link solve}, also resolving with whether this call hit the cache and how long it took. */
|
|
863
|
+
solveDetailed(definition: SolveDefinition, dataTree: DataTree[], options?: SchedulerSolveOptions): Promise<SolveDetail>;
|
|
864
|
+
/** A slow solve settling late must not overwrite state a newer solve or cache hit published. */
|
|
961
865
|
private writeLastState;
|
|
962
866
|
/** latest-wins: supersede the pending item and abort everything in flight. */
|
|
963
867
|
private supersedeCurrent;
|
|
964
|
-
|
|
868
|
+
private dequeue;
|
|
965
869
|
private abortQueuedItem;
|
|
966
|
-
/**
|
|
967
|
-
* Backpressure: settle an incoming item as QUEUE_FULL without ever enqueuing
|
|
968
|
-
* it. The structured context lets an HTTP layer map it to 503 + Retry-After.
|
|
969
|
-
*/
|
|
870
|
+
/** The structured context lets an HTTP layer map QUEUE_FULL to 503 + Retry-After. */
|
|
970
871
|
private shedAsQueueFull;
|
|
971
|
-
/**
|
|
972
|
-
* Arm the queue-wait deadline for an item about to be queued. If the item is
|
|
973
|
-
* still waiting when it fires, it's rejected as QUEUE_TIMEOUT and removed from
|
|
974
|
-
* the queue. Cleared on execute/settle via {@link clearQueueWaitTimer}.
|
|
975
|
-
*/
|
|
976
872
|
private armQueueWaitTimer;
|
|
977
|
-
/** Clear a queued item's wait-deadline timer, if one is pending. */
|
|
978
873
|
private clearQueueWaitTimer;
|
|
979
874
|
private enqueue;
|
|
980
875
|
private execute;
|
|
981
|
-
/**
|
|
982
|
-
* Run the solve, using the server-definition-cache fast path when it's
|
|
983
|
-
* enabled and the definition is reusable. Learns/updates the definition's
|
|
984
|
-
* server cache key from the result so later solves can reference it.
|
|
985
|
-
*
|
|
986
|
-
* `definitionHash` is the {@link hashDefinition} result already computed at
|
|
987
|
-
* `solve()` entry — threaded through rather than recomputed, so each solve
|
|
988
|
-
* pays exactly one linear pass over the definition (issue 57).
|
|
989
|
-
*/
|
|
990
876
|
private runExecutor;
|
|
877
|
+
private hashDefinitionMemo;
|
|
991
878
|
private drainNext;
|
|
992
879
|
private supersede;
|
|
993
880
|
private makeAbortError;
|
|
994
881
|
/**
|
|
995
|
-
*
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
*
|
|
999
|
-
* promise silently ignores a second settle. This guard is the single place the
|
|
1000
|
-
* settle-once invariant lives: it makes the *first* settle win and reports
|
|
1001
|
-
* whether this call was that winner, so callers fire their own hook only when
|
|
1002
|
-
* they actually settled. Any new settle path must go through here (or
|
|
1003
|
-
* {@link settleSuccess}) so the guard can't be forgotten.
|
|
1004
|
-
*
|
|
1005
|
-
* @returns `true` if this call settled the item; `false` if it was already settled.
|
|
882
|
+
* The executor, `supersede`, `cancelAll`, abort and the queue limits can all race to settle one
|
|
883
|
+
* item, and a promise ignores a second settle silently. The first settle wins; the return value
|
|
884
|
+
* says whether this call won, so only the winner fires its hook. Every settle path goes through
|
|
885
|
+
* here or {@link settleSuccess}.
|
|
1006
886
|
*/
|
|
1007
887
|
private settleError;
|
|
1008
888
|
/**
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
* @returns `true` if this call settled the item; `false` if it was already settled.
|
|
889
|
+
* Fires `onSettle` for queued items too, so a consumer counting solves in progress doesn't
|
|
890
|
+
* leak one. A supersede settles through {@link settleError} and fires `onSuperseded` instead.
|
|
1013
891
|
*/
|
|
892
|
+
private fail;
|
|
1014
893
|
private settleSuccess;
|
|
1015
|
-
/** Detach the queued-phase abort listener, if one is still attached. */
|
|
1016
894
|
private removeQueuedAbortHandler;
|
|
1017
|
-
private isAbortLikeError;
|
|
1018
895
|
private normalizeExecutionError;
|
|
1019
896
|
/** Cancel everything — in-flight and pending. */
|
|
1020
897
|
cancelAll(): void;
|
|
1021
|
-
private rejectAsAborted;
|
|
1022
898
|
private readCache;
|
|
1023
899
|
private writeCache;
|
|
1024
|
-
/** Remove one cache entry and release its bytes from the running total. */
|
|
1025
900
|
private dropCacheEntry;
|
|
1026
901
|
clearCache(): void;
|
|
1027
902
|
/**
|
|
@@ -1061,6 +936,19 @@ interface SolveOptions {
|
|
|
1061
936
|
/** Per-solve live-event callback, forwarded onto the request body. */
|
|
1062
937
|
selvaevents?: SelvaEventTarget;
|
|
1063
938
|
}
|
|
939
|
+
/** Options for {@link GrasshopperClient.create} that shape construction, not the solves. */
|
|
940
|
+
interface CreateClientOptions {
|
|
941
|
+
/**
|
|
942
|
+
* Retry ladder for the liveness probe: `attempts` retries after the first probe (default 2),
|
|
943
|
+
* with exponential backoff from `baseDelayMs` (default 250) capped at `maxDelayMs` (default 1000).
|
|
944
|
+
* Independent of `config.retry`, which governs solves only.
|
|
945
|
+
*/
|
|
946
|
+
probe?: {
|
|
947
|
+
attempts?: number;
|
|
948
|
+
baseDelayMs?: number;
|
|
949
|
+
maxDelayMs?: number;
|
|
950
|
+
};
|
|
951
|
+
}
|
|
1064
952
|
/**
|
|
1065
953
|
* GrasshopperClient provides a simple API for interacting with a Rhino Compute server and grasshopper.
|
|
1066
954
|
*
|
|
@@ -1078,7 +966,8 @@ interface SolveOptions {
|
|
|
1078
966
|
* });
|
|
1079
967
|
*
|
|
1080
968
|
* try {
|
|
1081
|
-
* const
|
|
969
|
+
* const io = await client.getIO(definitionUrl);
|
|
970
|
+
* const result = await client.solve(definitionUrl, TreeBuilder.fromInputParams(io.inputs));
|
|
1082
971
|
* } finally {
|
|
1083
972
|
* await client.dispose(); // Clean up resources
|
|
1084
973
|
* }
|
|
@@ -1109,16 +998,12 @@ declare class GrasshopperClient {
|
|
|
1109
998
|
* a user who clicked Solve, so the retry ladder must not spend its whole
|
|
1110
999
|
* budget confirming that a machine is switched off.
|
|
1111
1000
|
*
|
|
1112
|
-
* Each probe is bounded by {@link CREATE_PROBE_TIMEOUT_MS} rather than the
|
|
1113
|
-
* stats default: a healthy `GET /` answers in milliseconds, so a longer
|
|
1114
|
-
* per-probe timeout only multiplies the wait when the server is unreachable.
|
|
1115
|
-
*
|
|
1116
1001
|
* @throws {ComputeError} with code NETWORK_ERROR if the server stays
|
|
1117
1002
|
* unreachable across all attempts. `context.probeVerdict` carries the
|
|
1118
1003
|
* {@link ProbeVerdict} so callers can render a specific cause.
|
|
1119
1004
|
* @throws {ComputeError} with code INVALID_CONFIG if configuration is invalid
|
|
1120
1005
|
*/
|
|
1121
|
-
static create(config: GrasshopperComputeConfig): Promise<GrasshopperClient>;
|
|
1006
|
+
static create(config: GrasshopperComputeConfig, options?: CreateClientOptions): Promise<GrasshopperClient>;
|
|
1122
1007
|
/**
|
|
1123
1008
|
* Gets the client's configuration.
|
|
1124
1009
|
* Useful for passing to lower-level functions.
|
|
@@ -1162,16 +1047,7 @@ declare class GrasshopperClient {
|
|
|
1162
1047
|
* Call this when you're done using the client.
|
|
1163
1048
|
*/
|
|
1164
1049
|
dispose(): Promise<void>;
|
|
1165
|
-
/**
|
|
1166
|
-
* Ensures the client hasn't been disposed.
|
|
1167
|
-
*/
|
|
1168
1050
|
private ensureNotDisposed;
|
|
1169
|
-
/**
|
|
1170
|
-
* Validates and normalizes a compute configuration.
|
|
1171
|
-
*
|
|
1172
|
-
* @throws {ComputeError} with code INVALID_CONFIG if configuration is invalid
|
|
1173
|
-
*/
|
|
1174
|
-
private normalizeComputeConfig;
|
|
1175
1051
|
}
|
|
1176
1052
|
//#endregion
|
|
1177
1053
|
//#region src/grasshopper/io/output/response-processors.d.ts
|
|
@@ -1200,39 +1076,13 @@ interface GetValuesResult<T = ParsedContext> {
|
|
|
1200
1076
|
}
|
|
1201
1077
|
//#endregion
|
|
1202
1078
|
//#region src/grasshopper/client/grasshopper-response-processor.d.ts
|
|
1203
|
-
/**
|
|
1204
|
-
* High-level wrapper for interacting with Grasshopper Compute responses.
|
|
1205
|
-
*
|
|
1206
|
-
* This class exposes a clean, consistent API for accessing parsed values,
|
|
1207
|
-
* geometry, and produced files. It is designed to be the primary interface
|
|
1208
|
-
* when working with Grasshopper results in client applications.
|
|
1209
|
-
*/
|
|
1079
|
+
/** Reads parsed values and produced files out of one compute response. */
|
|
1210
1080
|
declare class GrasshopperResponseProcessor {
|
|
1211
|
-
/**
|
|
1212
|
-
* The raw compute response. Public so callers can hand it to a renderer-side parser — e.g.
|
|
1213
|
-
* `getThreeMeshesFromComputeResponse` in `@selvajs/visualization/parse`, which replaced this
|
|
1214
|
-
* class's former `extractMeshesFromResponse()`.
|
|
1215
|
-
*/
|
|
1081
|
+
/** Hand it to a mesh parser such as `@selvajs/visualization/parse`. */
|
|
1216
1082
|
readonly response: GrasshopperComputeResponse;
|
|
1217
|
-
/**
|
|
1218
|
-
* Retained for call-signature compatibility. Its only consumer was the removed
|
|
1219
|
-
* `extractMeshesFromResponse()`, which merged it into the parse options; pass `debug`
|
|
1220
|
-
* directly to the parser in `@selvajs/visualization/parse` instead.
|
|
1221
|
-
*/
|
|
1222
|
-
readonly debug: boolean;
|
|
1223
1083
|
constructor(
|
|
1224
|
-
/**
|
|
1225
|
-
|
|
1226
|
-
* `getThreeMeshesFromComputeResponse` in `@selvajs/visualization/parse`, which replaced this
|
|
1227
|
-
* class's former `extractMeshesFromResponse()`.
|
|
1228
|
-
*/
|
|
1229
|
-
response: GrasshopperComputeResponse,
|
|
1230
|
-
/**
|
|
1231
|
-
* Retained for call-signature compatibility. Its only consumer was the removed
|
|
1232
|
-
* `extractMeshesFromResponse()`, which merged it into the parse options; pass `debug`
|
|
1233
|
-
* directly to the parser in `@selvajs/visualization/parse` instead.
|
|
1234
|
-
*/
|
|
1235
|
-
debug?: boolean);
|
|
1084
|
+
/** Hand it to a mesh parser such as `@selvajs/visualization/parse`. */
|
|
1085
|
+
response: GrasshopperComputeResponse);
|
|
1236
1086
|
/**
|
|
1237
1087
|
* Extract all values in the response.
|
|
1238
1088
|
*
|
|
@@ -1269,19 +1119,6 @@ declare class GrasshopperResponseProcessor {
|
|
|
1269
1119
|
} | {
|
|
1270
1120
|
byId: string;
|
|
1271
1121
|
}, options?: GetValuesOptions): any;
|
|
1272
|
-
/**
|
|
1273
|
-
* REMOVED: `extractMeshesFromResponse()`. Mesh decoding lives in `@selvajs/visualization` now, so
|
|
1274
|
-
* this package stays pure solve/data and carries no `three` dependency. Call the parser directly
|
|
1275
|
-
* with the raw response:
|
|
1276
|
-
*
|
|
1277
|
-
* ```ts
|
|
1278
|
-
* import { getThreeMeshesFromComputeResponse } from '@selvajs/visualization/parse';
|
|
1279
|
-
*
|
|
1280
|
-
* const meshes = await getThreeMeshesFromComputeResponse(processor.response, { rhino });
|
|
1281
|
-
* scene.add(...meshes);
|
|
1282
|
-
* ```
|
|
1283
|
-
*/
|
|
1284
|
-
private getFileData;
|
|
1285
1122
|
/**
|
|
1286
1123
|
* Download all files generated by Grasshopper, optionally including
|
|
1287
1124
|
* additional user-provided files.
|
|
@@ -1313,102 +1150,58 @@ declare class GrasshopperResponseProcessor {
|
|
|
1313
1150
|
* The output is a cache key, so the invariant that matters is: two payloads
|
|
1314
1151
|
* that serialize differently on the wire must stringify differently here
|
|
1315
1152
|
* (false misses are harmless; false hits serve the wrong cached solve).
|
|
1153
|
+
* Non-JSON values get unquoted markers (`{u8:…}`, `[Circular]`) that no JSON
|
|
1154
|
+
* value stringifies to, so a plain object can't pose as one.
|
|
1316
1155
|
*/
|
|
1317
1156
|
export declare function stableStringify(value: unknown): string;
|
|
1318
|
-
/**
|
|
1319
|
-
* Hash definition and data tree into a stable cache key.
|
|
1320
|
-
*
|
|
1321
|
-
* The definition is the *identity* of what we solve, so a binary definition is
|
|
1322
|
-
* hashed over its full content (`fnv1aBytes`) — a length-only or sampled key
|
|
1323
|
-
* would let two different `.gh` files collide and serve one's cached solve for
|
|
1324
|
-
* the other. `.gh` files are small enough that a single linear pass is
|
|
1325
|
-
* negligible. A {@link DefinitionRef} is keyed by its `key` alone — the
|
|
1326
|
-
* caller-declared identity of immutable bytes — so no bytes are materialized
|
|
1327
|
-
* or hashed at all.
|
|
1328
|
-
*
|
|
1329
|
-
* The key keeps the definition and tree hashes as separate parts rather than
|
|
1330
|
-
* collapsing them into one 32-bit hash: a single FNV pass over the pair would
|
|
1331
|
-
* birthday-collide quadratically in cache size, while requiring both 32-bit
|
|
1332
|
-
* parts (plus lengths) to collide at once makes that negligible.
|
|
1333
|
-
*/
|
|
1157
|
+
/** The scheduler's solve-cache key for a definition and its input tree. */
|
|
1334
1158
|
export declare function hashSolveInput(definition: SolveDefinition, dataTree: unknown): string;
|
|
1335
1159
|
/**
|
|
1336
|
-
*
|
|
1337
|
-
*
|
|
1338
|
-
* with different inputs. Same full-content hashing as {@link hashSolveInput}: a
|
|
1339
|
-
* binary definition is hashed over all its bytes so two distinct `.gh` files of
|
|
1340
|
-
* equal length can't share a cache key. A {@link DefinitionRef} is keyed by its
|
|
1341
|
-
* `key` verbatim (refs are short identities like UUIDs, safe as Map keys) —
|
|
1342
|
-
* its immutability contract makes the key equivalent to a content hash.
|
|
1160
|
+
* A definition's identity, without its inputs. Strings and bytes are hashed over their full
|
|
1161
|
+
* content; a `DefinitionRef` uses its `key`.
|
|
1343
1162
|
*/
|
|
1344
1163
|
export declare function hashDefinition(definition: SolveDefinition): string;
|
|
1345
1164
|
//#endregion
|
|
1346
1165
|
//#region src/grasshopper/solve.d.ts
|
|
1347
1166
|
/**
|
|
1348
|
-
*
|
|
1167
|
+
* Run one solve. `GrasshopperClient.solve()` adds input validation and throws on solver errors.
|
|
1349
1168
|
*
|
|
1350
|
-
* @
|
|
1351
|
-
*
|
|
1352
|
-
* @
|
|
1353
|
-
* @param definition - The Grasshopper definition, which can be:
|
|
1354
|
-
* - A URL string (e.g., 'https://example.com/definition.gh')
|
|
1355
|
-
* - A base64-encoded string of the .gh file
|
|
1356
|
-
* - A plain string (will be base64-encoded)
|
|
1357
|
-
* - A Uint8Array of the .gh file (will be base64-encoded)
|
|
1358
|
-
* - A `DefinitionRef` (bytes are loaded via `ref.load()` for the upload)
|
|
1359
|
-
* @param config - Compute configuration (server URL, API key, etc. along with optional timeout, units, etc.)
|
|
1360
|
-
* @returns An object containing the compute result and extracted file data.
|
|
1169
|
+
* @param definition - A URL (sent as a pointer), base64 `.gh` content, raw `.gh` bytes, or a
|
|
1170
|
+
* `DefinitionRef` (loaded for the upload). Any other string is encoded as the definition text.
|
|
1171
|
+
* @returns The compute response, without the server's `pointer` and echoed `algo`.
|
|
1361
1172
|
*
|
|
1362
1173
|
* @example
|
|
1363
|
-
* // Using a URL
|
|
1364
1174
|
* await solveGrasshopperDefinition(trees, 'https://example.com/definition.gh', config);
|
|
1365
|
-
*
|
|
1366
|
-
* // Using a base64 string
|
|
1367
|
-
* await solveGrasshopperDefinition(trees, 'UEsDBBQAAAAIAL...', config);
|
|
1368
|
-
*
|
|
1369
|
-
* // Using binary data
|
|
1370
|
-
* const fileData = new Uint8Array([...]);
|
|
1371
|
-
* await solveGrasshopperDefinition(trees, fileData, config);
|
|
1175
|
+
* await solveGrasshopperDefinition(trees, new Uint8Array(await readFile('model.gh')), config);
|
|
1372
1176
|
*/
|
|
1373
1177
|
export declare function solveGrasshopperDefinition(dataTree: DataTree[], definition: SolveDefinition, config: GrasshopperComputeConfig): Promise<GrasshopperComputeResponse>;
|
|
1374
1178
|
//#endregion
|
|
1375
1179
|
//#region src/grasshopper/io/definition-io.d.ts
|
|
1376
1180
|
/**
|
|
1377
|
-
* Fetches
|
|
1181
|
+
* Fetches a definition's input/output schemas without per-type parsing.
|
|
1378
1182
|
*
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
* fallbacks for missing required fields), missing/non-array `inputs`/`outputs`
|
|
1384
|
-
* coerce to `[]`, and server load diagnostics surface as
|
|
1385
|
-
* `loadWarnings`/`loadErrors` (coerced to strings). Field VALUES — notably
|
|
1386
|
-
* `default` and the `values` dropdown-label map — pass through verbatim.
|
|
1183
|
+
* Field KEYS are canonicalized to camelCase and missing required fields get a
|
|
1184
|
+
* fallback ({@link normalizeInputSchema}); a missing or non-array `inputs` /
|
|
1185
|
+
* `outputs` becomes `[]`. Field VALUES, notably `default` and the `values`
|
|
1186
|
+
* label map, pass through verbatim.
|
|
1387
1187
|
*
|
|
1388
|
-
* @param definition - The Grasshopper definition (URL, base64 string, or Uint8Array)
|
|
1389
|
-
* @param config - Compute configuration (server URL, API key, etc.)
|
|
1390
|
-
* @returns Key-normalized inputs and outputs with no per-type processing
|
|
1391
1188
|
* @throws {ComputeError} If fetch fails or response is invalid
|
|
1392
1189
|
*
|
|
1393
1190
|
* @public Use `fetchParsedDefinitionIO()` for processed, type-safe inputs
|
|
1394
1191
|
*/
|
|
1395
1192
|
export declare function fetchDefinitionIO(definition: string | Uint8Array, config: ComputeConfig): Promise<GrasshopperParsedIORaw>;
|
|
1396
1193
|
/**
|
|
1397
|
-
* Fetches
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
* @public This is the recommended way to fetch definition I/O schemas.
|
|
1194
|
+
* Fetches a definition's input/output schemas and parses each input into its
|
|
1195
|
+
* typed `InputParam`. An input that fails to parse gets a safe default
|
|
1196
|
+
* and an entry in `parseErrors`.
|
|
1401
1197
|
*
|
|
1402
|
-
* @param definition - The Grasshopper definition (URL, base64 string, or Uint8Array)
|
|
1403
|
-
* @param config - Compute configuration (server URL, API key, etc.)
|
|
1404
|
-
* @returns Processed inputs with discriminated union types and outputs
|
|
1405
1198
|
* @throws {ComputeError} If fetch fails or response is invalid
|
|
1406
1199
|
*
|
|
1407
1200
|
* @example
|
|
1408
1201
|
* ```typescript
|
|
1409
1202
|
* const { inputs, outputs } = await fetchParsedDefinitionIO(
|
|
1410
1203
|
* 'https://example.com/definition.gh',
|
|
1411
|
-
* { serverUrl: '
|
|
1204
|
+
* { serverUrl: 'http://localhost:6500', apiKey: 'YOUR_KEY' }
|
|
1412
1205
|
* );
|
|
1413
1206
|
*
|
|
1414
1207
|
* // Inputs are now strongly typed
|
|
@@ -1433,101 +1226,87 @@ interface SchemaEndpointResult<TSchema = unknown> {
|
|
|
1433
1226
|
* Read compute's `/grasshopper/schema` body: `[{ FileName, Schemas }]` per
|
|
1434
1227
|
* uploaded file, or a bare object for a single file.
|
|
1435
1228
|
*
|
|
1436
|
-
* Use this rather than unwrapping the body by hand
|
|
1437
|
-
* by server branch
|
|
1438
|
-
*
|
|
1439
|
-
* half the servers, and the endpoint answers 200 either way. The failure looks
|
|
1440
|
-
* like "this definition has no schemas", which sends you debugging the wrong
|
|
1441
|
-
* thing entirely.
|
|
1442
|
-
*
|
|
1443
|
-
* A blanket key-rewrite (the old `camelcaseKeys` approach) is NOT the fix: it
|
|
1444
|
-
* reaches inside the schemas and mangles user-authored names — `"Display3d"` →
|
|
1445
|
-
* `"display3d"`, value-list labels like `"Option A"` → `"optionA"`. Only the two
|
|
1446
|
-
* wrapper keys are read here; schema CONTENTS pass through untouched, which is
|
|
1447
|
-
* why `TSchema` is a pass-through type parameter this module never inspects.
|
|
1229
|
+
* Use this rather than unwrapping the body by hand: the wrapper keys' casing
|
|
1230
|
+
* varies by server branch, and a fixed-key read yields "no schemas" with a 200.
|
|
1231
|
+
* Only the two wrapper keys are read; schema contents pass through untouched.
|
|
1448
1232
|
*
|
|
1449
1233
|
* @typeParam TSchema - Your schema type (e.g. `UISchema`). Not inspected.
|
|
1450
|
-
* @param raw - The parsed JSON body.
|
|
1451
1234
|
*/
|
|
1452
1235
|
export declare function readSchemaResults<TSchema = unknown>(raw: unknown): SchemaEndpointResult<TSchema>[];
|
|
1453
1236
|
//#endregion
|
|
1454
1237
|
//#region src/grasshopper/io/normalize-ui-schema.d.ts
|
|
1455
1238
|
/**
|
|
1456
|
-
* Canonicalize a `/grasshopper/schema` body's key
|
|
1457
|
-
*
|
|
1458
|
-
* ## Why this exists
|
|
1459
|
-
*
|
|
1460
|
-
* Compute serializes the plugin's `UISchema` POCO, whose camelCase wire names
|
|
1461
|
-
* live in Newtonsoft `[JsonProperty]` attributes. `Selva.gha` ILRepack-merges
|
|
1462
|
-
* Newtonsoft into itself, so those attributes have type
|
|
1463
|
-
* `Selva!Newtonsoft.Json.JsonPropertyAttribute`. When the serializer that runs is
|
|
1464
|
-
* compute's OWN Newtonsoft assembly, it does not recognize that type as its own
|
|
1465
|
-
* attribute, reads no attributes at all, and falls back to raw CLR member names —
|
|
1466
|
-
* emitting `Inputs`/`Layout`/`SchemaVersion`.
|
|
1467
|
-
*
|
|
1468
|
-
* Nothing throws on the wire. Every consumer reads `schema.inputs` as
|
|
1469
|
-
* `undefined`, so the definition renders with no inputs, and `schemaVersion`
|
|
1470
|
-
* reads `undefined` — which also silently disables the newer-plugin version gate.
|
|
1471
|
-
*
|
|
1472
|
-
* This is the schema-body counterpart to {@link normalizeInputSchema}, which
|
|
1473
|
-
* solves the same split for the `/io` endpoint's param records.
|
|
1474
|
-
*
|
|
1475
|
-
* ## Why a casing rule, and not a key allowlist
|
|
1476
|
-
*
|
|
1477
|
-
* The wire names are the CLR names run through Newtonsoft's camelCase strategy,
|
|
1478
|
-
* so reproducing that strategy covers every key. An allowlist would have to
|
|
1479
|
-
* enumerate every structural key in `UISchema` and drift out of date each time
|
|
1480
|
-
* the schema gains a field, failing silently and in exactly this way again.
|
|
1481
|
-
*
|
|
1482
|
-
* ## What it does NOT touch
|
|
1239
|
+
* Canonicalize a `/grasshopper/schema` body's key casing.
|
|
1483
1240
|
*
|
|
1484
|
-
*
|
|
1485
|
-
*
|
|
1486
|
-
*
|
|
1487
|
-
*
|
|
1488
|
-
*
|
|
1489
|
-
* `
|
|
1490
|
-
* with.
|
|
1241
|
+
* Compute serializes the plugin's `UISchema`, whose camelCase wire names live in
|
|
1242
|
+
* Newtonsoft `[JsonProperty]` attributes. `Selva.gha` ILRepack-merges Newtonsoft,
|
|
1243
|
+
* so those attributes are `Selva!Newtonsoft.Json.JsonPropertyAttribute`. When
|
|
1244
|
+
* compute's OWN Newtonsoft serializes, it doesn't recognize them, reads no
|
|
1245
|
+
* attributes, and emits raw CLR names (`Inputs`, `SchemaVersion`). Nothing throws:
|
|
1246
|
+
* `schema.inputs` reads `undefined`, and so does the `schemaVersion` gate.
|
|
1491
1247
|
*
|
|
1492
|
-
*
|
|
1248
|
+
* A casing rule, not a key allowlist: the wire names are the CLR names run
|
|
1249
|
+
* through Newtonsoft's camelCase strategy, so reproducing it covers every key
|
|
1250
|
+
* without drifting each time `UISchema` gains a field.
|
|
1493
1251
|
*/
|
|
1494
1252
|
/**
|
|
1495
|
-
* Returns a schema whose structural keys are camelCase,
|
|
1496
|
-
*
|
|
1497
|
-
*
|
|
1498
|
-
* object the caller may mutate).
|
|
1499
|
-
*
|
|
1500
|
-
* Safe to call on any parsed JSON value; non-objects are returned as-is.
|
|
1253
|
+
* Returns a schema whose structural keys are camelCase, whichever Newtonsoft
|
|
1254
|
+
* serialized it. Always a fresh object the caller may mutate; non-objects are
|
|
1255
|
+
* returned as-is.
|
|
1501
1256
|
*/
|
|
1502
1257
|
export declare function normalizeUISchemaCasing<T>(raw: T): T;
|
|
1503
1258
|
//#endregion
|
|
1504
1259
|
//#region src/grasshopper/io/input/input-processors.d.ts
|
|
1505
1260
|
/**
|
|
1506
1261
|
* Parse one raw Grasshopper input schema into a typed {@link InputParam}.
|
|
1507
|
-
*
|
|
1508
|
-
* {@link processInputWithError} to receive them.
|
|
1262
|
+
* A validation failure is swallowed and replaced with a safe default.
|
|
1509
1263
|
*/
|
|
1510
1264
|
export declare function processInput(rawInput: InputParamSchema): InputParam;
|
|
1511
1265
|
//#endregion
|
|
1512
|
-
//#region src/grasshopper/
|
|
1266
|
+
//#region src/grasshopper/io/output/rhino-objects.d.ts
|
|
1513
1267
|
/**
|
|
1514
|
-
*
|
|
1268
|
+
* Sentinel a Rhino geometry decode returns when a decode was attempted
|
|
1269
|
+
* and failed hard (a registered decoder or `CommonObject.decode` threw). Carries
|
|
1270
|
+
* the original payload so callers can log or retry. Use
|
|
1271
|
+
* {@link isRhinoDecodeError} to detect it.
|
|
1515
1272
|
*/
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
*/
|
|
1521
|
-
|
|
1522
|
-
data: string | boolean | number;
|
|
1273
|
+
interface RhinoDecodeError {
|
|
1274
|
+
__decodeError: true;
|
|
1275
|
+
/** The Rhino type name the failed decode was attempted for. */
|
|
1276
|
+
type: string;
|
|
1277
|
+
/** The original (undecoded) payload. */
|
|
1278
|
+
raw: unknown;
|
|
1523
1279
|
}
|
|
1280
|
+
/** Type guard for the {@link RhinoDecodeError} sentinel. */
|
|
1281
|
+
export declare function isRhinoDecodeError(value: unknown): value is RhinoDecodeError;
|
|
1524
1282
|
/**
|
|
1525
|
-
*
|
|
1283
|
+
* Free every rhino3dm WASM object reachable from `value`.
|
|
1284
|
+
*
|
|
1285
|
+
* rhino3dm objects are emscripten bindings — JS GC never reclaims their WASM
|
|
1286
|
+
* heap allocation, so everything decoded from a solve response (`getValues`,
|
|
1287
|
+
* `getValue`) must be deleted explicitly or the heap
|
|
1288
|
+
* grows monotonically across solves (e.g. a UI decoding per slider tick).
|
|
1289
|
+
*
|
|
1290
|
+
* Walks arrays and plain objects recursively; anything exposing a `delete()`
|
|
1291
|
+
* method is treated as a WASM binding and freed (skipped if already deleted).
|
|
1292
|
+
* Safe to call more than once and on values containing no WASM objects.
|
|
1526
1293
|
*/
|
|
1527
|
-
|
|
1294
|
+
export declare function disposeRhinoObjects(value: unknown): void;
|
|
1295
|
+
//#endregion
|
|
1296
|
+
//#region src/grasshopper/data-tree/data-tree.d.ts
|
|
1297
|
+
type DataTreeValue = string | number | boolean | object | null;
|
|
1298
|
+
/** One input's value for {@link TreeBuilder.fromValues}. */
|
|
1299
|
+
interface TreeValueEntry {
|
|
1300
|
+
paramName: string;
|
|
1301
|
+
/** Matched case-insensitively. */
|
|
1302
|
+
paramType: string;
|
|
1303
|
+
/** A scalar, an array (branch `{0}`), or a branch-path map like `{ '{0;1}': [1, 2] }`. */
|
|
1304
|
+
value: unknown;
|
|
1305
|
+
minimum?: number | null;
|
|
1306
|
+
maximum?: number | null;
|
|
1307
|
+
}
|
|
1528
1308
|
/**
|
|
1529
|
-
*
|
|
1530
|
-
* Does not depend on RhinoCompute library.
|
|
1309
|
+
* Builds the Grasshopper data trees a solve takes as input.
|
|
1531
1310
|
*
|
|
1532
1311
|
* @example
|
|
1533
1312
|
* ```ts
|
|
@@ -1541,247 +1320,70 @@ export declare class TreeBuilder {
|
|
|
1541
1320
|
private innerTree;
|
|
1542
1321
|
private paramName;
|
|
1543
1322
|
constructor(paramName: string);
|
|
1544
|
-
/**
|
|
1545
|
-
* Append values to a specific path in the tree.
|
|
1546
|
-
*
|
|
1547
|
-
* @param path - Array of integers representing the branch path (e.g., [0], [0, 1])
|
|
1548
|
-
* @param items - Values to append at this path
|
|
1549
|
-
* @returns this for method chaining
|
|
1550
|
-
*/
|
|
1323
|
+
/** Append values to the branch at `path` (`[0, 1]` is `{0;1}`). */
|
|
1551
1324
|
append(path: number[], items: DataTreeValue[]): this;
|
|
1552
|
-
/**
|
|
1553
|
-
* Append a single value to a path.
|
|
1554
|
-
*
|
|
1555
|
-
* @param path - Branch path
|
|
1556
|
-
* @param item - Single value to append
|
|
1557
|
-
* @returns this for method chaining
|
|
1558
|
-
*/
|
|
1559
|
-
appendSingle(path: number[], item: DataTreeValue): this;
|
|
1560
|
-
/**
|
|
1561
|
-
* Set values from a DataTreeDefault structure.
|
|
1562
|
-
* Replaces any existing tree data.
|
|
1563
|
-
*
|
|
1564
|
-
* @param treeData - TreeBuilder structure with path keys like "{0;1}"
|
|
1565
|
-
* @returns this for method chaining
|
|
1566
|
-
*/
|
|
1325
|
+
/** Replace the tree with a branch-path map like `{ '{0;1}': [1, 2] }`. */
|
|
1567
1326
|
fromDataTreeDefault(treeData: DataTreeDefault): this;
|
|
1568
|
-
/**
|
|
1569
|
-
* Append flattened values to path [0].
|
|
1570
|
-
* Useful for simple flat inputs.
|
|
1571
|
-
*
|
|
1572
|
-
* @param values - Single value or array of values
|
|
1573
|
-
* @returns this for method chaining
|
|
1574
|
-
*/
|
|
1327
|
+
/** Append a value, or each value of an array, to branch `{0}`. */
|
|
1575
1328
|
appendFlat(values: DataTreeValue | DataTreeValue[]): this;
|
|
1576
|
-
/**
|
|
1577
|
-
* Get the flattened list of all values in the tree.
|
|
1578
|
-
*
|
|
1579
|
-
* @returns Array of all values across all branches
|
|
1580
|
-
*/
|
|
1329
|
+
/** Every value across all branches. */
|
|
1581
1330
|
flatten(): DataTreeValue[];
|
|
1582
|
-
/**
|
|
1583
|
-
* Get all paths in the tree.
|
|
1584
|
-
*
|
|
1585
|
-
* @returns Array of path strings
|
|
1586
|
-
*/
|
|
1587
|
-
getPaths(): DataTreePath[];
|
|
1588
|
-
/**
|
|
1589
|
-
* Get values at a specific path.
|
|
1590
|
-
*
|
|
1591
|
-
* @param path - Path to retrieve values from
|
|
1592
|
-
* @returns Array of values or undefined if path doesn't exist
|
|
1593
|
-
*/
|
|
1594
|
-
getPath(path: number[]): DataTreeValue[] | undefined;
|
|
1595
|
-
/**
|
|
1596
|
-
* Convert to format compatible with Grasshopper Compute API.
|
|
1597
|
-
*
|
|
1598
|
-
* @returns InnerTree object ready for compute
|
|
1599
|
-
*/
|
|
1331
|
+
/** The tree in the shape a solve request sends. */
|
|
1600
1332
|
toComputeFormat(): DataTree;
|
|
1601
|
-
/**
|
|
1602
|
-
* Get the raw InnerTree data structure.
|
|
1603
|
-
*
|
|
1604
|
-
* @returns InnerTree data
|
|
1605
|
-
*/
|
|
1606
|
-
getInnerTree(): ComputeInnerTreeData;
|
|
1607
|
-
/**
|
|
1608
|
-
* Get the parameter name.
|
|
1609
|
-
*
|
|
1610
|
-
* @returns Parameter name
|
|
1611
|
-
*/
|
|
1612
1333
|
getParamName(): string;
|
|
1613
1334
|
/**
|
|
1614
|
-
*
|
|
1615
|
-
*
|
|
1616
|
-
*
|
|
1617
|
-
* @param inputs - Array of input parameter definitions
|
|
1618
|
-
* @returns Array of InnerTree instances ready for compute
|
|
1619
|
-
*
|
|
1620
|
-
* @example
|
|
1621
|
-
* ```ts
|
|
1622
|
-
* const trees = TreeBuilder.fromInputParams(inputs);
|
|
1623
|
-
* ```
|
|
1335
|
+
* One tree per input that has a default, keyed by its nickname. Defaults are coerced and
|
|
1336
|
+
* clamped by the same rules as {@link TreeBuilder.fromValues}.
|
|
1624
1337
|
*/
|
|
1625
1338
|
static fromInputParams(inputs: InputParam[]): DataTree[];
|
|
1626
1339
|
/**
|
|
1627
|
-
*
|
|
1628
|
-
*
|
|
1629
|
-
*
|
|
1630
|
-
*
|
|
1340
|
+
* One tree per entry, coercing UI values the way Grasshopper reads them. Number and Integer
|
|
1341
|
+
* items go through the numeric coercion (Integer rounds) and are clamped to
|
|
1342
|
+
* `minimum`/`maximum`; Boolean items also accept `'true'`/`'false'`; every other type passes
|
|
1343
|
+
* through. An item that fails coercion is dropped with a warning. An entry left with no items
|
|
1344
|
+
* is omitted, so Grasshopper uses its own value; `''` is an item, not an empty value.
|
|
1631
1345
|
*/
|
|
1632
|
-
static
|
|
1346
|
+
static fromValues(entries: TreeValueEntry[]): DataTree[];
|
|
1347
|
+
private static branchesOf;
|
|
1348
|
+
/** `null` means the item was rejected. */
|
|
1349
|
+
private static itemCoercer;
|
|
1633
1350
|
/**
|
|
1634
|
-
* Set or
|
|
1635
|
-
*
|
|
1636
|
-
*
|
|
1637
|
-
*
|
|
1638
|
-
* **Architecture Note:**
|
|
1639
|
-
* - Use with `DataTree[]` when building/modifying before computation
|
|
1640
|
-
* - Use with `InnerTree[]` when modifying compute API results
|
|
1641
|
-
* - `DataTree` is the high-level builder; `InnerTree` is the Rhino Compute format
|
|
1642
|
-
*
|
|
1643
|
-
* Copy-on-write: returns a new array; the caller's array is never mutated.
|
|
1644
|
-
*
|
|
1645
|
-
* @overload For TreeBuilder instances (high-level builder)
|
|
1646
|
-
* @param trees - Array of TreeBuilder instances to read from (not mutated)
|
|
1647
|
-
* @param paramName - The parameter name to set or replace
|
|
1648
|
-
* @param newValue - The new value (scalar, array, or TreeBuilder structure)
|
|
1649
|
-
* @returns A new TreeBuilder array with the updated parameter
|
|
1650
|
-
*
|
|
1651
|
-
* @overload For compiled InnerTree (low-level API format)
|
|
1652
|
-
* @param trees - The compiled InnerTree array (typically from `client.solve()`; not mutated)
|
|
1653
|
-
* @param paramName - The parameter name to set or replace
|
|
1654
|
-
* @param newValue - The new value (scalar, array, or TreeBuilder structure)
|
|
1655
|
-
* @returns A new InnerTree array with the updated parameter
|
|
1656
|
-
*
|
|
1657
|
-
* @example
|
|
1658
|
-
* ```ts
|
|
1659
|
-
* // With TreeBuilder instances (high-level)
|
|
1660
|
-
* let trees = [new TreeBuilder('X'), new TreeBuilder('Y')];
|
|
1661
|
-
* trees = TreeBuilder.replaceTreeValue(trees, 'X', 42);
|
|
1662
|
-
* const result = await client.solve(definitionUrl,
|
|
1663
|
-
* trees.map(t => t.toComputeFormat())
|
|
1664
|
-
* );
|
|
1665
|
-
* ```
|
|
1666
|
-
*
|
|
1667
|
-
* @example
|
|
1668
|
-
* ```ts
|
|
1669
|
-
* // With InnerTree format (low-level, from API)
|
|
1670
|
-
* let trees = await client.solve(definitionUrl, initialInputs);
|
|
1671
|
-
* trees = TreeBuilder.replaceTreeValue(trees, 'X', 42);
|
|
1672
|
-
* trees = TreeBuilder.replaceTreeValue(trees, 'Y', [1, 2, 3]);
|
|
1673
|
-
* ```
|
|
1351
|
+
* Set or add `paramName`'s tree to `newValue`: a scalar, an array (branch `{0}`), or a
|
|
1352
|
+
* branch-path map. Copy-on-write: returns a new array and leaves the caller's untouched, so
|
|
1353
|
+
* assign the result.
|
|
1674
1354
|
*/
|
|
1675
|
-
static replaceTreeValue(trees: TreeBuilder[], paramName: string, newValue: DataTreeValue): TreeBuilder[];
|
|
1676
1355
|
static replaceTreeValue(trees: DataTree[], paramName: string, newValue: DataTreeValue): DataTree[];
|
|
1356
|
+
private static buildFromValue;
|
|
1677
1357
|
/**
|
|
1678
|
-
*
|
|
1679
|
-
*
|
|
1358
|
+
* `paramName`'s whole tree from a solve result's `values`, keyed by branch path (`'{0;1}'`).
|
|
1359
|
+
* `null` when no tree has that param, an empty `Map` when it has no branches. An item without
|
|
1360
|
+
* `data` reads as `null` in place, so indices don't shift.
|
|
1680
1361
|
*/
|
|
1681
|
-
|
|
1362
|
+
static getTree(trees: DataTree[], paramName: string): Map<DataTreePath, DataTreeValue[]> | null;
|
|
1682
1363
|
/**
|
|
1683
|
-
*
|
|
1684
|
-
*
|
|
1685
|
-
* Automatically unwraps single values for convenience.
|
|
1686
|
-
* Works with both high-level `DataTree[]` instances and low-level `InnerTree[]` format.
|
|
1687
|
-
*
|
|
1688
|
-
* **Architecture Note:**
|
|
1689
|
-
* - Use with `DataTree[]` to read builder instances
|
|
1690
|
-
* - Use with `InnerTree[]` to read compute API responses
|
|
1691
|
-
* - Return behavior is consistent across both formats
|
|
1692
|
-
*
|
|
1693
|
-
* **Return Value Behavior:**
|
|
1694
|
-
* - Single value → unwrapped (returns `5` not `[5]`)
|
|
1695
|
-
* - Multiple values → array of values
|
|
1696
|
-
* - Not found → `null`
|
|
1697
|
-
*
|
|
1698
|
-
* @overload For TreeBuilder instances
|
|
1699
|
-
* @param trees - Array of TreeBuilder instances to read from
|
|
1700
|
-
* @param paramName - The parameter name to retrieve
|
|
1701
|
-
* @returns The unwrapped value, array of values, or null if parameter not found
|
|
1364
|
+
* `paramName`'s value when its tree has a single branch: one item unwrapped (`5`, not `[5]`),
|
|
1365
|
+
* several as an array. `null` for a missing param or an empty tree.
|
|
1702
1366
|
*
|
|
1703
|
-
* @
|
|
1704
|
-
* @
|
|
1705
|
-
* @param paramName - The parameter name to retrieve
|
|
1706
|
-
* @returns The unwrapped value, array of values, or null if parameter not found
|
|
1707
|
-
*
|
|
1708
|
-
* @example
|
|
1709
|
-
* ```ts
|
|
1710
|
-
* // With TreeBuilder instances
|
|
1711
|
-
* const trees = [new TreeBuilder('X'), new TreeBuilder('Y')];
|
|
1712
|
-
* trees[0].appendFlat(42);
|
|
1713
|
-
* const x = TreeBuilder.getTreeValue(trees, 'X'); // Returns 42
|
|
1714
|
-
* ```
|
|
1715
|
-
*
|
|
1716
|
-
* @example
|
|
1717
|
-
* ```ts
|
|
1718
|
-
* // With InnerTree from compute results
|
|
1719
|
-
* const result = await client.solve(definitionUrl, inputs);
|
|
1720
|
-
* const x = TreeBuilder.getTreeValue(result, 'X'); // Returns 42 (not [42])
|
|
1721
|
-
* const points = TreeBuilder.getTreeValue(result, 'Points'); // Returns [point1, point2, ...]
|
|
1722
|
-
* ```
|
|
1367
|
+
* @throws {ComputeError} `INVALID_INPUT` when the tree has more than one branch; read those
|
|
1368
|
+
* with {@link TreeBuilder.getTree}.
|
|
1723
1369
|
*/
|
|
1724
|
-
static getTreeValue(trees: TreeBuilder[], paramName: string): DataTreeValue | null;
|
|
1725
1370
|
static getTreeValue(trees: DataTree[], paramName: string): DataTreeValue | null;
|
|
1371
|
+
private static paramNameOf;
|
|
1726
1372
|
/**
|
|
1727
|
-
*
|
|
1728
|
-
* Returns null when the builder isn't found.
|
|
1729
|
-
*/
|
|
1730
|
-
private static readFromBuilders;
|
|
1731
|
-
/**
|
|
1732
|
-
* Read values from the first branch of the matching compiled InnerTree
|
|
1733
|
-
* (multi-branch responses are not flattened — current semantics, pinned by
|
|
1734
|
-
* the "reads from the first branch path only" test).
|
|
1735
|
-
*/
|
|
1736
|
-
private static readFromDataTrees;
|
|
1737
|
-
/**
|
|
1738
|
-
* Parse a TreeBuilder path string like "{0;1;2}" into [0, 1, 2].
|
|
1739
|
-
* Negative indices ("{-1;2}") and the root path "{}" are valid.
|
|
1373
|
+
* Parse a branch path like `"{0;1;2}"` into `[0, 1, 2]`.
|
|
1740
1374
|
*
|
|
1741
|
-
* @
|
|
1742
|
-
*
|
|
1743
|
-
* @throws {ComputeError} `INVALID_INPUT` when the path string is not a valid
|
|
1744
|
-
* Grasshopper branch path. Malformed keys must never silently collapse to a
|
|
1745
|
-
* default branch — two distinct unparseable keys would merge their items
|
|
1746
|
-
* into one branch.
|
|
1375
|
+
* @throws {ComputeError} `INVALID_INPUT` for a malformed path, rather than
|
|
1376
|
+
* collapsing it to a default branch where two bad keys would merge.
|
|
1747
1377
|
*/
|
|
1748
1378
|
static parsePathString(pathStr: string): number[];
|
|
1749
|
-
/**
|
|
1750
|
-
* Format a path array into TreeBuilder path string format.
|
|
1751
|
-
*
|
|
1752
|
-
* @param path - Path as number array
|
|
1753
|
-
* @returns Formatted path string like "{0;1;2}"
|
|
1754
|
-
*/
|
|
1379
|
+
/** `[0, 1, 2]` → `"{0;1;2}"`. */
|
|
1755
1380
|
static formatPathString(path: number[]): DataTreePath;
|
|
1756
|
-
/**
|
|
1757
|
-
private applyNumericConstraints;
|
|
1758
|
-
/**
|
|
1759
|
-
* Serialize a value for compute requests.
|
|
1760
|
-
* Preserves booleans and numbers as primitives for proper Grasshopper parameter handling.
|
|
1761
|
-
*/
|
|
1381
|
+
/** Booleans and numbers stay primitives: Grasshopper reads them typed. */
|
|
1762
1382
|
private static serializeValue;
|
|
1763
|
-
/**
|
|
1764
|
-
* Deserialize a value back to its original type.
|
|
1765
|
-
* Handles both string-encoded values and primitive values.
|
|
1766
|
-
*/
|
|
1767
1383
|
private static deserializeValue;
|
|
1768
|
-
/**
|
|
1769
|
-
* Check if a value is valid for inclusion in a DataTree.
|
|
1770
|
-
*/
|
|
1771
1384
|
private static hasValidValue;
|
|
1772
|
-
/**
|
|
1773
|
-
* Check if input is numeric type.
|
|
1774
|
-
*/
|
|
1775
|
-
private static isNumericInput;
|
|
1776
|
-
/**
|
|
1777
|
-
* Process array of values based on input type.
|
|
1778
|
-
*/
|
|
1779
|
-
private static processValues;
|
|
1780
|
-
/**
|
|
1781
|
-
* Clamp numeric value to constraints.
|
|
1782
|
-
*/
|
|
1783
1385
|
private static clampValue;
|
|
1784
1386
|
}
|
|
1785
1387
|
//#endregion
|
|
1786
|
-
export { type BooleanInputType, type CacheOptions,
|
|
1388
|
+
export { type BooleanInputType, type CacheOptions, type ColorInputType, ComputeServerStats, type CreateClientOptions, type DataItem, type DataTree, type DataTreeDefault, type DataTreePath, type DataTreeValue, type DefaultValue, type FileInputType, type GeometryInputType, type GetValuesOptions, type GetValuesResult, GrasshopperClient, type GrasshopperComputeConfig, type GrasshopperComputeResponse, type GrasshopperParsedIO, type GrasshopperParsedIORaw, GrasshopperResponseProcessor, type InnerTreeData, type InputParam, type InputParamSchema, type InputParseError, type NumericInputType, type OutputParamSchema, type ParsedContext, type RhinoDecodeError, type RhinoModelUnit, type SchedulerMode, type SchedulerSolveOptions, type SchemaEndpointResult, type SelvaEventTarget, type SelvaResponseBlock, type ServerStats, type ServerVersion, type SolveContext, type SolveDetail, type SolveExecutor, type SolveOptions, type SolveResult, type SolveSchedulerOptions, type TextInputType, type TreeValueEntry, type ValueListInputType };
|
|
1787
1389
|
//# sourceMappingURL=grasshopper.d.ts.map
|