@selvajs/solve 2.0.0-beta.9 → 2.0.0

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/dist/server.d.ts CHANGED
@@ -1,14 +1,25 @@
1
1
  import { t as SolveInput } from "./solve-input-CUjVGYPC.js";
2
- import { DataTree, GrasshopperClient, GrasshopperComputeResponse, SelvaEventTarget, SolveScheduler } from "@selvajs/compute/grasshopper";
3
- import { DefinitionRef, DefinitionRef as DefinitionRef$1, SolveDefinition, SolveDefinition as SolveDefinition$1, isDefinitionRef } from "@selvajs/compute/core";
4
- import { ILogger } from "@selvajs/platform";
2
+ import { UISchema } from "@selvajs/schemas";
3
+ import { GrasshopperClient, GrasshopperComputeResponse, SelvaEventTarget, SolveScheduler } from "@selvajs/compute/grasshopper";
4
+ import { DefinitionRef, DefinitionRef as DefinitionRef$1, ServerTiming, SolveDefinition } from "@selvajs/compute/core";
5
+ /** Rhino.Compute's own default `--timeout`, for a server that can't report its own. */
6
+ export declare const DEFAULT_SOLVE_DEADLINE_MS = 100000;
5
7
  /**
6
- * Opaque identity of a compute server — construct only via `serverIdentity()`.
7
- * Kept opaque so "a server is now a pool of URLs behind one id" stays additive.
8
+ * Ceiling on any solve deadline, whatever the server reports. Bounds how long a request, its
9
+ * live-event token and a delegated session stay open; past an hour a solve belongs in a job.
8
10
  */
9
- type ServerIdentity = string & {
10
- readonly __brand: 'ServerIdentity';
11
- };
11
+ export declare const MAX_SOLVE_DEADLINE_MS: number;
12
+ /** What Selva holds a solve to on one compute server. */
13
+ interface SolveLimits {
14
+ solveDeadlineMs: number;
15
+ /** `null` when the server didn't say: its own 413 is then the only check. */
16
+ maxRequestBytes: number | null;
17
+ /**
18
+ * Send a pointer to the server's cached definition instead of the `.gh`. Only on a server that
19
+ * answers a stale pointer with `definition_not_cached`: one that doesn't returns empty geometry.
20
+ */
21
+ reuseDefinitionCache: boolean;
22
+ }
12
23
  /** Minimal resolved-server shape the cache needs (a subset of the app's `ComputeServerConfig`). */
13
24
  interface ResolvedServer {
14
25
  id: string;
@@ -16,10 +27,11 @@ interface ResolvedServer {
16
27
  /** Sent as the `RhinoComputeKey` header. */
17
28
  apiKey?: string;
18
29
  }
19
- export declare function serverIdentity(server: Pick<ResolvedServer, 'id'>): ServerIdentity;
20
30
  interface CachedClient {
21
31
  client: GrasshopperClient;
22
32
  scheduler: SolveScheduler;
33
+ /** Read from the server when the client was built; a changed server rebuilds the client. */
34
+ limits: SolveLimits;
23
35
  }
24
36
  /**
25
37
  * Debug verbosity: `false` is silent, `true` gives concise cache/timing logs
@@ -27,68 +39,6 @@ interface CachedClient {
27
39
  * dumps (incl. geometry) — a superset of `true`, not an independent setting.
28
40
  */
29
41
  type ClientCacheDebug = boolean | 'verbose';
30
- /** Config injected by the consuming app, so this module stays env-agnostic and testable. */
31
- interface ClientCacheConfig {
32
- /** Per-solve timeout forwarded to the scheduler (`ComputeLimits.solveDeadlineMs`). */
33
- solveDeadlineMs: number;
34
- cachesolve: boolean;
35
- /** Reference large definitions by server cache key instead of re-uploading. */
36
- reuseServerDefinitionCache: boolean;
37
- /**
38
- * Max solves that may wait in the FIFO queue, excluding in-flight solves
39
- * (capped at `maxConcurrent`, itself driven by the server's probed child
40
- * count). `0` = unbounded (`ComputeLimits.computeMaxQueueDepth`); a full
41
- * queue rejects new solves with `QUEUE_FULL`.
42
- */
43
- maxQueueDepth: number;
44
- /**
45
- * Max ms a solve may sit queued before executing; `0` = no deadline
46
- * (`ComputeLimits.computeQueueWaitMs`). Too long a wait rejects with
47
- * `QUEUE_TIMEOUT`.
48
- */
49
- queueWaitMs: number;
50
- /**
51
- * Byte budget for this client's in-process solve cache. Applies per warm
52
- * client — worst-case heap is this × `maxWarmComputeServers`. `0` disables
53
- * the cache (`ComputeLimits.computeSolveCacheBytes`, env `COMPUTE_SOLVE_CACHE_MB`).
54
- */
55
- responseCacheMaxBytes: number;
56
- /**
57
- * Largest compute response body read; past it the download is cancelled (`too_large`).
58
- * Default: no limit.
59
- */
60
- maxResponseBytes?: number;
61
- debug: ClientCacheDebug;
62
- /** Max distinct warm compute servers before the LRU evicts the oldest. Default 16. */
63
- maxWarmComputeServers?: number;
64
- /** Sink for the debug lines. `onDebugLog` only fires when `debug` is not `false`. */
65
- onDebugLog?: (message: string) => void;
66
- }
67
- interface ClientCache {
68
- /**
69
- * Get (or create) the warm client + scheduler for a resolved compute server,
70
- * keyed by its `id`. `definitionGuid`, when present, is stamped as the
71
- * `X-Selva-Definition` header on this client's outbound solve/IO requests —
72
- * inert routing/telemetry metadata until a pool router exists.
73
- */
74
- getClient(server: ResolvedServer, opts?: {
75
- definitionGuid?: string;
76
- }): Promise<CachedClient>;
77
- /** Dispose and drop the warm client for `id`, so the next request rebuilds against fresh connection details. */
78
- evict(id: string | ServerIdentity): void;
79
- /** Solve-cache counters summed across every warm client. Counters die with the client that owns them, so totals can fall over time. */
80
- solveCacheStats(): SolveCacheStats;
81
- /**
82
- * Drop every retained solve result, keeping the warm clients (and their
83
- * connections and server-side definition pointers) intact. Nothing expires
84
- * these on its own — the byte budget is the only other pressure — so this is
85
- * the operator's release valve when a definition's inputs no longer describe
86
- * its output, e.g. it reads an external source that has since changed.
87
- */
88
- clearSolveCaches(): void;
89
- /** Dispose every warm client. Test seam / shutdown hook. */
90
- disposeAll(): void;
91
- }
92
42
  interface SolveCacheStats {
93
43
  warmClients: number;
94
44
  entries: number;
@@ -98,7 +48,6 @@ interface SolveCacheStats {
98
48
  /** Entries dropped under size/byte pressure (not replacement or manual clears). */
99
49
  evictions: number;
100
50
  }
101
- export declare function createClientCache(config: ClientCacheConfig): ClientCache;
102
51
  /**
103
52
  * In-process cache of `.gh` definition bytes, keyed by immutable **version id**.
104
53
  *
@@ -131,7 +80,7 @@ interface ByteRefOutcome {
131
80
  /** A definition reference shaped for `@selvajs/compute`'s `DefinitionRef`. */
132
81
  interface ByteCacheRef {
133
82
  key: string;
134
- load: () => Promise<Uint8Array>;
83
+ load: (signal?: AbortSignal) => Promise<Uint8Array>;
135
84
  outcome: ByteRefOutcome;
136
85
  }
137
86
  interface ByteCacheStats {
@@ -141,65 +90,23 @@ interface ByteCacheStats {
141
90
  entries: number;
142
91
  bytes: number;
143
92
  }
144
- interface DefinitionByteCache {
145
- getOrLoad(versionId: string, load: () => Promise<Uint8Array>): ByteCacheRef;
146
- stats(): ByteCacheStats;
147
- clear(): void;
93
+ /** A pre-solve prep sub-phase: `[label, ms]`, surfaced as a `p_*` Server-Timing entry. */
94
+ type PrepMark = [string, number];
95
+ interface CacheVerdict {
96
+ fromCache: boolean;
97
+ definitionReuploaded?: boolean;
148
98
  }
149
99
  /**
150
- * @param maxBytes total retained-byte budget; `0` (or negative) disables caching
151
- * entirely — every `load()` calls the loader and nothing is retained.
100
+ * skipped = scheduler never materialized bytes (pointer-known solve, the whole point of this
101
+ * path); hit = warm byte cache; miss = fell through to storage.
152
102
  */
153
- export declare function createDefinitionByteCache(maxBytes: number): DefinitionByteCache;
103
+ type DefBytesVerdict = 'skipped' | 'hit' | 'miss';
154
104
  /** Compute-response contract version. Bump (and document the change) whenever the envelope's shape changes in a way a consumer could observe. */
155
105
  export declare const COMPUTE_CONTRACT_VERSION: 1;
156
106
  export declare const COMPUTE_VERSION_HEADER = "X-Selva-Compute-Version";
157
- type PipelineInput = SolveInput;
158
- interface SolvePipelineArgs {
159
- /**
160
- * Raw `.gh` bytes, or a byte-cache `DefinitionRef` whose bytes the scheduler
161
- * materializes only when an upload is unavoidable — a pointer-known solve
162
- * moves zero bytes.
163
- */
164
- definitionSource: SolveDefinition$1;
165
- /** Mutable load outcome for a `DefinitionRef` source, so the `def_bytes` Server-Timing verdict can be emitted. Omit for raw-bytes solves. */
166
- byteRefOutcome?: ByteRefOutcome;
167
- /** Persisted input params; only those with a `paramType` are sent to the solve. */
168
- inputs: PipelineInput[];
169
- /**
170
- * A tree the caller already built with {@link buildSolveInputTree}; skips the
171
- * pipeline's own build and solves this object directly.
172
- *
173
- * A caller coalescing concurrent solves needs this: a single-flight key
174
- * derived from raw `{inputs, values}` would split two requests that transform
175
- * to the same tree, which is the identity the scheduler actually caches on.
176
- */
177
- inputTree?: DataTree[];
178
- /** User-chosen values keyed by input id; missing keys fall back to the schema default. */
179
- values: Record<string, unknown>;
180
- client: CachedClient;
181
- responseMaxBytes: number;
182
- /** Only phrases the timeout message — the scheduler enforces the deadline itself. */
183
- solveDeadlineMs: number;
184
- /** Client's `Accept-Encoding`; gzip is applied only when it advertises `gzip`. */
185
- acceptEncoding: string;
186
- /** Per-solve live-event callback the compute server hands to the definition; absent when the caller opened no stream. */
187
- selvaEvents?: SelvaEventTarget;
188
- /**
189
- * Forwarded to the scheduler so a client disconnect cancels the upstream
190
- * compute call. Its `aborted` flag also distinguishes a client disconnect
191
- * from the scheduler's own deadline firing.
192
- */
193
- signal: AbortSignal;
194
- /** Wall-clock origin (`performance.now()` at the top of the request) so `load`/`total` phase timings line up with the caller's pre-solve prep. */
195
- loadStartMs: number;
196
- /** Pre-solve "load" phase duration the caller already measured (auth + DB + fetch). */
197
- defLoadMs: number;
198
- /** Pre-solve prep sub-phase marks (`[label, ms]`), surfaced verbatim as `p_*` Server-Timing entries. */
199
- prepMarks?: [string, number][];
200
- }
201
- /** Phase timings the pipeline measured; the caller uses them for debug logging. */
107
+ /** What the `Server-Timing` header carries for one caller, as data: read this, don't parse that. */
202
108
  interface SolvePhaseMetrics {
109
+ defLoadMs: number;
203
110
  treeBuildMs: number;
204
111
  solveMs: number;
205
112
  serializeMs: number;
@@ -208,6 +115,11 @@ interface SolvePhaseMetrics {
208
115
  serializedBytes: number;
209
116
  /** Null when compression was skipped. */
210
117
  compressedBytes: number | null;
118
+ /** The compute server's own timing; null when it reports none. */
119
+ rhino: ServerTiming | null;
120
+ settle: CacheVerdict;
121
+ /** Absent for raw-bytes solves. */
122
+ defBytes?: DefBytesVerdict;
211
123
  }
212
124
  /** A ready-to-send response: body + headers + the solve result + phase metrics. */
213
125
  interface SolveEnvelope {
@@ -218,20 +130,21 @@ interface SolveEnvelope {
218
130
  result: GrasshopperComputeResponse;
219
131
  metrics: SolvePhaseMetrics;
220
132
  }
133
+ /** Whether an `Accept-Encoding` header takes gzip. `gzip;q=0` is a client refusing it. */
134
+ export declare function acceptsGzip(acceptEncoding: string): boolean;
221
135
  /**
222
- * `ok` carries the envelope; every other variant names an expected failure the
223
- * calling route maps to a status code (timeout→504, client_abort→499,
224
- * too_large→413, shed→503+Retry-After, compute_error→generic 500/503).
225
- * `durationMs` on error variants is the solve wall time up to the failure, for
226
- * the metric record.
136
+ * `ok` carries the envelope; every other variant names an expected failure:
137
+ * `SolveEngine.toWebResponse` maps each to a status. `durationMs` on error variants is the solve
138
+ * wall time up to the failure, for the metric record.
227
139
  */
228
- type SolveOutcome = {
140
+ type SolveEngineOutcome = {
229
141
  kind: 'ok';
230
142
  envelope: SolveEnvelope;
231
143
  solveMs: number;
232
144
  errorCount: number;
233
145
  warningCount: number;
234
- } | {
146
+ } | SolveFailure;
147
+ type SolveFailure = {
235
148
  kind: 'timeout';
236
149
  durationMs: number;
237
150
  message: string;
@@ -241,11 +154,21 @@ type SolveOutcome = {
241
154
  } | {
242
155
  kind: 'too_large';
243
156
  } |
244
- /** Scheduler backpressure rejected the solve before it ran: queue was full (`queue_full`) or the wait exceeded the deadline (`queue_timeout`). Retryable — `retryAfterSeconds` is a backoff hint. */
157
+ /** The compute server refused the request body (its `RHINO_COMPUTE_MAX_REQUEST_SIZE`). */
158
+ {
159
+ kind: 'request_too_large';
160
+ durationMs: number;
161
+ message: string;
162
+ } |
163
+ /**
164
+ * Retryable: no result, through no fault of the request, and `retryAfterSeconds` is a backoff
165
+ * hint. Scheduler backpressure rejected the solve before it ran (`queue_full`,
166
+ * `queue_timeout`), or its client was shut down under it (`interrupted`).
167
+ */
245
168
  {
246
169
  kind: 'shed';
247
170
  durationMs: number;
248
- reason: 'queue_full' | 'queue_timeout';
171
+ reason: 'queue_full' | 'queue_timeout' | 'interrupted';
249
172
  retryAfterSeconds: number;
250
173
  message: string;
251
174
  } | {
@@ -253,71 +176,12 @@ type SolveOutcome = {
253
176
  durationMs: number;
254
177
  error: unknown;
255
178
  };
256
- export declare function runSolvePipeline(args: SolvePipelineArgs): Promise<SolveOutcome>;
257
- /**
258
- * Re-key a coalesced envelope to a single waiter's `Accept-Encoding`.
259
- *
260
- * The single-flight coalescer runs ONE pipeline execution for N identical
261
- * concurrent solves and hands every waiter the same {@link SolveEnvelope},
262
- * baked from the FIRST caller's `Accept-Encoding`. A later waiter with a
263
- * different `Accept-Encoding` would otherwise get a body labelled with the
264
- * wrong encoding — `Vary` can't help here, since it's one shared object, not a
265
- * cache lookup. Encoding is deliberately left out of the coalesce key so mixed
266
- * clients still coalesce; this adapts the shared result to each waiter instead.
267
- *
268
- * Only the correctness-critical direction is adapted: a gzip envelope served to
269
- * a non-gzip waiter is gunzipped back to JSON. The reverse (plain JSON to a
270
- * gzip-capable waiter) is left uncompressed — correct, just not maximally small.
271
- */
272
- export declare function adaptEnvelopeToEncoding(envelope: SolveEnvelope, acceptEncoding: string): {
273
- body: string | Uint8Array;
274
- headers: Record<string, string>;
275
- };
276
- /** The input tree a solve sends: each input's value, or its schema default when it has none. */
277
- export declare function buildSolveInputTree(inputs: SolveInput[], values: Record<string, unknown>): DataTree[];
278
- /**
279
- * In-process single-flight — dogpile protection for every solve.
280
- *
281
- * Always on, not gated behind a result cache being configured: the dogpile is worst
282
- * when nothing else is caching, since N concurrent identical solves each pay a full
283
- * Rhino round trip (the scheduler doesn't coalesce in-flight requests itself, and
284
- * Rhino's `cachesolve` still costs a round trip per repeat). An earlier version
285
- * gated this on cache config and so disabled it in exactly the deployments most
286
- * exposed to a cold-key stampede — hot public definition plus a deploy.
287
- *
288
- * Per app instance, above `ISolveResultCache`. No cross-instance lease (Redis
289
- * `SET NX`) yet.
290
- *
291
- * The shared promise resolves to one value for every waiter, so `work` must return
292
- * something safe to share by reference — the solve pipeline's envelope qualifies
293
- * because the app serializes it per response.
294
- */
295
- interface SolveCacheSingleFlight {
296
- /**
297
- * Coalesces concurrent calls under the same key: the first caller runs `work`,
298
- * later callers for that key await the same promise, and the key frees as soon
299
- * as it settles.
300
- *
301
- * `onWaiterJoined` fires only on the owner's call, only while `work` is still
302
- * running, each time another caller joins. Ownership changes what the owner's
303
- * abort signal should mean: a solo run can cancel on its own client's
304
- * disconnect, but a shared run can't without 499-ing every waiter.
305
- */
306
- run<T>(key: string, work: () => Promise<T>, onWaiterJoined?: () => void): Promise<T>;
307
- inFlight(): number;
308
- }
309
- interface SolveCacheSingleFlightOptions {
310
- onJoin?: (key: string) => void;
311
- }
312
- export declare function createSolveCacheSingleFlight(options?: SolveCacheSingleFlightOptions): SolveCacheSingleFlight;
313
179
  /**
314
180
  * Subset of `ComputeLimits` (`@selvajs/server/compute`) the engine needs.
315
181
  * Pass the resolved object through as-is — extra fields are ignored.
316
182
  */
317
183
  interface SolveEngineLimits {
318
- solveDeadlineMs: number;
319
184
  computeResponseMaxBytes: number;
320
- computeReuseDefinitionCache: boolean;
321
185
  computeServerCachesolve: boolean;
322
186
  computeMaxQueueDepth: number;
323
187
  computeQueueWaitMs: number;
@@ -326,26 +190,20 @@ interface SolveEngineLimits {
326
190
  }
327
191
  interface SolveEngineOptions {
328
192
  limits: SolveEngineLimits;
329
- logger?: ILogger;
330
- /** Max distinct warm compute servers before the LRU evicts the oldest. Default 16. */
193
+ /** Max distinct warm compute servers before the LRU evicts the oldest. */
331
194
  maxWarmComputeServers?: number;
332
195
  /** Concise cache/timing logs when truthy; `'verbose'` also dumps full lib-level requests/responses. Default off. */
333
196
  debug?: ClientCacheDebug;
197
+ /** Sink for the debug lines. Without it they go nowhere. */
334
198
  onDebugLog?: (message: string) => void;
335
199
  /** Fired when a caller joins an already-in-flight solve instead of running its own. */
336
200
  onSolveCoalesced?: (key: string) => void;
337
201
  }
338
202
  /**
339
- * Accepts every form `runSolvePipeline` does, plus `{versionId, load}` sugar
340
- * that builds (and caches) a `ByteCacheRef` internally. A `ByteCacheRef`
341
- * obtained ahead of time from `engine.definitionRef()` (e.g. to read bytes for
342
- * schema extraction before solving) is passed through as-is — detected by its
343
- * `outcome` field, which a plain `DefinitionRef` never has.
203
+ * A `ByteCacheRef` obtained ahead of time from `engine.definitionRef()` (e.g. to
204
+ * read bytes for schema extraction before solving) is passed through as-is.
344
205
  */
345
- type SolveEngineDefinitionSource = Uint8Array | string | DefinitionRef$1 | ByteCacheRef | {
346
- versionId: string;
347
- load: () => Promise<Uint8Array>;
348
- };
206
+ type SolveEngineDefinitionSource = Uint8Array | string | DefinitionRef$1 | ByteCacheRef;
349
207
  interface SolveEngineSolveArgs {
350
208
  server: ResolvedServer;
351
209
  definitionSource: SolveEngineDefinitionSource;
@@ -356,27 +214,26 @@ interface SolveEngineSolveArgs {
356
214
  * Ignored for the other source forms.
357
215
  */
358
216
  definitionKey?: string;
359
- inputs: PipelineInput[];
217
+ /**
218
+ * The definition's inputs, from the schema you stored, never from the request: `id`, `nickname`,
219
+ * `paramType` and the bounds decide what reaches the definition, so a body that supplies them
220
+ * can drop a limit or fill a slot your host reserved.
221
+ */
222
+ inputs: SolveInput[];
360
223
  values: Record<string, unknown>;
361
224
  signal: AbortSignal;
362
225
  acceptEncoding?: string;
363
- /** Stamped as `X-Selva-Definition` on this solve's client. */
226
+ /**
227
+ * Stamped as `X-Selva-Definition` when this solve builds the server's warm client. The header
228
+ * is fixed per client, so later solves on that server carry the first definition's guid.
229
+ */
364
230
  definitionGuid?: string;
365
231
  loadStartMs?: number;
366
232
  defLoadMs?: number;
367
- prepMarks?: [string, number][];
368
- /**
369
- * Per-solve live-event callback. A coalesced waiter shares the first caller's
370
- * compute call, so only that caller's target reaches the definition; the
371
- * others still get the server-emitted start/end events on their own stream.
372
- */
233
+ prepMarks?: PrepMark[];
234
+ /** Per-solve live-event callback. A solve carrying one runs its own compute call, never a shared one. */
373
235
  selvaEvents?: SelvaEventTarget;
374
236
  }
375
- interface FrameworkAgnosticResponse {
376
- status: number;
377
- headers: Record<string, string>;
378
- body: string | Uint8Array;
379
- }
380
237
  interface SolveEngineStats {
381
238
  client: SolveCacheStats;
382
239
  definitionBytes: ByteCacheStats;
@@ -389,11 +246,17 @@ export declare class SolveEngine {
389
246
  private readonly clientCache;
390
247
  private readonly byteCache;
391
248
  private readonly singleFlight;
249
+ private readonly clientGenerations;
250
+ private lastClientGeneration;
392
251
  constructor(options: SolveEngineOptions);
393
252
  getClient(server: ResolvedServer, opts?: {
394
253
  definitionGuid?: string;
395
254
  }): Promise<CachedClient>;
396
- definitionRef(versionId: string, load: () => Promise<Uint8Array>): ByteCacheRef;
255
+ definitionRef(versionId: string, load: (signal: AbortSignal) => Promise<Uint8Array>): ByteCacheRef;
256
+ /**
257
+ * Drops the warm client for `id`; call it when the server's URL or key changes. Solves already
258
+ * running finish on the old connection details first, so a revoked key stays in use until then.
259
+ */
397
260
  evictServer(id: string): void;
398
261
  clearSolveCaches(): void;
399
262
  /**
@@ -402,15 +265,23 @@ export declare class SolveEngine {
402
265
  */
403
266
  clearDefinitionCache(): void;
404
267
  stats(): SolveEngineStats;
405
- solve(args: SolveEngineSolveArgs): Promise<SolveOutcome>;
406
- toResponse(outcome: SolveOutcome, opts?: {
407
- onError?: (status: number, body: {
408
- message: string;
409
- retryAfter?: number;
410
- }) => never;
411
- }): FrameworkAgnosticResponse;
412
- toWebResponse(outcome: SolveOutcome): Response;
268
+ solve(args: SolveEngineSolveArgs): Promise<SolveEngineOutcome>;
269
+ /**
270
+ * The response for an outcome; the mapping from outcome to status lives here. Throws
271
+ * `compute_error`'s error: what it means for the caller is the host's to decide.
272
+ */
273
+ toWebResponse(outcome: SolveEngineOutcome): Response;
274
+ /**
275
+ * Part of the coalesce key: after an eviction the id stays and the client changes, and a new
276
+ * caller joining a draining flight would get an answer from the old URL or key.
277
+ */
278
+ private clientGeneration;
413
279
  private resolveDefinitionSource;
414
280
  }
415
- export { type ByteCacheRef, type ByteCacheStats, type ByteRefOutcome, type CachedClient, type ClientCache, type ClientCacheConfig, type DefinitionByteCache, type DefinitionRef, type FrameworkAgnosticResponse, type PipelineInput, type ResolvedServer, type ServerIdentity, type SolveCacheSingleFlight, type SolveCacheSingleFlightOptions, type SolveCacheStats, type SolveDefinition, type SolveEngineDefinitionSource, type SolveEngineLimits, type SolveEngineOptions, type SolveEngineSolveArgs, type SolveEngineStats, type SolveEnvelope, type SolveInput, type SolveOutcome, type SolvePhaseMetrics, type SolvePipelineArgs, isDefinitionRef };
281
+ /**
282
+ * What `SolveEngine.solve` takes as `inputs`, from a schema the host stored. The bounds live on
283
+ * the number widgets in the layout, not on `schema.inputs`, so without them nothing clamps.
284
+ */
285
+ export declare function solveInputsFromSchema(schema: UISchema): SolveInput[];
286
+ export type { ByteCacheRef, ByteCacheStats, ByteRefOutcome, CachedClient, DefinitionRef, ResolvedServer, SolveCacheStats, SolveDefinition, SolveEngineDefinitionSource, SolveEngineLimits, SolveEngineOptions, SolveEngineOutcome, SolveEngineSolveArgs, SolveEngineStats, SolveEnvelope, SolveInput, SolveLimits, SolvePhaseMetrics };
416
287
  //# sourceMappingURL=server.d.ts.map