@cognipilot/rumoca 0.9.4 → 0.9.5
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 +5 -5
- package/modelica_language.js +88 -0
- package/package.json +7 -1
- package/parse_worker.js +1 -2
- package/rumoca_bind_wasm.d.ts +188 -12
- package/rumoca_bind_wasm.js +825 -94
- package/rumoca_bind_wasm_bg.wasm +0 -0
- package/rumoca_bind_wasm_diffsol_bg.wasm +0 -0
- package/rumoca_diffsol.js +2 -2
- package/rumoca_gpu.js +139 -79
- package/rumoca_interactive.js +1098 -0
- package/rumoca_package_meta.json +1 -1
- package/rumoca_runtime.js +164 -0
- package/rumoca_worker.js +307 -87
package/rumoca_worker.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureParsedSourceRootCache,
|
|
3
|
+
normalizeSimulationSolver,
|
|
4
|
+
renderDaeTextWithRuntime,
|
|
5
|
+
simulateModelWithRuntime,
|
|
6
|
+
} from './rumoca_runtime.js';
|
|
7
|
+
|
|
1
8
|
// Web Worker for Rumoca WASM with rayon threading support
|
|
2
9
|
// This worker runs WASM functions that use Atomics.wait (not allowed on main thread)
|
|
3
10
|
|
|
@@ -7,13 +14,34 @@ const cacheBust = workerUrl.searchParams.get('v') || '';
|
|
|
7
14
|
const withCacheBust = (path) =>
|
|
8
15
|
cacheBust ? `${path}?v=${encodeURIComponent(cacheBust)}` : path;
|
|
9
16
|
|
|
17
|
+
// WASM scenario-config commands take JSON-string arguments. Accept either an
|
|
18
|
+
// already-stringified payload field or a structured object from the main thread.
|
|
19
|
+
const jsonArg = (value, emptyDefault = '') =>
|
|
20
|
+
value == null ? emptyDefault : (typeof value === 'string' ? value : JSON.stringify(value));
|
|
21
|
+
|
|
22
|
+
function hasWorkspaceSources(workspaceSources) {
|
|
23
|
+
if (typeof workspaceSources !== 'string') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const trimmed = workspaceSources.trim();
|
|
27
|
+
return Boolean(trimmed && trimmed !== '{}');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function syncWorkspaceSources(workspaceSources) {
|
|
31
|
+
if (typeof sync_workspace_sources !== 'function') {
|
|
32
|
+
throw new Error('Workspace-source simulation not available in this WASM build.');
|
|
33
|
+
}
|
|
34
|
+
sync_workspace_sources(workspaceSources);
|
|
35
|
+
}
|
|
36
|
+
|
|
10
37
|
let init;
|
|
11
38
|
let wasm_init;
|
|
12
39
|
let get_version;
|
|
13
40
|
let get_builtin_targets;
|
|
14
41
|
let compile_to_json;
|
|
15
|
-
let
|
|
16
|
-
let
|
|
42
|
+
let compile_with_workspace_sources;
|
|
43
|
+
let sync_workspace_sources;
|
|
44
|
+
let workspace_effective_source_roots;
|
|
17
45
|
let get_source_root_statuses;
|
|
18
46
|
let get_simulation_models;
|
|
19
47
|
let compile_with_source_roots;
|
|
@@ -22,6 +50,7 @@ let clear_source_root_cache;
|
|
|
22
50
|
let get_source_root_document_count;
|
|
23
51
|
let export_parsed_source_roots_binary;
|
|
24
52
|
let merge_parsed_source_roots_binary;
|
|
53
|
+
let prime_source_root_completion_cache;
|
|
25
54
|
let lsp_diagnostics;
|
|
26
55
|
let lsp_hover;
|
|
27
56
|
let lsp_completion;
|
|
@@ -34,52 +63,30 @@ let lsp_semantic_token_legend;
|
|
|
34
63
|
let list_classes;
|
|
35
64
|
let get_class_info;
|
|
36
65
|
let render_target;
|
|
66
|
+
let scenario_get_simulation_config;
|
|
67
|
+
let scenario_set_simulation_preset;
|
|
68
|
+
let scenario_reset_simulation_preset;
|
|
69
|
+
let scenario_get_visualization_config;
|
|
70
|
+
let scenario_set_visualization_config;
|
|
71
|
+
let scenario_get_codegen_config;
|
|
72
|
+
let scenario_set_codegen_config;
|
|
73
|
+
let scenario_get_source_roots;
|
|
74
|
+
let scenario_set_source_roots;
|
|
75
|
+
let scenario_get_scenario_config;
|
|
76
|
+
let scenario_get_scenario_config_full;
|
|
77
|
+
let scenario_set_scenario_config;
|
|
78
|
+
let scenario_default_scenario_config;
|
|
37
79
|
let simulate_model = null;
|
|
38
|
-
let
|
|
80
|
+
let simulate_model_with_workspace_sources = null;
|
|
39
81
|
let lower_model_to_solve_json = null;
|
|
82
|
+
let model_parameter_metadata = null;
|
|
83
|
+
let model_parameter_metadata_with_workspace_sources = null;
|
|
84
|
+
let model_parameter_metadata_with_source_roots = null;
|
|
85
|
+
let prepare_gpu_simulation = null;
|
|
86
|
+
let wasmRuntimeModule = null;
|
|
40
87
|
let wasmModuleLoaded = false;
|
|
41
88
|
let activeRequestId = null;
|
|
42
89
|
|
|
43
|
-
// Lazy diffsol (stiff/implicit) addon — a separate relaxed-SIMD module, loaded
|
|
44
|
-
// only when a BDF solve is requested, so this worker (and the package) stay
|
|
45
|
-
// universal. Returns the addon's exports, or rejects on browsers without
|
|
46
|
-
// relaxed-SIMD.
|
|
47
|
-
let diffsolAddonPromise = null;
|
|
48
|
-
function loadDiffsolAddon() {
|
|
49
|
-
if (!diffsolAddonPromise) {
|
|
50
|
-
diffsolAddonPromise = (async () => {
|
|
51
|
-
const mod = await import(withCacheBust('./rumoca_bind_wasm_diffsol.js'));
|
|
52
|
-
await mod.default();
|
|
53
|
-
return mod;
|
|
54
|
-
})();
|
|
55
|
-
diffsolAddonPromise.catch(() => {
|
|
56
|
-
diffsolAddonPromise = null;
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return diffsolAddonPromise;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Run a stiff (BDF/diffsol) simulation: the main module lowers the model to a
|
|
63
|
-
// `{ solve_model, t_end, dt }` payload, the addon simulates it. Returns the
|
|
64
|
-
// same JSON string shape as `simulate_model`.
|
|
65
|
-
async function simulateViaDiffsol(source, model, tEnd, dt) {
|
|
66
|
-
if (typeof lower_model_to_solve_json !== 'function') {
|
|
67
|
-
throw new Error('this build cannot lower models for the diffsol addon');
|
|
68
|
-
}
|
|
69
|
-
let addon;
|
|
70
|
-
try {
|
|
71
|
-
addon = await loadDiffsolAddon();
|
|
72
|
-
} catch (err) {
|
|
73
|
-
throw new Error(
|
|
74
|
-
'the stiff (BDF/diffsol) solver needs a browser with WebAssembly '
|
|
75
|
-
+ 'relaxed-SIMD (Chrome 114+, Firefox 120+, Safari 16.4+). '
|
|
76
|
-
+ `Use RK45 instead. (${err && err.message ? err.message : err})`,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
const prep = lower_model_to_solve_json(source, model, tEnd, dt);
|
|
80
|
-
return addon.simulate_solve_model_diffsol(prep);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
90
|
function canUseSharedWasmThreads() {
|
|
84
91
|
return typeof self.crossOriginIsolated === 'boolean'
|
|
85
92
|
&& self.crossOriginIsolated
|
|
@@ -94,8 +101,9 @@ async function loadWasmModule() {
|
|
|
94
101
|
get_version = mod.get_version;
|
|
95
102
|
get_builtin_targets = mod.get_builtin_targets;
|
|
96
103
|
compile_to_json = mod.compile_to_json;
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
compile_with_workspace_sources = mod.compile_with_workspace_sources;
|
|
105
|
+
sync_workspace_sources = mod.sync_workspace_sources;
|
|
106
|
+
workspace_effective_source_roots = mod.workspace_effective_source_roots;
|
|
99
107
|
get_source_root_statuses = mod.get_source_root_statuses;
|
|
100
108
|
get_simulation_models = mod.get_simulation_models;
|
|
101
109
|
compile_with_source_roots = mod.compile_with_source_roots;
|
|
@@ -104,6 +112,7 @@ async function loadWasmModule() {
|
|
|
104
112
|
get_source_root_document_count = mod.get_source_root_document_count;
|
|
105
113
|
export_parsed_source_roots_binary = mod.export_parsed_source_roots_binary;
|
|
106
114
|
merge_parsed_source_roots_binary = mod.merge_parsed_source_roots_binary;
|
|
115
|
+
prime_source_root_completion_cache = mod.prime_source_root_completion_cache;
|
|
107
116
|
lsp_diagnostics = mod.lsp_diagnostics;
|
|
108
117
|
lsp_hover = mod.lsp_hover;
|
|
109
118
|
lsp_completion = mod.lsp_completion;
|
|
@@ -116,28 +125,66 @@ async function loadWasmModule() {
|
|
|
116
125
|
list_classes = mod.list_classes;
|
|
117
126
|
get_class_info = mod.get_class_info;
|
|
118
127
|
render_target = mod.render_target;
|
|
128
|
+
scenario_get_simulation_config = mod.scenario_get_simulation_config;
|
|
129
|
+
scenario_set_simulation_preset = mod.scenario_set_simulation_preset;
|
|
130
|
+
scenario_reset_simulation_preset = mod.scenario_reset_simulation_preset;
|
|
131
|
+
scenario_get_visualization_config = mod.scenario_get_visualization_config;
|
|
132
|
+
scenario_set_visualization_config = mod.scenario_set_visualization_config;
|
|
133
|
+
scenario_get_codegen_config = mod.scenario_get_codegen_config;
|
|
134
|
+
scenario_set_codegen_config = mod.scenario_set_codegen_config;
|
|
135
|
+
scenario_get_source_roots = mod.scenario_get_source_roots;
|
|
136
|
+
scenario_set_source_roots = mod.scenario_set_source_roots;
|
|
137
|
+
scenario_get_scenario_config = mod.scenario_get_scenario_config;
|
|
138
|
+
scenario_get_scenario_config_full = mod.scenario_get_scenario_config_full;
|
|
139
|
+
scenario_set_scenario_config = mod.scenario_set_scenario_config;
|
|
140
|
+
scenario_default_scenario_config = mod.scenario_default_scenario_config;
|
|
119
141
|
if (typeof mod.simulate_model === 'function') {
|
|
120
142
|
simulate_model = mod.simulate_model;
|
|
121
143
|
}
|
|
122
|
-
|
|
123
|
-
simulate_model_with_project_sources = mod.simulate_model_with_project_sources;
|
|
124
|
-
}
|
|
144
|
+
simulate_model_with_workspace_sources = mod.simulate_model_with_workspace_sources;
|
|
125
145
|
if (typeof mod.lower_model_to_solve_json === 'function') {
|
|
126
146
|
lower_model_to_solve_json = mod.lower_model_to_solve_json;
|
|
127
147
|
}
|
|
148
|
+
if (typeof mod.model_parameter_metadata === 'function') {
|
|
149
|
+
model_parameter_metadata = mod.model_parameter_metadata;
|
|
150
|
+
}
|
|
151
|
+
if (typeof mod.model_parameter_metadata_with_workspace_sources === 'function') {
|
|
152
|
+
model_parameter_metadata_with_workspace_sources = mod.model_parameter_metadata_with_workspace_sources;
|
|
153
|
+
}
|
|
154
|
+
if (typeof mod.model_parameter_metadata_with_source_roots === 'function') {
|
|
155
|
+
model_parameter_metadata_with_source_roots = mod.model_parameter_metadata_with_source_roots;
|
|
156
|
+
}
|
|
157
|
+
if (typeof mod.prepare_gpu_simulation === 'function') {
|
|
158
|
+
prepare_gpu_simulation = mod.prepare_gpu_simulation;
|
|
159
|
+
}
|
|
160
|
+
wasmRuntimeModule = {
|
|
161
|
+
compile: compile_to_json,
|
|
162
|
+
lower_model_to_solve_json,
|
|
163
|
+
merge_parsed_source_roots_binary,
|
|
164
|
+
model_parameter_metadata,
|
|
165
|
+
model_parameter_metadata_with_source_roots,
|
|
166
|
+
model_parameter_metadata_with_workspace_sources,
|
|
167
|
+
prime_source_root_completion_cache,
|
|
168
|
+
prepare_gpu_simulation,
|
|
169
|
+
render_target,
|
|
170
|
+
simulate_model,
|
|
171
|
+
};
|
|
128
172
|
wasmModuleLoaded = true;
|
|
129
173
|
}
|
|
130
174
|
|
|
131
175
|
let initialized = false;
|
|
176
|
+
const debugWorkerLogs = false;
|
|
132
177
|
|
|
133
178
|
// Intercept console.log to forward progress messages to main thread
|
|
134
179
|
const originalLog = console.log;
|
|
135
180
|
console.log = function(...args) {
|
|
136
|
-
|
|
181
|
+
if (debugWorkerLogs) {
|
|
182
|
+
originalLog.apply(console, args);
|
|
183
|
+
}
|
|
137
184
|
// Forward WASM progress messages to main thread
|
|
138
185
|
const message = args.join(' ');
|
|
139
186
|
if (message.includes('[WASM]') && message.includes('parsing')) {
|
|
140
|
-
// Extract progress info: "[WASM] wasm::
|
|
187
|
+
// Extract progress info: "[WASM] wasm::workspace: parsing 50/500 (10%)"
|
|
141
188
|
const scopeMatch = message.match(/\[WASM\]\s+([^:]+(?:::[^:]+)*):\s+/);
|
|
142
189
|
const match = message.match(/parsing (\d+)\/(\d+) \((\d+)%\)/);
|
|
143
190
|
if (match) {
|
|
@@ -159,20 +206,20 @@ async function initialize() {
|
|
|
159
206
|
if (initialized) return true;
|
|
160
207
|
|
|
161
208
|
try {
|
|
162
|
-
console.log('[Worker] Loading WASM module...');
|
|
209
|
+
if (debugWorkerLogs) console.log('[Worker] Loading WASM module...');
|
|
163
210
|
await loadWasmModule();
|
|
164
211
|
await init({ module_or_path: withCacheBust('./rumoca_bind_wasm_bg.wasm') });
|
|
165
212
|
|
|
166
213
|
const requestedThreads = navigator.hardwareConcurrency || 4;
|
|
167
214
|
const numThreads = canUseSharedWasmThreads() ? requestedThreads : 0;
|
|
168
215
|
if (numThreads > 0) {
|
|
169
|
-
console.log('[Worker] Initializing thread pool...');
|
|
216
|
+
if (debugWorkerLogs) console.log('[Worker] Initializing thread pool...');
|
|
170
217
|
} else {
|
|
171
|
-
console.warn('[Worker] Shared WASM threads unavailable; using single-thread mode.');
|
|
218
|
+
if (debugWorkerLogs) console.warn('[Worker] Shared WASM threads unavailable; using single-thread mode.');
|
|
172
219
|
}
|
|
173
220
|
await wasm_init(numThreads);
|
|
174
221
|
if (numThreads > 0) {
|
|
175
|
-
console.log(`[Worker] Thread pool initialized with ${numThreads} threads`);
|
|
222
|
+
if (debugWorkerLogs) console.log(`[Worker] Thread pool initialized with ${numThreads} threads`);
|
|
176
223
|
}
|
|
177
224
|
initialized = true;
|
|
178
225
|
return true;
|
|
@@ -211,23 +258,35 @@ self.onmessage = async (e) => {
|
|
|
211
258
|
switch (action) {
|
|
212
259
|
case 'languageCommand': {
|
|
213
260
|
const payload = e.data.payload || {};
|
|
214
|
-
if (typeof
|
|
215
|
-
|
|
261
|
+
if (typeof sync_workspace_sources === 'function' && typeof payload.workspaceSources === 'string') {
|
|
262
|
+
sync_workspace_sources(payload.workspaceSources);
|
|
216
263
|
}
|
|
217
264
|
switch (command) {
|
|
218
265
|
case 'rumoca.language.getSourceRootDocumentCount':
|
|
219
266
|
result = get_source_root_document_count();
|
|
220
267
|
break;
|
|
221
268
|
case 'rumoca.language.diagnostics':
|
|
269
|
+
await ensureParsedSourceRootCache(
|
|
270
|
+
wasmRuntimeModule,
|
|
271
|
+
payload.sourceRootCacheUrl || '',
|
|
272
|
+
);
|
|
222
273
|
result = lsp_diagnostics(payload.source || '');
|
|
223
274
|
break;
|
|
224
275
|
case 'rumoca.language.hover':
|
|
225
276
|
result = lsp_hover(payload.source || '', payload.line, payload.character);
|
|
226
277
|
break;
|
|
227
278
|
case 'rumoca.language.completion':
|
|
279
|
+
await ensureParsedSourceRootCache(
|
|
280
|
+
wasmRuntimeModule,
|
|
281
|
+
payload.sourceRootCacheUrl || '',
|
|
282
|
+
);
|
|
228
283
|
result = lsp_completion(payload.source || '', payload.line, payload.character);
|
|
229
284
|
break;
|
|
230
285
|
case 'rumoca.language.completionWithTiming':
|
|
286
|
+
await ensureParsedSourceRootCache(
|
|
287
|
+
wasmRuntimeModule,
|
|
288
|
+
payload.sourceRootCacheUrl || '',
|
|
289
|
+
);
|
|
231
290
|
result = lsp_completion_with_timing(payload.source || '', payload.line, payload.character);
|
|
232
291
|
break;
|
|
233
292
|
case 'rumoca.language.definition':
|
|
@@ -263,53 +322,206 @@ self.onmessage = async (e) => {
|
|
|
263
322
|
}
|
|
264
323
|
break;
|
|
265
324
|
}
|
|
266
|
-
case '
|
|
325
|
+
case 'scenarioCommand': {
|
|
267
326
|
const payload = e.data.payload || {};
|
|
268
327
|
switch (command) {
|
|
269
|
-
case 'rumoca.
|
|
328
|
+
case 'rumoca.scenario.getSimulationModels':
|
|
270
329
|
result = get_simulation_models(payload.source || '', payload.defaultModel || '');
|
|
271
330
|
break;
|
|
272
|
-
case 'rumoca.
|
|
331
|
+
case 'rumoca.scenario.getSimulationConfig':
|
|
332
|
+
result = scenario_get_simulation_config(
|
|
333
|
+
jsonArg(payload.workspaceSources),
|
|
334
|
+
payload.model || '',
|
|
335
|
+
jsonArg(payload.fallback),
|
|
336
|
+
);
|
|
337
|
+
break;
|
|
338
|
+
case 'rumoca.scenario.setSimulationPreset':
|
|
339
|
+
result = scenario_set_simulation_preset(
|
|
340
|
+
jsonArg(payload.workspaceSources),
|
|
341
|
+
payload.model || '',
|
|
342
|
+
jsonArg(payload.preset, 'null'),
|
|
343
|
+
);
|
|
344
|
+
break;
|
|
345
|
+
case 'rumoca.scenario.resetSimulationPreset':
|
|
346
|
+
result = scenario_reset_simulation_preset(
|
|
347
|
+
jsonArg(payload.workspaceSources),
|
|
348
|
+
payload.model || '',
|
|
349
|
+
);
|
|
350
|
+
break;
|
|
351
|
+
case 'rumoca.scenario.getVisualizationConfig':
|
|
352
|
+
result = scenario_get_visualization_config(
|
|
353
|
+
jsonArg(payload.workspaceSources),
|
|
354
|
+
payload.model || '',
|
|
355
|
+
);
|
|
356
|
+
break;
|
|
357
|
+
case 'rumoca.scenario.setVisualizationConfig':
|
|
358
|
+
result = scenario_set_visualization_config(
|
|
359
|
+
jsonArg(payload.workspaceSources),
|
|
360
|
+
payload.model || '',
|
|
361
|
+
jsonArg(payload.views, 'null'),
|
|
362
|
+
);
|
|
363
|
+
break;
|
|
364
|
+
case 'rumoca.scenario.getCodegenConfig':
|
|
365
|
+
result = scenario_get_codegen_config(
|
|
366
|
+
jsonArg(payload.workspaceSources),
|
|
367
|
+
payload.model || '',
|
|
368
|
+
);
|
|
369
|
+
break;
|
|
370
|
+
case 'rumoca.scenario.setCodegenConfig':
|
|
371
|
+
result = scenario_set_codegen_config(
|
|
372
|
+
jsonArg(payload.workspaceSources),
|
|
373
|
+
payload.model || '',
|
|
374
|
+
jsonArg(payload.config, 'null'),
|
|
375
|
+
);
|
|
376
|
+
break;
|
|
377
|
+
case 'rumoca.scenario.getSourceRoots':
|
|
378
|
+
result = scenario_get_source_roots(
|
|
379
|
+
jsonArg(payload.workspaceSources),
|
|
380
|
+
payload.model || '',
|
|
381
|
+
payload.task || '',
|
|
382
|
+
);
|
|
383
|
+
break;
|
|
384
|
+
case 'rumoca.scenario.setSourceRoots':
|
|
385
|
+
result = scenario_set_source_roots(
|
|
386
|
+
jsonArg(payload.workspaceSources),
|
|
387
|
+
payload.model || '',
|
|
388
|
+
jsonArg(payload.config, 'null'),
|
|
389
|
+
);
|
|
390
|
+
break;
|
|
391
|
+
case 'rumoca.scenario.getScenarioConfig':
|
|
392
|
+
result = scenario_get_scenario_config(
|
|
393
|
+
jsonArg(payload.workspaceSources),
|
|
394
|
+
payload.path || payload.uri || '',
|
|
395
|
+
);
|
|
396
|
+
break;
|
|
397
|
+
case 'rumoca.scenario.getScenarioConfigFull':
|
|
398
|
+
result = scenario_get_scenario_config_full(
|
|
399
|
+
jsonArg(payload.workspaceSources),
|
|
400
|
+
payload.path || payload.uri || '',
|
|
401
|
+
);
|
|
402
|
+
break;
|
|
403
|
+
case 'rumoca.scenario.setScenarioConfig':
|
|
404
|
+
result = scenario_set_scenario_config(
|
|
405
|
+
payload.path || payload.uri || '',
|
|
406
|
+
jsonArg(payload.config, 'null'),
|
|
407
|
+
);
|
|
408
|
+
break;
|
|
409
|
+
case 'rumoca.scenario.defaultScenarioConfig':
|
|
410
|
+
result = scenario_default_scenario_config(
|
|
411
|
+
jsonArg(payload.workspaceSources),
|
|
412
|
+
payload.model || '',
|
|
413
|
+
payload.task || '',
|
|
414
|
+
);
|
|
415
|
+
break;
|
|
416
|
+
case 'rumoca.scenario.startSimulation':
|
|
273
417
|
if (!simulate_model) {
|
|
274
418
|
throw new Error('Simulation not available in this WASM build. Rebuild with rumoca-sim (diffsol feature enabled).');
|
|
275
419
|
}
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
420
|
+
if (typeof payload.sourceRoots === 'string' && payload.sourceRoots.trim() && payload.sourceRoots.trim() !== '{}') {
|
|
421
|
+
load_source_roots(payload.sourceRoots);
|
|
422
|
+
}
|
|
423
|
+
{
|
|
424
|
+
const solver = normalizeSimulationSolver(payload.solver);
|
|
425
|
+
const useWorkspaceSources = hasWorkspaceSources(payload.workspaceSources);
|
|
426
|
+
const parameterOverrides = payload.parameterOverrides && typeof payload.parameterOverrides === 'object'
|
|
427
|
+
? payload.parameterOverrides
|
|
428
|
+
: {};
|
|
429
|
+
if (useWorkspaceSources && solver === 'bdf') {
|
|
430
|
+
syncWorkspaceSources(payload.workspaceSources);
|
|
431
|
+
result = JSON.stringify(await simulateModelWithRuntime({
|
|
432
|
+
wasm: wasmRuntimeModule,
|
|
433
|
+
pkgBase: './',
|
|
434
|
+
source: payload.source || '',
|
|
435
|
+
modelName: payload.modelName || 'Model',
|
|
436
|
+
tEnd: payload.tEnd || 1.0,
|
|
437
|
+
dt: payload.dt || 0,
|
|
438
|
+
solver,
|
|
439
|
+
sourceRootCacheUrl: payload.sourceRootCacheUrl || '',
|
|
440
|
+
parameterOverrides,
|
|
441
|
+
}));
|
|
442
|
+
} else if (useWorkspaceSources) {
|
|
443
|
+
if (typeof simulate_model_with_workspace_sources !== 'function') {
|
|
444
|
+
throw new Error('Workspace-source simulation not available in this WASM build.');
|
|
445
|
+
}
|
|
446
|
+
result = simulate_model_with_workspace_sources(
|
|
447
|
+
payload.source || '',
|
|
448
|
+
payload.modelName || 'Model',
|
|
449
|
+
payload.workspaceSources,
|
|
450
|
+
payload.tEnd || 1.0,
|
|
451
|
+
payload.dt || 0,
|
|
452
|
+
solver,
|
|
453
|
+
jsonArg(parameterOverrides, '{}'),
|
|
454
|
+
);
|
|
455
|
+
} else {
|
|
456
|
+
result = JSON.stringify(await simulateModelWithRuntime({
|
|
457
|
+
wasm: wasmRuntimeModule,
|
|
458
|
+
pkgBase: './',
|
|
459
|
+
source: payload.source || '',
|
|
460
|
+
modelName: payload.modelName || 'Model',
|
|
461
|
+
tEnd: payload.tEnd || 1.0,
|
|
462
|
+
dt: payload.dt || 0,
|
|
463
|
+
solver,
|
|
464
|
+
sourceRootCacheUrl: payload.sourceRootCacheUrl || '',
|
|
465
|
+
parameterOverrides,
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
break;
|
|
470
|
+
case 'rumoca.model.parameterMetadata':
|
|
471
|
+
if (typeof payload.sourceRoots === 'string' && payload.sourceRoots.trim() && payload.sourceRoots.trim() !== '{}') {
|
|
472
|
+
if (typeof model_parameter_metadata_with_source_roots !== 'function') {
|
|
473
|
+
throw new Error('Source-root parameter metadata is not available in this WASM build.');
|
|
474
|
+
}
|
|
475
|
+
result = model_parameter_metadata_with_source_roots(
|
|
282
476
|
payload.source || '',
|
|
283
477
|
payload.modelName || 'Model',
|
|
284
|
-
payload.
|
|
285
|
-
payload.dt || 0,
|
|
478
|
+
payload.sourceRoots,
|
|
286
479
|
);
|
|
287
|
-
} else if (
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
) {
|
|
293
|
-
result = simulate_model_with_project_sources(
|
|
480
|
+
} else if (hasWorkspaceSources(payload.workspaceSources)) {
|
|
481
|
+
if (typeof model_parameter_metadata_with_workspace_sources !== 'function') {
|
|
482
|
+
throw new Error('Workspace parameter metadata is not available in this WASM build.');
|
|
483
|
+
}
|
|
484
|
+
result = model_parameter_metadata_with_workspace_sources(
|
|
294
485
|
payload.source || '',
|
|
295
486
|
payload.modelName || 'Model',
|
|
296
|
-
payload.
|
|
297
|
-
payload.tEnd || 1.0,
|
|
298
|
-
payload.dt || 0,
|
|
299
|
-
payload.solver || 'auto',
|
|
487
|
+
payload.workspaceSources,
|
|
300
488
|
);
|
|
301
489
|
} else {
|
|
302
|
-
|
|
490
|
+
if (typeof model_parameter_metadata !== 'function') {
|
|
491
|
+
throw new Error('Parameter metadata is not available in this WASM build.');
|
|
492
|
+
}
|
|
493
|
+
result = model_parameter_metadata(
|
|
303
494
|
payload.source || '',
|
|
304
495
|
payload.modelName || 'Model',
|
|
305
|
-
payload.tEnd || 1.0,
|
|
306
|
-
payload.dt || 0,
|
|
307
|
-
payload.solver || 'auto',
|
|
308
496
|
);
|
|
309
497
|
}
|
|
310
498
|
break;
|
|
499
|
+
case 'rumoca.scenario.renderDaeText':
|
|
500
|
+
result = await renderDaeTextWithRuntime({
|
|
501
|
+
wasm: wasmRuntimeModule,
|
|
502
|
+
source: payload.source || '',
|
|
503
|
+
modelName: payload.modelName || 'Model',
|
|
504
|
+
sourceRootCacheUrl: payload.sourceRootCacheUrl || '',
|
|
505
|
+
});
|
|
506
|
+
break;
|
|
507
|
+
case 'rumoca.scenario.prepareGpuSimulation':
|
|
508
|
+
await ensureParsedSourceRootCache(
|
|
509
|
+
wasmRuntimeModule,
|
|
510
|
+
payload.sourceRootCacheUrl || '',
|
|
511
|
+
);
|
|
512
|
+
if (typeof payload.source !== 'string') {
|
|
513
|
+
throw new Error('prepareGpuSimulation requires source text');
|
|
514
|
+
}
|
|
515
|
+
if (typeof prepare_gpu_simulation !== 'function') {
|
|
516
|
+
throw new Error('prepare_gpu_simulation missing in this WASM build');
|
|
517
|
+
}
|
|
518
|
+
result = prepare_gpu_simulation(
|
|
519
|
+
payload.source || '',
|
|
520
|
+
payload.modelName || 'Model',
|
|
521
|
+
);
|
|
522
|
+
break;
|
|
311
523
|
default:
|
|
312
|
-
throw new Error(`Unknown
|
|
524
|
+
throw new Error(`Unknown scenario command: ${command}`);
|
|
313
525
|
}
|
|
314
526
|
break;
|
|
315
527
|
}
|
|
@@ -325,11 +537,11 @@ self.onmessage = async (e) => {
|
|
|
325
537
|
case 'rumoca.workspace.compile':
|
|
326
538
|
result = compile_to_json(payload.source || '', payload.modelName || 'Model');
|
|
327
539
|
break;
|
|
328
|
-
case 'rumoca.workspace.
|
|
329
|
-
result =
|
|
540
|
+
case 'rumoca.workspace.compileWithWorkspaceSources':
|
|
541
|
+
result = compile_with_workspace_sources(
|
|
330
542
|
payload.source || '',
|
|
331
543
|
payload.modelName || 'Model',
|
|
332
|
-
payload.
|
|
544
|
+
payload.workspaceSources || '{}',
|
|
333
545
|
);
|
|
334
546
|
break;
|
|
335
547
|
case 'rumoca.workspace.compileWithSourceRoots':
|
|
@@ -345,6 +557,15 @@ self.onmessage = async (e) => {
|
|
|
345
557
|
case 'rumoca.workspace.getSourceRootStatuses':
|
|
346
558
|
result = get_source_root_statuses();
|
|
347
559
|
break;
|
|
560
|
+
case 'rumoca.workspace.effectiveSourceRoots':
|
|
561
|
+
if (typeof workspace_effective_source_roots !== 'function') {
|
|
562
|
+
throw new Error('workspace_effective_source_roots missing in this WASM build');
|
|
563
|
+
}
|
|
564
|
+
result = workspace_effective_source_roots(
|
|
565
|
+
payload.workspaceSources || '{}',
|
|
566
|
+
payload.focusPath || payload.path || '',
|
|
567
|
+
);
|
|
568
|
+
break;
|
|
348
569
|
case 'rumoca.workspace.exportParsedSourceRootsBinary':
|
|
349
570
|
result = export_parsed_source_roots_binary(payload.urisJson || '[]');
|
|
350
571
|
break;
|
|
@@ -388,7 +609,6 @@ self.onmessage = async (e) => {
|
|
|
388
609
|
self.postMessage({ id, success: true, result });
|
|
389
610
|
} catch (e) {
|
|
390
611
|
activeRequestId = null;
|
|
391
|
-
console.error('[Worker] Error:', e);
|
|
392
612
|
self.postMessage({ id, error: e.message || String(e) });
|
|
393
613
|
}
|
|
394
614
|
};
|