@tellegen/engine 0.4.1 → 0.4.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.
Files changed (49) hide show
  1. package/README.md +33 -0
  2. package/dist/acopf-protocol.d.ts +20 -0
  3. package/dist/acopf-protocol.d.ts.map +1 -0
  4. package/dist/acopf-protocol.js +2 -0
  5. package/dist/acopf-protocol.js.map +1 -0
  6. package/dist/acopf-wasi.d.ts +29 -0
  7. package/dist/acopf-wasi.d.ts.map +1 -0
  8. package/dist/acopf-wasi.js +91 -0
  9. package/dist/acopf-wasi.js.map +1 -0
  10. package/dist/acopf-worker.d.ts +2 -0
  11. package/dist/acopf-worker.d.ts.map +1 -0
  12. package/dist/acopf-worker.js +86 -0
  13. package/dist/acopf-worker.js.map +1 -0
  14. package/dist/acopf.d.ts +19 -0
  15. package/dist/acopf.d.ts.map +1 -0
  16. package/dist/acopf.js +84 -0
  17. package/dist/acopf.js.map +1 -0
  18. package/dist/acopf.test.d.ts +2 -0
  19. package/dist/acopf.test.d.ts.map +1 -0
  20. package/dist/acopf.test.js +91 -0
  21. package/dist/acopf.test.js.map +1 -0
  22. package/dist/generated/api-types.d.ts +110 -4
  23. package/dist/generated/api-types.d.ts.map +1 -1
  24. package/dist/generated/api-types.js +3 -3
  25. package/dist/generated/study-schema.d.ts.map +1 -1
  26. package/dist/generated/study-schema.js +1 -1
  27. package/dist/generated/study-schema.js.map +1 -1
  28. package/dist/generated/study-types.d.ts +54 -1
  29. package/dist/generated/study-types.d.ts.map +1 -1
  30. package/dist/generated/study-types.js +1 -1
  31. package/dist/generated/synth-schema.d.ts.map +1 -1
  32. package/dist/generated/synth-schema.js +1 -1
  33. package/dist/generated/synth-schema.js.map +1 -1
  34. package/dist/generated/synth-types.d.ts +1 -0
  35. package/dist/generated/synth-types.d.ts.map +1 -1
  36. package/dist/generated/synth-types.js +1 -1
  37. package/dist/index.d.ts +129 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +21 -5
  40. package/dist/index.js.map +1 -1
  41. package/dist/protocol.d.ts +4 -0
  42. package/dist/protocol.d.ts.map +1 -1
  43. package/dist/protocol.js +2 -0
  44. package/dist/protocol.js.map +1 -1
  45. package/dist/wasm-pkg/tellegen.d.ts +8 -0
  46. package/dist/wasm-pkg/tellegen.js +32 -1
  47. package/dist/wasm-pkg/tellegen_bg.wasm +0 -0
  48. package/dist/wasm-pkg/tellegen_bg.wasm.d.ts +1 -0
  49. package/package.json +1 -1
package/README.md CHANGED
@@ -50,6 +50,9 @@ Every solvable ingest payload includes `module_json`, a generation-2 PowerIO
50
50
  IR module. Pass that value to `createStudy`, `solveModule`, and geographic
51
51
  transforms. The engine does not expose a second network JSON boundary.
52
52
 
53
+ Stored AC OPF instances retain `formulation: "acopf"` and their original
54
+ `module_json`. They use the experimental worker below, not `createStudy`.
55
+
53
56
  `ingestJsonDrop(bytes)` classifies and parses JSON in one call. Its
54
57
  `IngestedJsonDrop` result is discriminated by `kind`: PowerIO modules have a
55
58
  `null` format; transmission and distribution results carry the selected
@@ -59,6 +62,36 @@ bare model JSON is now `unknown`; regenerate it as `pio-ir` from source data.
59
62
  Every API that accepts a byte buffer rejects inputs larger than
60
63
  `MAX_ENGINE_INPUT_BYTES` (128 MiB) before worker dispatch.
61
64
 
65
+ ## Experimental AC OPF
66
+
67
+ The ordinary package contains no POUNCE WASI asset. A development host must
68
+ explicitly build and serve it, then probe it before offering AC OPF:
69
+
70
+ ```ts
71
+ import { probeAcOpfWorker, solveAcOpfModule } from "@tellegen/engine";
72
+
73
+ const wasmUrl = "/experimental-acopf/tellegen_acopf_wasi.wasm";
74
+ const lifetime = new AbortController();
75
+ if (!(await probeAcOpfWorker(wasmUrl, undefined, lifetime.signal)))
76
+ throw new Error("AC OPF unavailable");
77
+ const cancel = new AbortController();
78
+ const result = await solveAcOpfModule(wasmUrl, moduleJson, cancel.signal);
79
+ // Calling cancel.abort() during a solve terminates its dedicated worker.
80
+ ```
81
+
82
+ `moduleJson` must hold a balanced network or canonical `AcOpfInstance`. Each
83
+ call uses a fresh worker and solves the supplied base operating point. Edits,
84
+ sensitivities, LMPs, retained Studies, and browser solution export are not
85
+ supported. There is no server or main-thread fallback. A successful result is
86
+ locally feasible, not a proof of global optimality.
87
+
88
+ See the [development setup and release gates](../../docs/src/acopf-pounce-decision.md#experimental-browser-abi)
89
+ before building or distributing the separate asset.
90
+
91
+ Probe calls accept an optional third `AbortSignal` argument. Abort it when the
92
+ owning view is disposed; a cancelled probe returns `false` and terminates its
93
+ worker. Solve calls accept their cancellation signal as the third argument.
94
+
62
95
  ## Synthetic Grid Generation
63
96
 
64
97
  `createSynthSession(request, { osm?, places?, signal? })` generates a
@@ -0,0 +1,20 @@
1
+ import type { SolveResponse } from "./generated/api-types.js";
2
+ export type AcOpfWorkerRequest = {
3
+ type: "probe";
4
+ wasmUrl: string;
5
+ } | {
6
+ type: "solve";
7
+ wasmUrl: string;
8
+ moduleJson: string;
9
+ requestJson: string;
10
+ };
11
+ export type AcOpfWorkerResponse = {
12
+ type: "ready";
13
+ } | {
14
+ type: "result";
15
+ response: SolveResponse;
16
+ } | {
17
+ type: "error";
18
+ message: string;
19
+ };
20
+ //# sourceMappingURL=acopf-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf-protocol.d.ts","sourceRoot":"","sources":["../src/acopf-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=acopf-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf-protocol.js","sourceRoot":"","sources":["../src/acopf-protocol.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ /** Minimal WASI Preview 1 host for the compute-only AC OPF reactor. */
2
+ export declare function createAcOpfWasi(onOutput: (text: string) => void): {
3
+ imports: {
4
+ wasi_snapshot_preview1: {
5
+ fd_write(fd: number, iovs: number, iovsLen: number, nwritten: number): number;
6
+ clock_time_get(_id: number, _precision: bigint, out: number): number;
7
+ clock_res_get(_id: number, out: number): number;
8
+ random_get(buf: number, len: number): 0 | 8;
9
+ environ_sizes_get(count: number, size: number): number;
10
+ environ_get: () => number;
11
+ args_sizes_get(count: number, size: number): number;
12
+ args_get: () => number;
13
+ proc_exit(code: number): never;
14
+ sched_yield: () => number;
15
+ fd_close: () => number;
16
+ fd_fdstat_get: () => number;
17
+ fd_fdstat_set_flags: () => number;
18
+ fd_prestat_get: () => number;
19
+ fd_prestat_dir_name: () => number;
20
+ fd_read: () => number;
21
+ fd_seek: () => number;
22
+ path_create_directory: () => number;
23
+ path_filestat_get: () => number;
24
+ path_open: () => number;
25
+ };
26
+ };
27
+ bind(instance: WebAssembly.Instance): void;
28
+ };
29
+ //# sourceMappingURL=acopf-wasi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf-wasi.d.ts","sourceRoot":"","sources":["../src/acopf-wasi.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAMvE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;;;yBAS/C,MAAM,QAAQ,MAAM,WAAW,MAAM,YAAY,MAAM;gCAgBhD,MAAM,cAAc,MAAM,OAAO,MAAM;+BAQxC,MAAM,OAAO,MAAM;4BAItB,MAAM,OAAO,MAAM;qCAWV,MAAM,QAAQ,MAAM;;kCAOvB,MAAM,QAAQ,MAAM;;4BAO1B,MAAM,GAAG,KAAK;;;;;;;;;;;;;;mBAkBf,WAAW,CAAC,QAAQ;EAStC"}
@@ -0,0 +1,91 @@
1
+ /** Minimal WASI Preview 1 host for the compute-only AC OPF reactor. */
2
+ const ERRNO_SUCCESS = 0;
3
+ const ERRNO_BADF = 8;
4
+ const ERRNO_NOSYS = 52;
5
+ export function createAcOpfWasi(onOutput) {
6
+ let memory = null;
7
+ const decoder = new TextDecoder();
8
+ const view = () => {
9
+ if (!memory)
10
+ throw new Error("AC OPF WASI memory is not bound");
11
+ return new DataView(memory.buffer);
12
+ };
13
+ const wasi_snapshot_preview1 = {
14
+ fd_write(fd, iovs, iovsLen, nwritten) {
15
+ const data = view();
16
+ let written = 0;
17
+ let output = "";
18
+ for (let index = 0; index < iovsLen; index += 1) {
19
+ const ptr = data.getUint32(iovs + index * 8, true);
20
+ const len = data.getUint32(iovs + index * 8 + 4, true);
21
+ if (len > 0 && memory) {
22
+ output += decoder.decode(new Uint8Array(memory.buffer, ptr, len));
23
+ }
24
+ written += len;
25
+ }
26
+ data.setUint32(nwritten, written, true);
27
+ if (output && (fd === 1 || fd === 2))
28
+ onOutput(output);
29
+ return ERRNO_SUCCESS;
30
+ },
31
+ clock_time_get(_id, _precision, out) {
32
+ view().setBigUint64(out, BigInt(Math.round(performance.now() * 1e6)), true);
33
+ return ERRNO_SUCCESS;
34
+ },
35
+ clock_res_get(_id, out) {
36
+ view().setBigUint64(out, 1000n, true);
37
+ return ERRNO_SUCCESS;
38
+ },
39
+ random_get(buf, len) {
40
+ if (!memory)
41
+ return ERRNO_BADF;
42
+ const bytes = new Uint8Array(memory.buffer, buf, len);
43
+ // Web Crypto limits one call to 65,536 bytes.
44
+ for (let offset = 0; offset < len; offset += 65_536) {
45
+ crypto.getRandomValues(bytes.subarray(offset, Math.min(len, offset + 65_536)));
46
+ }
47
+ return ERRNO_SUCCESS;
48
+ },
49
+ environ_sizes_get(count, size) {
50
+ const data = view();
51
+ data.setUint32(count, 0, true);
52
+ data.setUint32(size, 0, true);
53
+ return ERRNO_SUCCESS;
54
+ },
55
+ environ_get: () => ERRNO_SUCCESS,
56
+ args_sizes_get(count, size) {
57
+ const data = view();
58
+ data.setUint32(count, 0, true);
59
+ data.setUint32(size, 0, true);
60
+ return ERRNO_SUCCESS;
61
+ },
62
+ args_get: () => ERRNO_SUCCESS,
63
+ proc_exit(code) {
64
+ throw new Error(`AC OPF wasm called proc_exit(${code})`);
65
+ },
66
+ sched_yield: () => ERRNO_SUCCESS,
67
+ fd_close: () => ERRNO_BADF,
68
+ fd_fdstat_get: () => ERRNO_BADF,
69
+ fd_fdstat_set_flags: () => ERRNO_BADF,
70
+ fd_prestat_get: () => ERRNO_BADF,
71
+ fd_prestat_dir_name: () => ERRNO_BADF,
72
+ fd_read: () => ERRNO_BADF,
73
+ fd_seek: () => ERRNO_BADF,
74
+ path_create_directory: () => ERRNO_NOSYS,
75
+ path_filestat_get: () => ERRNO_NOSYS,
76
+ path_open: () => ERRNO_NOSYS,
77
+ };
78
+ return {
79
+ imports: { wasi_snapshot_preview1 },
80
+ bind(instance) {
81
+ memory = instance.exports.memory;
82
+ if (!(memory instanceof WebAssembly.Memory)) {
83
+ throw new Error("AC OPF wasm did not export memory");
84
+ }
85
+ const initialize = instance.exports._initialize;
86
+ if (typeof initialize === "function")
87
+ initialize();
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=acopf-wasi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf-wasi.js","sourceRoot":"","sources":["../src/acopf-wasi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=acopf-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf-worker.d.ts","sourceRoot":"","sources":["../src/acopf-worker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,86 @@
1
+ import { errorText } from "./errors.js";
2
+ import { createAcOpfWasi } from "./acopf-wasi.js";
3
+ const scope = globalThis;
4
+ const encoder = new TextEncoder();
5
+ const decoder = new TextDecoder();
6
+ async function instantiate(url) {
7
+ const wasi = createAcOpfWasi((text) => console.debug("[acopf]", text.trimEnd()));
8
+ const response = await fetch(url);
9
+ if (!response.ok) {
10
+ throw new Error(`AC OPF wasm fetch failed (HTTP ${response.status})`);
11
+ }
12
+ let instance;
13
+ try {
14
+ ({ instance } = await WebAssembly.instantiateStreaming(Promise.resolve(response.clone()), wasi.imports));
15
+ }
16
+ catch {
17
+ ({ instance } = await WebAssembly.instantiate(await response.arrayBuffer(), wasi.imports));
18
+ }
19
+ wasi.bind(instance);
20
+ const exports = instance.exports;
21
+ for (const name of [
22
+ "tellegen_acopf_alloc",
23
+ "tellegen_acopf_dealloc",
24
+ "tellegen_acopf_free_payload",
25
+ "tellegen_acopf_solve",
26
+ ]) {
27
+ if (typeof exports[name] !== "function") {
28
+ throw new Error(`AC OPF wasm is missing its ${name} export`);
29
+ }
30
+ }
31
+ return exports;
32
+ }
33
+ function copyInput(exports, text) {
34
+ const bytes = encoder.encode(text);
35
+ const ptr = exports.tellegen_acopf_alloc(bytes.length);
36
+ if (!ptr)
37
+ throw new Error("AC OPF wasm allocation failed");
38
+ new Uint8Array(exports.memory.buffer, ptr, bytes.length).set(bytes);
39
+ return [ptr, bytes.length];
40
+ }
41
+ function readPayload(exports, ptr) {
42
+ if (!ptr)
43
+ throw new Error("AC OPF wasm returned no payload");
44
+ const memory = new Uint8Array(exports.memory.buffer);
45
+ if (ptr + 4 > memory.length)
46
+ throw new Error("AC OPF wasm returned an invalid pointer");
47
+ const len = new DataView(exports.memory.buffer).getUint32(ptr, true);
48
+ if (ptr + 4 + len > memory.length) {
49
+ throw new Error("AC OPF wasm returned an invalid payload length");
50
+ }
51
+ const text = decoder.decode(memory.subarray(ptr + 4, ptr + 4 + len));
52
+ exports.tellegen_acopf_free_payload(ptr);
53
+ return JSON.parse(text);
54
+ }
55
+ scope.onmessage = async ({ data }) => {
56
+ try {
57
+ const exports = await instantiate(data.wasmUrl);
58
+ if (data.type === "probe") {
59
+ scope.postMessage({ type: "ready" });
60
+ scope.close();
61
+ return;
62
+ }
63
+ const moduleInput = copyInput(exports, data.moduleJson);
64
+ const requestInput = copyInput(exports, data.requestJson);
65
+ try {
66
+ const value = readPayload(exports, exports.tellegen_acopf_solve(...moduleInput, ...requestInput));
67
+ if (typeof value?.error === "string")
68
+ throw new Error(value.error);
69
+ scope.postMessage({
70
+ type: "result",
71
+ response: value,
72
+ });
73
+ }
74
+ finally {
75
+ exports.tellegen_acopf_dealloc(...moduleInput);
76
+ exports.tellegen_acopf_dealloc(...requestInput);
77
+ }
78
+ }
79
+ catch (error) {
80
+ scope.postMessage({ type: "error", message: errorText(error) });
81
+ }
82
+ finally {
83
+ scope.close();
84
+ }
85
+ };
86
+ //# sourceMappingURL=acopf-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf-worker.js","sourceRoot":"","sources":["../src/acopf-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SolveResponse } from "./generated/api-types.js";
2
+ import type { AcOpfWorkerRequest, AcOpfWorkerResponse } from "./acopf-protocol.js";
3
+ interface WorkerLike {
4
+ onmessage: ((event: MessageEvent<AcOpfWorkerResponse>) => void) | null;
5
+ onerror: ((event: ErrorEvent) => void) | null;
6
+ onmessageerror: ((event: MessageEvent) => void) | null;
7
+ postMessage(message: AcOpfWorkerRequest): void;
8
+ terminate(): void;
9
+ }
10
+ export type AcOpfWorkerFactory = () => WorkerLike;
11
+ /** Probe the optional development asset in the same worker/WASI environment a
12
+ * solve uses. A missing asset, unsupported browser, or instantiation failure
13
+ * returns false and leaves the formulation disabled. */
14
+ export declare function probeAcOpfWorker(wasmUrl: string, workerFactory?: AcOpfWorkerFactory, signal?: AbortSignal): Promise<boolean>;
15
+ /** Run one nonlinear AC OPF in a fresh, dedicated worker. Cancellation always
16
+ * terminates that worker; there is deliberately no main-thread fallback. */
17
+ export declare function solveAcOpfModule(wasmUrl: string, moduleJson: string, signal?: AbortSignal, workerFactory?: AcOpfWorkerFactory): Promise<SolveResponse>;
18
+ export {};
19
+ //# sourceMappingURL=acopf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf.d.ts","sourceRoot":"","sources":["../src/acopf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAG7B,UAAU,UAAU;IAClB,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACvE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC/C,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,UAAU,CAAC;AA8DlD;;wDAEwD;AACxD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,kBAAkB,EAClC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;4EAC4E;AAC5E,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,WAAW,EACpB,aAAa,CAAC,EAAE,kBAAkB,GACjC,OAAO,CAAC,aAAa,CAAC,CAgBxB"}
package/dist/acopf.js ADDED
@@ -0,0 +1,84 @@
1
+ import { assertEngineInputLength } from "./input-limit.js";
2
+ const defaultWorkerFactory = () => new Worker(new URL("./acopf-worker.js", import.meta.url), { type: "module" });
3
+ function workerCall(request, signal, workerFactory = defaultWorkerFactory) {
4
+ signal?.throwIfAborted();
5
+ if (typeof Worker === "undefined" && workerFactory === defaultWorkerFactory) {
6
+ return Promise.reject(new Error("AC OPF requires a browser with dedicated Worker support"));
7
+ }
8
+ return new Promise((resolve, reject) => {
9
+ let worker;
10
+ try {
11
+ worker = workerFactory();
12
+ }
13
+ catch (error) {
14
+ reject(error);
15
+ return;
16
+ }
17
+ const finish = () => {
18
+ signal?.removeEventListener("abort", abort);
19
+ worker.onmessage = null;
20
+ worker.onerror = null;
21
+ worker.onmessageerror = null;
22
+ worker.terminate();
23
+ };
24
+ const abort = () => {
25
+ finish();
26
+ reject(new DOMException("AC OPF solve cancelled", "AbortError"));
27
+ };
28
+ signal?.addEventListener("abort", abort, { once: true });
29
+ if (signal?.aborted) {
30
+ abort();
31
+ return;
32
+ }
33
+ worker.onmessage = ({ data }) => {
34
+ finish();
35
+ if (data.type === "error")
36
+ reject(new Error(data.message));
37
+ else
38
+ resolve(data);
39
+ };
40
+ worker.onerror = () => {
41
+ finish();
42
+ reject(new Error("AC OPF worker failed"));
43
+ };
44
+ worker.onmessageerror = () => {
45
+ finish();
46
+ reject(new Error("AC OPF worker returned an unreadable message"));
47
+ };
48
+ try {
49
+ worker.postMessage(request);
50
+ }
51
+ catch (error) {
52
+ finish();
53
+ reject(error);
54
+ }
55
+ });
56
+ }
57
+ /** Probe the optional development asset in the same worker/WASI environment a
58
+ * solve uses. A missing asset, unsupported browser, or instantiation failure
59
+ * returns false and leaves the formulation disabled. */
60
+ export async function probeAcOpfWorker(wasmUrl, workerFactory, signal) {
61
+ try {
62
+ const response = await workerCall({ type: "probe", wasmUrl }, signal, workerFactory);
63
+ return response.type === "ready";
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ /** Run one nonlinear AC OPF in a fresh, dedicated worker. Cancellation always
70
+ * terminates that worker; there is deliberately no main-thread fallback. */
71
+ export async function solveAcOpfModule(wasmUrl, moduleJson, signal, workerFactory) {
72
+ assertEngineInputLength(moduleJson.length);
73
+ const response = await workerCall({
74
+ type: "solve",
75
+ wasmUrl,
76
+ moduleJson,
77
+ requestJson: JSON.stringify({ formulation: "acopf" }),
78
+ }, signal, workerFactory);
79
+ if (response.type !== "result") {
80
+ throw new Error("AC OPF worker returned no solve result");
81
+ }
82
+ return response.response;
83
+ }
84
+ //# sourceMappingURL=acopf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf.js","sourceRoot":"","sources":["../src/acopf.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=acopf.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf.test.d.ts","sourceRoot":"","sources":["../src/acopf.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { probeAcOpfWorker, solveAcOpfModule, } from "./acopf.js";
3
+ class FakeWorker {
4
+ onmessage = null;
5
+ onerror = null;
6
+ onmessageerror = null;
7
+ terminated = false;
8
+ request = null;
9
+ postMessage(request) {
10
+ this.request = request;
11
+ }
12
+ terminate() {
13
+ this.terminated = true;
14
+ }
15
+ reply(response) {
16
+ this.onmessage?.({ data: response });
17
+ }
18
+ }
19
+ describe("experimental AC OPF worker host", () => {
20
+ it("enables the capability only after the WASI worker probes successfully", async () => {
21
+ const worker = new FakeWorker();
22
+ const pending = probeAcOpfWorker("/acopf.wasm", () => worker);
23
+ expect(worker.request).toEqual({ type: "probe", wasmUrl: "/acopf.wasm" });
24
+ worker.reply({ type: "ready" });
25
+ await expect(pending).resolves.toBe(true);
26
+ expect(worker.terminated).toBe(true);
27
+ });
28
+ it("keeps the capability disabled when the asset or ABI probe fails", async () => {
29
+ const worker = new FakeWorker();
30
+ const pending = probeAcOpfWorker("/missing.wasm", () => worker);
31
+ worker.reply({ type: "error", message: "HTTP 404" });
32
+ await expect(pending).resolves.toBe(false);
33
+ expect(worker.terminated).toBe(true);
34
+ });
35
+ it("terminates the isolated worker on cancellation and never falls back", async () => {
36
+ const worker = new FakeWorker();
37
+ const factory = () => worker;
38
+ const abort = new AbortController();
39
+ const pending = solveAcOpfModule("/acopf.wasm", "{}", abort.signal, factory);
40
+ abort.abort();
41
+ await expect(pending).rejects.toMatchObject({ name: "AbortError" });
42
+ expect(worker.terminated).toBe(true);
43
+ });
44
+ it("returns the typed solve response and disposes the one-shot worker", async () => {
45
+ const workers = [new FakeWorker(), new FakeWorker()];
46
+ let index = 0;
47
+ const factory = () => workers[index++];
48
+ const first = solveAcOpfModule("/acopf.wasm", "{}", undefined, factory);
49
+ workers[0].reply({
50
+ type: "result",
51
+ response: { formulation: "acopf", status: "feasible" },
52
+ });
53
+ await expect(first).resolves.toMatchObject({ formulation: "acopf" });
54
+ const second = solveAcOpfModule("/acopf.wasm", "{}", undefined, factory);
55
+ workers[1].reply({
56
+ type: "result",
57
+ response: { formulation: "acopf", status: "feasible" },
58
+ });
59
+ await expect(second).resolves.toMatchObject({ formulation: "acopf" });
60
+ expect(workers.every((worker) => worker.terminated)).toBe(true);
61
+ expect(index).toBe(2);
62
+ });
63
+ it("terminates a pending probe when its owner is disposed", async () => {
64
+ const worker = new FakeWorker();
65
+ const abort = new AbortController();
66
+ const pending = probeAcOpfWorker("/acopf.wasm", () => worker, abort.signal);
67
+ abort.abort();
68
+ await expect(pending).resolves.toBe(false);
69
+ expect(worker.terminated).toBe(true);
70
+ expect(worker.onmessage).toBeNull();
71
+ });
72
+ it("does not create a worker for an already cancelled probe", async () => {
73
+ const abort = new AbortController();
74
+ abort.abort();
75
+ let created = false;
76
+ await expect(probeAcOpfWorker("/acopf.wasm", () => {
77
+ created = true;
78
+ return new FakeWorker();
79
+ }, abort.signal)).resolves.toBe(false);
80
+ expect(created).toBe(false);
81
+ });
82
+ it("disposes the worker if posting the request throws", async () => {
83
+ const worker = new FakeWorker();
84
+ worker.postMessage = () => {
85
+ throw new Error("post failed");
86
+ };
87
+ await expect(solveAcOpfModule("/acopf.wasm", "{}", undefined, () => worker)).rejects.toThrow("post failed");
88
+ expect(worker.terminated).toBe(true);
89
+ });
90
+ });
91
+ //# sourceMappingURL=acopf.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acopf.test.js","sourceRoot":"","sources":["../src/acopf.test.ts"],"names":[],"mappings":"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"}