@openmbee/opensysml 0.9.2 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +355 -33
  2. package/dist/browser/index.d.ts +9 -0
  3. package/dist/browser/index.js +16 -0
  4. package/dist/browser/wasm-worker.d.ts +1 -0
  5. package/dist/browser/wasm-worker.js +2 -0
  6. package/dist/browser/wasm.d.ts +17 -0
  7. package/dist/browser/wasm.js +97 -0
  8. package/dist/core/arguments.d.ts +4 -0
  9. package/dist/core/arguments.js +19 -0
  10. package/dist/core/capabilities.d.ts +90 -9
  11. package/dist/core/capabilities.js +111 -10
  12. package/dist/core/connection.d.ts +203 -2
  13. package/dist/core/connection.js +810 -17
  14. package/dist/core/conversion.d.ts +153 -0
  15. package/dist/core/conversion.js +191 -0
  16. package/dist/core/document.d.ts +188 -0
  17. package/dist/core/document.js +457 -0
  18. package/dist/core/edit.d.ts +446 -0
  19. package/dist/core/edit.js +1994 -0
  20. package/dist/core/engines.d.ts +64 -0
  21. package/dist/core/engines.js +74 -0
  22. package/dist/core/errors.d.ts +164 -2
  23. package/dist/core/errors.js +209 -3
  24. package/dist/core/exploration.d.ts +71 -0
  25. package/dist/core/exploration.js +116 -0
  26. package/dist/core/graphs.d.ts +15 -0
  27. package/dist/core/graphs.js +3 -0
  28. package/dist/core/index.d.ts +30 -9
  29. package/dist/core/index.js +14 -5
  30. package/dist/core/model.d.ts +168 -8
  31. package/dist/core/model.js +258 -31
  32. package/dist/core/package.d.ts +2 -0
  33. package/dist/core/package.js +2 -0
  34. package/dist/core/query.d.ts +50 -0
  35. package/dist/core/query.js +197 -0
  36. package/dist/core/render-view.d.ts +97 -0
  37. package/dist/core/render-view.js +120 -0
  38. package/dist/core/sources.d.ts +34 -0
  39. package/dist/core/sources.js +134 -0
  40. package/dist/core/status.d.ts +9 -2
  41. package/dist/core/status.js +24 -8
  42. package/dist/core/typed.d.ts +71 -0
  43. package/dist/core/typed.js +245 -0
  44. package/dist/core/values.d.ts +127 -8
  45. package/dist/core/values.js +538 -30
  46. package/dist/core/verdict.d.ts +271 -0
  47. package/dist/core/verdict.js +567 -0
  48. package/dist/core/wasm.d.ts +114 -0
  49. package/dist/core/wasm.js +514 -0
  50. package/dist/generated/sysml_pb.d.ts +1062 -15
  51. package/dist/generated/sysml_pb.js +200 -100
  52. package/dist/node/generate-cli.d.ts +2 -0
  53. package/dist/node/generate-cli.js +10 -0
  54. package/dist/node/generate.d.ts +99 -0
  55. package/dist/node/generate.js +757 -0
  56. package/dist/node/index.d.ts +29 -2
  57. package/dist/node/index.js +211 -10
  58. package/dist/node/service.d.ts +5 -3
  59. package/dist/node/service.js +32 -26
  60. package/dist/node/wasm-source.d.ts +18 -0
  61. package/dist/node/wasm-source.js +103 -0
  62. package/dist/node/wasm-worker.d.ts +1 -0
  63. package/dist/node/wasm-worker.js +10 -0
  64. package/dist/node/wasm.d.ts +17 -0
  65. package/dist/node/wasm.js +63 -0
  66. package/package.json +19 -7
  67. package/release-digests.json +117 -0
@@ -0,0 +1,567 @@
1
+ // Verdicts of the verification the service performs, and the results that carry
2
+ // them: validations, calc results, analysis results and sweep tables.
3
+ import { FailureReason } from "../generated/sysml_pb.js";
4
+ import { AnalysisRunError, ExecutionError, UnsupportedValueError, WrongKindError, } from "./errors.js";
5
+ import { emptyStanding, standingOf } from "./engines.js";
6
+ import { decodeValue, decodeVerdict, formatValue, } from "./values.js";
7
+ /** Verdict kinds, as the service reports them. */
8
+ export const KIND_CONSTRAINT = "constraint";
9
+ export const KIND_REQUIREMENT = "requirement";
10
+ export const KIND_SATISFY = "satisfy";
11
+ export const KIND_OBJECTIVE = "objective";
12
+ export const KIND_ASSERTION = "assertion";
13
+ export const KIND_OBJECT = "object";
14
+ /** VerdictKind values a verification case's body produces. */
15
+ export const VERDICT_PASS = "pass";
16
+ export const VERDICT_FAIL = "fail";
17
+ export const VERDICT_INCONCLUSIVE = "inconclusive";
18
+ export const VERDICT_ERROR = "error";
19
+ /** The questions a verification answers. */
20
+ export const QUESTION_EVALUATE = "evaluate";
21
+ export const QUESTION_HOLDS = "holds";
22
+ export const QUESTION_SATISFIABLE = "satisfiable";
23
+ /** The statuses a verdict reports, as the service spells them. */
24
+ export const STATUS_HOLDS = "holds";
25
+ export const STATUS_VIOLATED = "violated";
26
+ export const STATUS_UNDECIDED = "undecided";
27
+ export const STATUS_SATISFIABLE = "satisfiable";
28
+ export const STATUS_UNSATISFIABLE = "unsatisfiable";
29
+ /** The mark a verification verdict's line opens with. */
30
+ function verificationMark(kind) {
31
+ if (kind === VERDICT_PASS) {
32
+ return "✓";
33
+ }
34
+ return kind === VERDICT_FAIL ? "✗" : "?";
35
+ }
36
+ /** Whether a verdict's condition holds: the arm it decoded to. */
37
+ export function verdictHolds(verdict) {
38
+ return verdict.kind === "holds";
39
+ }
40
+ /** Whether the verdict is an answer about the model at all: not undecided. */
41
+ export function verdictEvaluated(verdict) {
42
+ return verdict.kind !== "undecided";
43
+ }
44
+ function named(verdict) {
45
+ const { subject } = verdict;
46
+ const element = subject.element !== "" ? subject.element : subject.elementId;
47
+ let out = element.split(" ").includes(subject.kind) ? element : `${subject.kind} ${element}`;
48
+ if (subject.instancePath !== undefined) {
49
+ out += ` at ${subject.instancePath}`;
50
+ }
51
+ return out;
52
+ }
53
+ /** Raise an {@link ExecutionError} when the verdict is undecided; else return it. */
54
+ export function raiseVerdictError(verdict) {
55
+ if (verdict.kind === "undecided") {
56
+ throw new ExecutionError(`${named(verdict)}: ${verdict.error}`);
57
+ }
58
+ return verdict;
59
+ }
60
+ /** One line saying what the verdict is and why, then its standing when reported. */
61
+ export function explainVerdict(verdict) {
62
+ const { subject } = verdict;
63
+ let subject_ = "";
64
+ if (subject.instanceId !== undefined) {
65
+ subject_ = ` (on ${subject.instanceTypeId ?? "instance"} ID: ${subject.instanceId.toString()})`;
66
+ }
67
+ let line;
68
+ if (verdict.kind === "undecided") {
69
+ line = `? ${named(verdict)}${subject_}: ${verdict.error}`;
70
+ }
71
+ else if (verdict.kind === "holds") {
72
+ line = `✓ ${named(verdict)} holds${subject_}`;
73
+ }
74
+ else {
75
+ const detail = verdict.condition !== ""
76
+ ? `: condition evaluated to false: ${verdict.condition}`
77
+ : ": condition evaluated to false";
78
+ line = `✗ ${named(verdict)} fails${subject_}${detail}`;
79
+ }
80
+ const standing = explainVerdictStanding(verdict.standing);
81
+ return standing === "" ? line : `${line} — ${standing}`;
82
+ }
83
+ function explainVerdictStanding(standing) {
84
+ if (standing.strength === "") {
85
+ return "";
86
+ }
87
+ let line = standing.strength;
88
+ if (standing.engine !== "") {
89
+ line += ` by ${standing.engine}`;
90
+ }
91
+ const reached = standing.bounds
92
+ .filter((bound) => bound.reached)
93
+ .map((b) => `${b.name} ${b.limit.toString()} reached`);
94
+ if (reached.length > 0) {
95
+ line += ` (${reached.join(", ")})`;
96
+ }
97
+ return line;
98
+ }
99
+ /** One line saying what a verification case's body answered and why. */
100
+ export function explainVerificationVerdict(verdict) {
101
+ let line = `${verificationMark(verdict.kind)} verification ${verdict.caseId} verdict: ${verdict.kind}`;
102
+ if (verdict.subcase) {
103
+ line += " (subcase)";
104
+ }
105
+ if (verdict.detail !== "") {
106
+ line += ` — ${verdict.detail}`;
107
+ }
108
+ return line;
109
+ }
110
+ /** Whether a verification-case verdict is a pass. */
111
+ export function verificationPassed(verdict) {
112
+ return verdict.kind === VERDICT_PASS;
113
+ }
114
+ /** Read a wire `VerificationVerdict`. */
115
+ export function decodeVerificationVerdict(pb) {
116
+ return {
117
+ caseId: pb.caseId,
118
+ kind: pb.kind,
119
+ detail: pb.detail,
120
+ subcase: pb.subcase,
121
+ requirementId: pb.requirementId,
122
+ };
123
+ }
124
+ /** The arm of a `Verdict`, for callers that switch on it directly. */
125
+ export function armOf(verdict) {
126
+ return verdict.verdict;
127
+ }
128
+ /** Whether the verdict's condition holds. */
129
+ export function holds(verdict) {
130
+ return verdict.verdict.kind === "holds";
131
+ }
132
+ /** Raise when the verdict reports the named element is of another kind. */
133
+ export function raiseWrongKind(pbVerdict, diagnostics) {
134
+ if (pbVerdict?.failureReason === FailureReason.WRONG_KIND) {
135
+ throw new WrongKindError(pbVerdict.error, "wrong_kind", diagnostics);
136
+ }
137
+ }
138
+ /** Raise the error a failure the service classified: wrong kind, else a run failure. */
139
+ export function raiseFailure(message, failureReason, diagnostics) {
140
+ if (failureReason === FailureReason.WRONG_KIND) {
141
+ throw new WrongKindError(message, "wrong_kind", diagnostics);
142
+ }
143
+ throw new ExecutionError(message, "unspecified", diagnostics);
144
+ }
145
+ /** Read the error-or-result of an outputs map: undecodable values stay errors in place. */
146
+ export function valuesMap(entries) {
147
+ const out = new Map();
148
+ for (const [name, pb] of entries) {
149
+ try {
150
+ out.set(name, decodeValue(pb));
151
+ }
152
+ catch (error) {
153
+ out.set(name, asUnsupported(error));
154
+ }
155
+ }
156
+ return out;
157
+ }
158
+ /** The verifications the requirement of `pbVerdict` was reported for. */
159
+ export function verificationsFor(verifications, pbVerdict) {
160
+ if (pbVerdict.requirementId === "") {
161
+ return [];
162
+ }
163
+ return verifications.filter((v) => v.requirementId === pbVerdict.requirementId);
164
+ }
165
+ /** Wrap a wire verdict with the instances and diagnostics its response carried,
166
+ * attaching the verifications of its own requirement — every one the response
167
+ * carried when `attachAll` is set, as a single-verdict response asks for. */
168
+ export function verdictOf(pbVerdict, instances, diagnostics, verifications, attachAll = false) {
169
+ return {
170
+ verdict: decodeVerdict(pbVerdict, attachAll ? verifications : verificationsFor(verifications, pbVerdict)),
171
+ instances,
172
+ diagnostics,
173
+ };
174
+ }
175
+ /** The outputs an invocation computed, or the features a calc usage wrote. */
176
+ export class CalcResult {
177
+ /** The value an invocation returned; undefined when `outputs` carries the answer. */
178
+ value;
179
+ /** Output features a calc usage computed. */
180
+ outputs;
181
+ diagnostics;
182
+ standing;
183
+ constructor(init) {
184
+ this.value = init.value;
185
+ this.outputs = init.outputs;
186
+ this.diagnostics = init.diagnostics ?? [];
187
+ this.standing = init.standing ?? emptyStanding();
188
+ }
189
+ get engine() {
190
+ return this.standing.engine;
191
+ }
192
+ /** Strength of the evidence the answer rests on; empty when unreported. */
193
+ get strength() {
194
+ return this.standing.strength;
195
+ }
196
+ /** The bounds the engine ran under. */
197
+ get bounds() {
198
+ return this.standing.bounds;
199
+ }
200
+ toString() {
201
+ if (this.outputs.size > 0) {
202
+ return [...this.outputs.entries()]
203
+ .map(([name, val]) => `${name} = ${render(val)}`)
204
+ .join(", ");
205
+ }
206
+ return render(this.value);
207
+ }
208
+ }
209
+ function render(value) {
210
+ if (value === undefined) {
211
+ return "undefined";
212
+ }
213
+ return value instanceof UnsupportedValueError ? `<unsupported: ${value.message}>` : formatValue(value);
214
+ }
215
+ /** One application an analysis case made of one of its own calcs as a value. */
216
+ export class CaseEvaluation {
217
+ /** FQN of the calc applied. */
218
+ functionId;
219
+ /** What it was applied to; an alternative is the instance it is. */
220
+ arguments;
221
+ /** What it computed; undefined when `error` says why nothing was. */
222
+ result;
223
+ /** Why the evaluation computed nothing; empty when it did. */
224
+ error;
225
+ /** Whether the case returned this evaluation's argument: a trade study's selection. */
226
+ selected;
227
+ /** Whether it computed what the selected one did without being selected. */
228
+ tied;
229
+ constructor(init) {
230
+ this.functionId = init.functionId;
231
+ this.arguments = init.arguments;
232
+ this.result = init.result;
233
+ this.error = init.error ?? "";
234
+ this.selected = init.selected ?? false;
235
+ this.tied = init.tied ?? false;
236
+ }
237
+ /** Whether the evaluation computed a result. */
238
+ get evaluated() {
239
+ return this.error === "";
240
+ }
241
+ /** One line saying what was evaluated, what it gave, and whether it was selected. */
242
+ explain() {
243
+ const call = `${this.functionId}(${this.arguments.map(render).join(", ")})`;
244
+ let line = this.error !== "" ? `${call}: error: ${this.error}` : `${call} = ${render(this.result)}`;
245
+ if (this.selected) {
246
+ line += " [selected]";
247
+ }
248
+ else if (this.tied) {
249
+ line += " [tied]";
250
+ }
251
+ return line;
252
+ }
253
+ toString() {
254
+ return this.explain();
255
+ }
256
+ }
257
+ /** What an analysis case computed and decided. */
258
+ export class AnalysisResult {
259
+ /** Output features the case computed, by name. */
260
+ outputs;
261
+ /** The objective and assertion verdicts, in the order the case states them. */
262
+ verdicts;
263
+ /** The subject the case ran on and the objects reachable from it. */
264
+ instances;
265
+ diagnostics;
266
+ /** For a verification case, what its body answered and each subcase's. */
267
+ verifications;
268
+ /** Each application the run made of one of the case's calcs as a value. */
269
+ evaluations;
270
+ standing;
271
+ constructor(init) {
272
+ this.outputs = init.outputs;
273
+ this.verdicts = init.verdicts;
274
+ this.instances = init.instances ?? [];
275
+ this.diagnostics = init.diagnostics ?? [];
276
+ this.verifications = init.verifications ?? [];
277
+ this.evaluations = init.evaluations ?? [];
278
+ this.standing = init.standing ?? emptyStanding();
279
+ }
280
+ get engine() {
281
+ return this.standing.engine;
282
+ }
283
+ /** Strength of the evidence the answer rests on; empty when unreported. */
284
+ get strength() {
285
+ return this.standing.strength;
286
+ }
287
+ /** The bounds the engine ran under. */
288
+ get bounds() {
289
+ return this.standing.bounds;
290
+ }
291
+ /** The evaluations of the alternatives the case selected; one for a trade study. */
292
+ get selected() {
293
+ return this.evaluations.filter((evaluation) => evaluation.selected);
294
+ }
295
+ /** Whether every objective and assertion holds; a case stating none is satisfied. */
296
+ get satisfied() {
297
+ return this.verdicts.every((verdict) => verdict.verdict.kind === "holds");
298
+ }
299
+ toString() {
300
+ const lines = [
301
+ ...[...this.outputs.entries()].map(([name, val]) => `${name} = ${render(val)}`),
302
+ ...this.verdicts.map((verdict) => explainVerdict(verdict.verdict)),
303
+ ...this.verifications.map(explainVerificationVerdict),
304
+ ...this.evaluations.map((evaluation) => evaluation.explain()),
305
+ ];
306
+ return lines.join("\n");
307
+ }
308
+ }
309
+ /** Every assertion about one object and the objects it holds, answered. */
310
+ export class Validation {
311
+ /** One per assertion, root first then each held object in traversal order. */
312
+ verdicts;
313
+ /** The object's own verdict, of kind 'object'; undefined when the service sent none. */
314
+ summary;
315
+ /** The object validated and every object reachable from it. */
316
+ instances;
317
+ /** Whether traversal stopped at its bound before reaching every held object. */
318
+ bounded;
319
+ diagnostics;
320
+ /** What the bodies of the verification cases of the requirements met answered. */
321
+ verifications;
322
+ constructor(init) {
323
+ this.verdicts = init.verdicts;
324
+ this.summary = init.summary;
325
+ this.instances = init.instances ?? [];
326
+ this.bounded = init.bounded ?? false;
327
+ this.diagnostics = init.diagnostics ?? [];
328
+ this.verifications = init.verifications ?? [];
329
+ }
330
+ /** The standing of the summary's engine; unreported when the service sent none. */
331
+ get standing() {
332
+ return this.summary?.verdict.standing ?? emptyStanding();
333
+ }
334
+ get engine() {
335
+ return this.standing.engine;
336
+ }
337
+ /** Strength of the evidence the answer rests on; empty when unreported. */
338
+ get strength() {
339
+ return this.standing.strength;
340
+ }
341
+ /** The bounds the engine ran under. */
342
+ get bounds() {
343
+ return this.standing.bounds;
344
+ }
345
+ /** Whether the object is shown valid: at least one assertion, every one holding, all reached. */
346
+ get valid() {
347
+ return this.summary?.verdict.kind === "holds" && !this.bounded;
348
+ }
349
+ /** The verdicts the model answered false, as opposed to undecided ones. */
350
+ get violated() {
351
+ return this.verdicts.filter((verdict) => verdict.verdict.kind === "fails");
352
+ }
353
+ /** The verdicts whose condition could not be evaluated. */
354
+ get undecided() {
355
+ return this.verdicts.filter((verdict) => verdict.verdict.kind === "undecided");
356
+ }
357
+ /** Raise an {@link ExecutionError} if any assertion could not be decided. */
358
+ raiseForError() {
359
+ for (const verdict of this.undecided) {
360
+ raiseVerdictError(verdict.verdict);
361
+ }
362
+ return this;
363
+ }
364
+ get length() {
365
+ return this.verdicts.length;
366
+ }
367
+ [Symbol.iterator]() {
368
+ return this.verdicts[Symbol.iterator]();
369
+ }
370
+ toString() {
371
+ const lines = this.verdicts.map((verdict) => explainVerdict(verdict.verdict));
372
+ if (this.summary !== undefined) {
373
+ lines.push(explainVerdict(this.summary.verdict));
374
+ }
375
+ return lines.join("\n");
376
+ }
377
+ }
378
+ /** One run of a sweep: what it bound, what it produced, and how long it took. */
379
+ export class SweepRow {
380
+ /** The swept parameters as this run bound them, by name. */
381
+ inputs;
382
+ /** What the run produced, by name; a calc's return is named "result". */
383
+ outputs;
384
+ /** The objective and assertion verdicts of an analysis case; empty for a calc. */
385
+ verdicts;
386
+ /** Wall time of this run, in seconds. */
387
+ seconds;
388
+ /** Why this run failed; empty when it did not. */
389
+ error;
390
+ /** Each application this run made of one of the case's calcs as a value. */
391
+ evaluations;
392
+ constructor(init) {
393
+ this.inputs = init.inputs;
394
+ this.outputs = init.outputs;
395
+ this.verdicts = init.verdicts;
396
+ this.seconds = init.seconds;
397
+ this.error = init.error ?? "";
398
+ this.evaluations = init.evaluations ?? [];
399
+ }
400
+ /** The evaluations of the alternatives this run selected; one for a trade study. */
401
+ get selected() {
402
+ return this.evaluations.filter((evaluation) => evaluation.selected);
403
+ }
404
+ /** Whether this run failed rather than producing outputs. */
405
+ get failed() {
406
+ return this.error !== "";
407
+ }
408
+ toString() {
409
+ const inputs = [...this.inputs.entries()].map(([n, v]) => `${n}=${render(v)}`).join(", ");
410
+ if (this.failed) {
411
+ return `${inputs}: ${this.error}`;
412
+ }
413
+ const outputs = [...this.outputs.entries()].map(([n, v]) => `${n} = ${render(v)}`).join(", ");
414
+ return `${inputs}: ${outputs}`;
415
+ }
416
+ }
417
+ /** Every run of one sweep, in the order the runs were made. */
418
+ export class SweepTable {
419
+ /** One row per run. */
420
+ rows;
421
+ /** The swept parameters, in the order their ranges were given. */
422
+ parameters;
423
+ /** Whether the rows were drawn rather than stepped through. */
424
+ sampled;
425
+ /** The seed the rows were drawn from; 0 for a swept table. */
426
+ seed;
427
+ /** The subjects the runs were about and the objects reachable from them. */
428
+ instances;
429
+ diagnostics;
430
+ standing;
431
+ constructor(init) {
432
+ this.rows = init.rows;
433
+ this.parameters = init.parameters;
434
+ this.sampled = init.sampled ?? false;
435
+ this.seed = init.seed ?? 0n;
436
+ this.instances = init.instances ?? [];
437
+ this.diagnostics = init.diagnostics ?? [];
438
+ this.standing = init.standing ?? emptyStanding();
439
+ }
440
+ get engine() {
441
+ return this.standing.engine;
442
+ }
443
+ /** Strength of the evidence the answer rests on; empty when unreported. */
444
+ get strength() {
445
+ return this.standing.strength;
446
+ }
447
+ /** The bounds the engine ran under. */
448
+ get bounds() {
449
+ return this.standing.bounds;
450
+ }
451
+ /** The runs that failed. */
452
+ get failures() {
453
+ return this.rows.filter((row) => row.failed);
454
+ }
455
+ get length() {
456
+ return this.rows.length;
457
+ }
458
+ [Symbol.iterator]() {
459
+ return this.rows[Symbol.iterator]();
460
+ }
461
+ row(index) {
462
+ if (index < 0 || index >= this.rows.length) {
463
+ throw new RangeError(`the table has ${this.rows.length} rows, not ${index + 1}`);
464
+ }
465
+ return this.rows[index];
466
+ }
467
+ toString() {
468
+ return this.rows.map((row) => row.toString()).join("\n");
469
+ }
470
+ }
471
+ /** Read the case evaluations of a response, undecodable values kept as errors. */
472
+ export function evaluationsOf(evals) {
473
+ return evals.map((pb) => new CaseEvaluation({
474
+ functionId: pb.functionId,
475
+ arguments: pb.arguments.map((argument) => valueOrError(argument)),
476
+ ...(pb.error === "" && pb.result !== undefined
477
+ ? { result: valueOrError(pb.result) }
478
+ : {}),
479
+ error: pb.error,
480
+ selected: pb.selected,
481
+ tied: pb.tied,
482
+ }));
483
+ }
484
+ /** Decode one wire `Value`, keeping a decode failure as the error it raised. */
485
+ export function valueOrError(pb) {
486
+ try {
487
+ return decodeValue(pb);
488
+ }
489
+ catch (error) {
490
+ return asUnsupported(error);
491
+ }
492
+ }
493
+ /** A decode failure as the UnsupportedValueError it is, or one carrying its message. */
494
+ function asUnsupported(error) {
495
+ if (error instanceof UnsupportedValueError) {
496
+ return error;
497
+ }
498
+ return new UnsupportedValueError(error instanceof Error ? error.message : String(error));
499
+ }
500
+ /** Read the verdicts a validation response carries, and its summary. */
501
+ export function validationOf(response, instances, diagnostics) {
502
+ const verifications = response.verificationVerdicts.map(decodeVerificationVerdict);
503
+ const verdicts = response.verdicts.map((pbVerdict) => verdictOf(pbVerdict, instances, diagnostics, verifications));
504
+ return new Validation({
505
+ verdicts,
506
+ ...(response.summary === undefined
507
+ ? {}
508
+ : { summary: verdictOf(response.summary, instances, diagnostics, verifications, true) }),
509
+ instances,
510
+ bounded: response.bounded,
511
+ diagnostics,
512
+ verifications,
513
+ });
514
+ }
515
+ /** Read a RunAnalysis response, or raise its failure. */
516
+ export function analysisResultOf(response, instances, diagnostics) {
517
+ const verifications = response.verificationVerdicts.map(decodeVerificationVerdict);
518
+ const outputs = new Map();
519
+ for (const output of response.outputs) {
520
+ outputs.set(output.name, valueOrError(output.value));
521
+ }
522
+ const result = new AnalysisResult({
523
+ outputs,
524
+ verdicts: response.verdicts.map((pbVerdict) => verdictOf(pbVerdict, instances, diagnostics, [])),
525
+ instances,
526
+ diagnostics,
527
+ verifications,
528
+ evaluations: evaluationsOf(response.evaluations),
529
+ standing: standingOf(response),
530
+ });
531
+ if (response.error !== "") {
532
+ throw new AnalysisRunError(response.error, result, { diagnostics });
533
+ }
534
+ return result;
535
+ }
536
+ /** Read a RunSweep response into a SweepTable. */
537
+ export function sweepTableOf(response, instances, diagnostics) {
538
+ const rows = response.rows.map((row) => sweepRowOf(row, instances, diagnostics));
539
+ return new SweepTable({
540
+ rows,
541
+ parameters: [...response.parameters],
542
+ sampled: response.sampled,
543
+ seed: response.seed,
544
+ instances,
545
+ diagnostics,
546
+ standing: standingOf(response),
547
+ });
548
+ }
549
+ function sweepRowOf(row, instances, diagnostics) {
550
+ const inputs = new Map();
551
+ const outputs = new Map();
552
+ for (const entry of row.inputs) {
553
+ inputs.set(entry.name, valueOrError(entry.value));
554
+ }
555
+ for (const entry of row.outputs) {
556
+ outputs.set(entry.name, valueOrError(entry.value));
557
+ }
558
+ const verifications = [];
559
+ return new SweepRow({
560
+ inputs,
561
+ outputs,
562
+ verdicts: row.verdicts.map((pbVerdict) => verdictOf(pbVerdict, instances, diagnostics, verifications)),
563
+ seconds: Number(row.elapsedMicros) / 1e6,
564
+ error: row.error,
565
+ evaluations: evaluationsOf(row.evaluations),
566
+ });
567
+ }
@@ -0,0 +1,114 @@
1
+ import { type Transport } from "@connectrpc/connect";
2
+ import { Connection } from "./connection.js";
3
+ import type { TransportOptions } from "./connection.js";
4
+ /** A host surface implemented by an inline Go runtime or a worker. */
5
+ export interface WasmHost {
6
+ readonly version: string;
7
+ call(method: string, params: string, signal?: AbortSignal): Promise<string>;
8
+ close(): Promise<void>;
9
+ }
10
+ /** The Go runtime interface exposed by wasm_exec.js. */
11
+ export interface GoRuntime {
12
+ readonly importObject: WebAssembly.Imports;
13
+ run(instance: WebAssembly.Instance): Promise<unknown>;
14
+ }
15
+ /** A constructor exported globally by wasm_exec.js. */
16
+ export type GoConstructor = new () => GoRuntime;
17
+ export type WorkerWasmSource = string | ArrayBuffer | Uint8Array | WebAssembly.Module;
18
+ export type WasmWorkerRequest = {
19
+ type: "init";
20
+ wasm: WorkerWasmSource;
21
+ wasmExec?: string;
22
+ } | {
23
+ type: "call";
24
+ id: number;
25
+ method: string;
26
+ params: string;
27
+ } | {
28
+ type: "close";
29
+ };
30
+ export type WasmWorkerResponse = {
31
+ type: "ready";
32
+ version: string;
33
+ } | {
34
+ type: "failed";
35
+ message: string;
36
+ } | {
37
+ type: "answer";
38
+ id: number;
39
+ envelope: string;
40
+ };
41
+ /** The platform-specific message and lifecycle surface of a WASM worker. */
42
+ export interface WasmWorkerEndpoint {
43
+ post(message: WasmWorkerRequest, transfer: readonly Transferable[]): void;
44
+ onMessage(listener: (message: WasmWorkerResponse) => void): void;
45
+ onFailure(listener: (reason: Error) => void): void;
46
+ terminate(): Promise<void> | void;
47
+ }
48
+ /** The message port surface shared by browser and Node workers. */
49
+ export interface WasmPortLike {
50
+ postMessage(message: WasmWorkerResponse): void;
51
+ addEventListener(type: "message", listener: (event: MessageEvent<WasmWorkerRequest>) => void): void;
52
+ start?(): void;
53
+ }
54
+ /** Optional platform loaders for worker runtimes that need local file access. */
55
+ export interface WasmPortLoaders {
56
+ loadWasm?(source: WorkerWasmSource): Promise<BufferSource | WebAssembly.Module>;
57
+ loadGo?(wasmExec: string | undefined): Promise<GoConstructor>;
58
+ }
59
+ /** Connection settings shared by the Node and browser WASM clients. */
60
+ export interface WasmConnectionOptions extends TransportOptions {
61
+ version?: string;
62
+ requireCapabilities?: readonly string[];
63
+ }
64
+ interface GlobalWasmSurface {
65
+ readonly version: string;
66
+ call(method: string, params: string): string;
67
+ }
68
+ /**
69
+ * Adapts the Go host global to the asynchronous host interface.
70
+ */
71
+ export declare function wasmHostFromGlobal(surface?: GlobalWasmSurface): WasmHost;
72
+ /**
73
+ * Starts a Go WebAssembly module in this realm and captures its host global.
74
+ */
75
+ export declare function instantiateInline(module: BufferSource | WebAssembly.Module, Go: GoConstructor): Promise<WasmHost>;
76
+ /**
77
+ * Creates a Connect transport for the JSON envelope served by sysml-wasm.
78
+ */
79
+ export declare function createWasmTransport(host: WasmHost, options: TransportOptions): Transport;
80
+ /**
81
+ * Opens a Connection over a WASM host, negotiating its version and capabilities.
82
+ */
83
+ export declare function connectWasmHost(host: WasmHost, options?: WasmConnectionOptions): Promise<Connection>;
84
+ /** Adapts a platform worker endpoint to the shared WASM host protocol. */
85
+ export declare class WorkerWasmHost implements WasmHost {
86
+ private readonly endpoint;
87
+ version: string;
88
+ private readonly pending;
89
+ private readonly ready;
90
+ private resolveReady;
91
+ private rejectReady;
92
+ private nextId;
93
+ private failure;
94
+ private closed;
95
+ constructor(endpoint: WasmWorkerEndpoint);
96
+ start(request: Extract<WasmWorkerRequest, {
97
+ type: "init";
98
+ }>, transfer: readonly Transferable[]): Promise<this>;
99
+ call(method: string, params: string, signal?: AbortSignal): Promise<string>;
100
+ close(): Promise<void>;
101
+ private receive;
102
+ private fail;
103
+ private removePending;
104
+ private throwIfFailed;
105
+ private throwIfClosed;
106
+ }
107
+ /**
108
+ * Serves the shared init/call protocol on a Node or browser worker port.
109
+ */
110
+ export declare function serveWasmPort(port: WasmPortLike, loaders?: WasmPortLoaders): void;
111
+ /** Loads and caches the Go constructor installed by wasm_exec.js. */
112
+ export declare function loadGoConstructor(wasmExec?: string): Promise<GoConstructor>;
113
+ export declare function loadWasmSource(source: WorkerWasmSource | URL | Response): Promise<BufferSource | WebAssembly.Module>;
114
+ export {};