@neuroverseos/nv-sim 0.1.9 → 0.1.11

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 (38) hide show
  1. package/README.md +187 -535
  2. package/connectors/nv_mirofish_wrapper.py +841 -0
  3. package/connectors/nv_scienceclaw_wrapper.py +453 -0
  4. package/dist/adapters/scienceclaw.js +52 -2
  5. package/dist/assets/index-CH_VswRM.css +1 -0
  6. package/dist/assets/index-sT4b_z7w.js +686 -0
  7. package/dist/assets/{reportEngine-D2ZrMny8.js → reportEngine-Bu8bB5Yq.js} +1 -1
  8. package/dist/connectors/nv-scienceclaw-post.js +363 -0
  9. package/dist/engine/aiProvider.js +82 -3
  10. package/dist/engine/analyzer.js +12 -24
  11. package/dist/engine/cli.js +89 -114
  12. package/dist/engine/dynamicsGovernance.js +4 -0
  13. package/dist/engine/fullGovernedLoop.js +16 -1
  14. package/dist/engine/goalEngine.js +3 -4
  15. package/dist/engine/governance.js +18 -0
  16. package/dist/engine/index.js +19 -28
  17. package/dist/engine/intentTranslator.js +281 -0
  18. package/dist/engine/liveAdapter.js +100 -18
  19. package/dist/engine/liveVisualizer.js +2071 -1023
  20. package/dist/engine/primeRadiant.js +2 -8
  21. package/dist/engine/reasoningEngine.js +2 -7
  22. package/dist/engine/scenarioCapsule.js +5 -5
  23. package/dist/engine/swarmSimulation.js +1 -9
  24. package/dist/engine/universalAdapter.js +371 -0
  25. package/dist/engine/worldBridge.js +22 -8
  26. package/dist/index.html +2 -2
  27. package/dist/lib/reasoningEngine.js +17 -1
  28. package/dist/lib/simulationAdapter.js +11 -11
  29. package/dist/lib/swarmParser.js +1 -1
  30. package/dist/runtime/govern.js +160 -7
  31. package/dist/runtime/index.js +1 -4
  32. package/dist/runtime/types.js +91 -0
  33. package/package.json +23 -6
  34. package/dist/adapters/mirofish.js +0 -461
  35. package/dist/assets/index-B64NuIXu.css +0 -1
  36. package/dist/assets/index-BMkPevVr.js +0 -532
  37. package/dist/assets/mirotir-logo-DUexumBH.svg +0 -185
  38. package/dist/engine/mirofish.js +0 -295
@@ -1,185 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 320" fill="none">
2
- <!--
3
- Mirotir Logo
4
-
5
- Concept: School of fish (swarm) forming a circular cluster
6
- with a horizontal line of teal fish cutting through — the
7
- "reasoning line" that makes sense of the crowd.
8
-
9
- Dark blue fish = the simulation (MiroFish, the crowd)
10
- Teal fish line = the reasoning (Echelon, the brain)
11
- Breakaway fish = the decision emerging from analysis
12
-
13
- Typeface: Bold geometric sans-serif (Neue Haas Grotesk style)
14
- Uniform stroke widths, clean, constructed, modern.
15
- -->
16
-
17
- <defs>
18
- <!-- Fish shape template - dark blue swarm -->
19
- <g id="fish-dark">
20
- <ellipse rx="10" ry="6" fill="#1B5E7B"/>
21
- <polygon points="10,-5 17,0 10,5" fill="#1B5E7B"/>
22
- </g>
23
- <!-- Fish shape template - dark blue small -->
24
- <g id="fish-dark-sm">
25
- <ellipse rx="7" ry="4" fill="#1B5E7B"/>
26
- <polygon points="7,-3.5 12,0 7,3.5" fill="#1B5E7B"/>
27
- </g>
28
- <!-- Fish shape template - teal reasoning line -->
29
- <g id="fish-teal">
30
- <ellipse rx="11" ry="7" fill="#5BC0BE"/>
31
- <polygon points="11,-5.5 19,0 11,5.5" fill="#5BC0BE"/>
32
- <circle cx="-3" cy="-1" r="1.5" fill="white"/>
33
- </g>
34
- <!-- Fish shape template - teal small -->
35
- <g id="fish-teal-sm">
36
- <ellipse rx="8" ry="5" fill="#6FDBD8"/>
37
- <polygon points="8,-4 14,0 8,4" fill="#6FDBD8"/>
38
- <circle cx="-2" cy="-1" r="1.2" fill="white"/>
39
- </g>
40
- </defs>
41
-
42
- <!-- ================================ -->
43
- <!-- SWARM CLUSTER (circular school) -->
44
- <!-- ================================ -->
45
-
46
- <!-- Top arc of swarm -->
47
- <use href="#fish-dark" x="100" y="55" transform="rotate(-5,100,55)"/>
48
- <use href="#fish-dark-sm" x="122" y="48" transform="rotate(8,122,48)"/>
49
- <use href="#fish-dark" x="145" y="42" transform="rotate(-3,145,42)"/>
50
- <use href="#fish-dark-sm" x="170" y="38" transform="rotate(12,170,38)"/>
51
- <use href="#fish-dark" x="192" y="44" transform="rotate(-8,192,44)"/>
52
- <use href="#fish-dark-sm" x="215" y="50" transform="rotate(5,215,50)"/>
53
-
54
- <!-- Upper middle row -->
55
- <use href="#fish-dark" x="78" y="75" transform="rotate(10,78,75)"/>
56
- <use href="#fish-dark" x="108" y="72" transform="rotate(-6,108,72)"/>
57
- <use href="#fish-dark-sm" x="135" y="68" transform="rotate(3,135,68)"/>
58
- <use href="#fish-dark" x="160" y="65" transform="rotate(-10,160,65)"/>
59
- <use href="#fish-dark-sm" x="185" y="62" transform="rotate(7,185,62)"/>
60
- <use href="#fish-dark" x="208" y="68" transform="rotate(-4,208,68)"/>
61
- <use href="#fish-dark-sm" x="228" y="75" transform="rotate(9,228,75)"/>
62
-
63
- <!-- Middle-upper row -->
64
- <use href="#fish-dark-sm" x="68" y="95" transform="rotate(-7,68,95)"/>
65
- <use href="#fish-dark" x="92" y="90" transform="rotate(4,92,90)"/>
66
- <use href="#fish-dark" x="118" y="88" transform="rotate(-2,118,88)"/>
67
- <use href="#fish-dark-sm" x="145" y="85" transform="rotate(11,145,85)"/>
68
- <use href="#fish-dark" x="172" y="82" transform="rotate(-9,172,82)"/>
69
- <use href="#fish-dark" x="198" y="86" transform="rotate(6,198,86)"/>
70
- <use href="#fish-dark-sm" x="222" y="92" transform="rotate(-5,222,92)"/>
71
- <use href="#fish-dark" x="242" y="98" transform="rotate(3,242,98)"/>
72
-
73
- <!-- Pre-reasoning row -->
74
- <use href="#fish-dark" x="58" y="112" transform="rotate(8,58,112)"/>
75
- <use href="#fish-dark-sm" x="85" y="108" transform="rotate(-3,85,108)"/>
76
- <use href="#fish-dark" x="112" y="105" transform="rotate(5,112,105)"/>
77
- <use href="#fish-dark" x="140" y="103" transform="rotate(-7,140,103)"/>
78
- <use href="#fish-dark-sm" x="168" y="100" transform="rotate(2,168,100)"/>
79
- <use href="#fish-dark" x="195" y="104" transform="rotate(-11,195,104)"/>
80
- <use href="#fish-dark-sm" x="218" y="108" transform="rotate(4,218,108)"/>
81
- <use href="#fish-dark" x="240" y="115" transform="rotate(-6,240,115)"/>
82
-
83
- <!-- ================================ -->
84
- <!-- REASONING LINE (teal fish) -->
85
- <!-- The line that cuts through -->
86
- <!-- ================================ -->
87
-
88
- <use href="#fish-teal" x="32" y="132"/>
89
- <use href="#fish-teal" x="65" y="130" transform="rotate(-2,65,130)"/>
90
- <use href="#fish-teal" x="100" y="130"/>
91
- <use href="#fish-teal" x="135" y="129" transform="rotate(2,135,129)"/>
92
- <use href="#fish-teal" x="170" y="130"/>
93
- <use href="#fish-teal" x="205" y="130" transform="rotate(-1,205,130)"/>
94
- <use href="#fish-teal" x="240" y="131" transform="rotate(1,240,131)"/>
95
-
96
- <!-- Breakaway fish — the decision emerging -->
97
- <use href="#fish-teal-sm" x="282" y="130" transform="rotate(-3,282,130)"/>
98
-
99
- <!-- ================================ -->
100
- <!-- SWARM CLUSTER (below reasoning) -->
101
- <!-- ================================ -->
102
-
103
- <!-- Post-reasoning row -->
104
- <use href="#fish-dark" x="60" y="152" transform="rotate(-4,60,152)"/>
105
- <use href="#fish-dark-sm" x="88" y="148" transform="rotate(7,88,148)"/>
106
- <use href="#fish-dark" x="115" y="150" transform="rotate(-9,115,150)"/>
107
- <use href="#fish-dark" x="142" y="153" transform="rotate(3,142,153)"/>
108
- <use href="#fish-dark-sm" x="170" y="155" transform="rotate(-6,170,155)"/>
109
- <use href="#fish-dark" x="198" y="152" transform="rotate(5,198,152)"/>
110
- <use href="#fish-dark-sm" x="222" y="148" transform="rotate(-2,222,148)"/>
111
- <use href="#fish-dark" x="245" y="152" transform="rotate(8,245,152)"/>
112
-
113
- <!-- Lower-middle row -->
114
- <use href="#fish-dark-sm" x="72" y="170" transform="rotate(6,72,170)"/>
115
- <use href="#fish-dark" x="98" y="168" transform="rotate(-8,98,168)"/>
116
- <use href="#fish-dark" x="128" y="172" transform="rotate(4,128,172)"/>
117
- <use href="#fish-dark-sm" x="155" y="175" transform="rotate(-5,155,175)"/>
118
- <use href="#fish-dark" x="180" y="172" transform="rotate(10,180,172)"/>
119
- <use href="#fish-dark-sm" x="205" y="168" transform="rotate(-3,205,168)"/>
120
- <use href="#fish-dark" x="230" y="170" transform="rotate(7,230,170)"/>
121
-
122
- <!-- Lower row -->
123
- <use href="#fish-dark" x="85" y="192" transform="rotate(-6,85,192)"/>
124
- <use href="#fish-dark-sm" x="112" y="190" transform="rotate(9,112,190)"/>
125
- <use href="#fish-dark" x="138" y="195" transform="rotate(-4,138,195)"/>
126
- <use href="#fish-dark" x="165" y="192" transform="rotate(2,165,192)"/>
127
- <use href="#fish-dark-sm" x="190" y="188" transform="rotate(-7,190,188)"/>
128
- <use href="#fish-dark" x="215" y="192" transform="rotate(5,215,192)"/>
129
-
130
- <!-- Bottom arc -->
131
- <use href="#fish-dark-sm" x="100" y="210" transform="rotate(3,100,210)"/>
132
- <use href="#fish-dark" x="128" y="212" transform="rotate(-8,128,212)"/>
133
- <use href="#fish-dark-sm" x="155" y="215" transform="rotate(6,155,215)"/>
134
- <use href="#fish-dark" x="182" y="212" transform="rotate(-2,182,212)"/>
135
- <use href="#fish-dark-sm" x="205" y="208" transform="rotate(4,205,208)"/>
136
-
137
- <!-- ================================ -->
138
- <!-- WORDMARK: MIROTIR -->
139
- <!-- Bold geometric sans-serif -->
140
- <!-- Neue Haas Grotesk style -->
141
- <!-- Uniform stroke, constructed -->
142
- <!-- ================================ -->
143
-
144
- <g transform="translate(340, 100)">
145
- <!-- M -->
146
- <path d="M0,130 L0,0 L8,0 L8,130 L0,130 Z" fill="#1B5E7B"/>
147
- <path d="M8,0 L36,50 L36,42 L14,0 L8,0 Z" fill="#1B5E7B"/>
148
- <path d="M36,42 L36,50 L64,0 L58,0 L36,42 Z" fill="#1B5E7B"/>
149
- <path d="M58,0 L66,0 L66,130 L58,130 Z" fill="#1B5E7B"/>
150
-
151
- <!-- I -->
152
- <path d="M82,0 L90,0 L90,130 L82,130 Z" fill="#1B5E7B"/>
153
-
154
- <!-- R -->
155
- <path d="M106,0 L114,0 L114,130 L106,130 Z" fill="#1B5E7B"/>
156
- <path d="M114,0 L148,0 Q162,0 162,22 Q162,44 148,44 L114,44 L114,36 L146,36 Q154,36 154,22 Q154,8 146,8 L114,8 Z" fill="#1B5E7B"/>
157
- <path d="M134,44 L164,130 L155,130 L126,46 Z" fill="#1B5E7B"/>
158
-
159
- <!-- O -->
160
- <path d="M178,0 L214,0 Q232,0 232,18 L232,112 Q232,130 214,130 L178,130 Q160,130 160,112 L160,18 Q160,0 178,0 Z M178,8 Q168,8 168,18 L168,112 Q168,122 178,122 L214,122 Q224,122 224,112 L224,18 Q224,8 214,8 Z" fill="#1B5E7B"/>
161
-
162
- <!-- T -->
163
- <path d="M244,0 L302,0 L302,8 L277,8 L277,130 L269,130 L269,8 L244,8 Z" fill="#1B5E7B"/>
164
-
165
- <!-- I -->
166
- <path d="M314,0 L322,0 L322,130 L314,130 Z" fill="#1B5E7B"/>
167
-
168
- <!-- R -->
169
- <path d="M338,0 L346,0 L346,130 L338,130 Z" fill="#1B5E7B"/>
170
- <path d="M346,0 L380,0 Q394,0 394,22 Q394,44 380,44 L346,44 L346,36 L378,36 Q386,36 386,22 Q386,8 378,8 L346,8 Z" fill="#1B5E7B"/>
171
- <path d="M366,44 L396,130 L387,130 L358,46 Z" fill="#1B5E7B"/>
172
- </g>
173
-
174
- <!-- ================================ -->
175
- <!-- TAGLINE -->
176
- <!-- ================================ -->
177
-
178
- <text x="340" y="268"
179
- font-family="'Helvetica Neue', 'Arial', sans-serif"
180
- font-size="14"
181
- font-weight="400"
182
- letter-spacing="3.5"
183
- fill="#5BC0BE">EXPLORE DECISIONS BEFORE REALITY DOES</text>
184
-
185
- </svg>
@@ -1,295 +0,0 @@
1
- "use strict";
2
- /**
3
- * MiroFish Integration Adapter
4
- *
5
- * Connects Mirotir to MiroFish swarm simulations as an EXTERNAL SERVICE.
6
- *
7
- * POSITIONING:
8
- * MiroFish shows what might happen → the spectacle
9
- * Mirotir helps you decide what to do → the brain
10
- *
11
- * "MiroFish simulates the crowd. Mirotir reasons about the decision."
12
- *
13
- * LICENSE COMPLIANCE:
14
- * MiroFish is called as an external service via its REST API.
15
- * We do NOT embed, copy, or redistribute MiroFish code.
16
- * We do NOT use MiroFish internals, algorithms, or data structures.
17
- * The integration is purely through the public API contract.
18
- * This is the same relationship as using Stripe's API — we call it, we don't own it.
19
- *
20
- * ARCHITECTURE:
21
- * Scenario → Echelon reasoning → strategies generated
22
- * ↓
23
- * MiroFish simulation runs
24
- * ↓
25
- * Echelon evaluates outcomes
26
- *
27
- * MiroFish = world engine (emergent behavior, swarms, crowds)
28
- * Echelon = decision engine (structured reasoning, recommendations)
29
- *
30
- * FALLBACK:
31
- * When MiroFish is not available, we use Echelon's native
32
- * lightweight reaction model (swarmSimulation.ts).
33
- * The API contract is the same either way.
34
- */
35
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
36
- if (k2 === undefined) k2 = k;
37
- var desc = Object.getOwnPropertyDescriptor(m, k);
38
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
39
- desc = { enumerable: true, get: function() { return m[k]; } };
40
- }
41
- Object.defineProperty(o, k2, desc);
42
- }) : (function(o, m, k, k2) {
43
- if (k2 === undefined) k2 = k;
44
- o[k2] = m[k];
45
- }));
46
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
47
- Object.defineProperty(o, "default", { enumerable: true, value: v });
48
- }) : function(o, v) {
49
- o["default"] = v;
50
- });
51
- var __importStar = (this && this.__importStar) || (function () {
52
- var ownKeys = function(o) {
53
- ownKeys = Object.getOwnPropertyNames || function (o) {
54
- var ar = [];
55
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
56
- return ar;
57
- };
58
- return ownKeys(o);
59
- };
60
- return function (mod) {
61
- if (mod && mod.__esModule) return mod;
62
- var result = {};
63
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
64
- __setModuleDefault(result, mod);
65
- return result;
66
- };
67
- })();
68
- Object.defineProperty(exports, "__esModule", { value: true });
69
- exports.MiroFishError = exports.MiroFishClient = exports.DEFAULT_MIROFISH_CONFIG = void 0;
70
- exports.stakeholdersToMiroFishAgents = stakeholdersToMiroFishAgents;
71
- exports.miroFishResultToSwarmResult = miroFishResultToSwarmResult;
72
- exports.buildMiroFishRequest = buildMiroFishRequest;
73
- exports.configureMiroFish = configureMiroFish;
74
- exports.getMiroFishClient = getMiroFishClient;
75
- exports.runUnifiedSimulation = runUnifiedSimulation;
76
- /**
77
- * Default MiroFish configuration.
78
- * Assumes local Docker container on default port.
79
- */
80
- exports.DEFAULT_MIROFISH_CONFIG = {
81
- endpoint: "http://localhost:8080",
82
- timeout: 30000,
83
- fallbackToNative: true,
84
- };
85
- // ============================================
86
- // MIROFISH CLIENT
87
- // ============================================
88
- /**
89
- * MiroFish API client.
90
- * Calls MiroFish as an external service via REST API.
91
- */
92
- class MiroFishClient {
93
- config;
94
- constructor(config) {
95
- this.config = { ...exports.DEFAULT_MIROFISH_CONFIG, ...config };
96
- }
97
- /**
98
- * Check if the MiroFish service is available.
99
- */
100
- async isAvailable() {
101
- try {
102
- const response = await fetch(`${this.config.endpoint}/health`, {
103
- method: "GET",
104
- signal: AbortSignal.timeout(5000),
105
- });
106
- return response.ok;
107
- }
108
- catch {
109
- return false;
110
- }
111
- }
112
- /**
113
- * Run a simulation against the MiroFish service.
114
- */
115
- async simulate(request) {
116
- const headers = {
117
- "Content-Type": "application/json",
118
- };
119
- if (this.config.apiKey) {
120
- headers["Authorization"] = `Bearer ${this.config.apiKey}`;
121
- }
122
- const response = await fetch(`${this.config.endpoint}/simulate`, {
123
- method: "POST",
124
- headers,
125
- body: JSON.stringify(request),
126
- signal: AbortSignal.timeout(this.config.timeout ?? 30000),
127
- });
128
- if (!response.ok) {
129
- throw new MiroFishError(`MiroFish simulation failed: ${response.status} ${response.statusText}`, response.status);
130
- }
131
- return response.json();
132
- }
133
- /**
134
- * Get the MiroFish service configuration.
135
- */
136
- getConfig() {
137
- return this.config;
138
- }
139
- }
140
- exports.MiroFishClient = MiroFishClient;
141
- /**
142
- * MiroFish-specific error.
143
- */
144
- class MiroFishError extends Error {
145
- statusCode;
146
- constructor(message, statusCode) {
147
- super(message);
148
- this.name = "MiroFishError";
149
- this.statusCode = statusCode;
150
- }
151
- }
152
- exports.MiroFishError = MiroFishError;
153
- // ============================================
154
- // TRANSLATION LAYER
155
- // ============================================
156
- /**
157
- * Convert Mirotir stakeholders to MiroFish agents.
158
- */
159
- function stakeholdersToMiroFishAgents(stakeholders) {
160
- return stakeholders.map((s) => ({
161
- id: s.id,
162
- role: s.description ?? s.id,
163
- disposition: s.disposition,
164
- priorities: s.priorities,
165
- }));
166
- }
167
- /**
168
- * Convert MiroFish simulation results to Mirotir's SwarmSimulationResult format.
169
- *
170
- * This is the key translation — MiroFish provides the raw emergent behavior,
171
- * and we normalize it into the format that Echelon's reasoning engine consumes.
172
- *
173
- * MiroFish shows WHAT happens.
174
- * Echelon reasons about WHAT IT MEANS.
175
- */
176
- function miroFishResultToSwarmResult(mfResult) {
177
- // Convert MiroFish steps to SwarmRounds
178
- const rounds = mfResult.steps.map((step) => {
179
- const reactions = step.agent_actions.map((action) => ({
180
- stakeholder_id: action.agent_id,
181
- reaction: action.action,
182
- confidence: action.confidence,
183
- impact: action.sentiment,
184
- trigger: action.reasoning ?? "MiroFish emergent behavior",
185
- }));
186
- return {
187
- round: step.step,
188
- reactions,
189
- emergent_dynamics: step.system_events,
190
- };
191
- });
192
- // Determine trajectory from MiroFish final state
193
- let trajectory;
194
- if (mfResult.final_state.convergence && mfResult.final_state.stability > 0.7) {
195
- trajectory = "converging";
196
- }
197
- else if (mfResult.final_state.convergence) {
198
- trajectory = "stabilizing";
199
- }
200
- else if (mfResult.final_state.stability < 0.3) {
201
- trajectory = "escalating";
202
- }
203
- else {
204
- trajectory = "diverging";
205
- }
206
- // Extract inflection points from emergent patterns
207
- const inflection_points = mfResult.emergent_patterns ?? [
208
- "MiroFish simulation completed — see rounds for detailed agent behaviors",
209
- ];
210
- return {
211
- rounds,
212
- trajectory,
213
- inflection_points,
214
- };
215
- }
216
- /**
217
- * Build a MiroFish simulation request from Mirotir inputs.
218
- */
219
- function buildMiroFishRequest(scenario, stakeholders, config) {
220
- return {
221
- scenario,
222
- agents: stakeholdersToMiroFishAgents(config.simulate_stakeholders
223
- ? stakeholders.filter((s) => config.simulate_stakeholders.includes(s.id))
224
- : stakeholders),
225
- steps: config.rounds ?? 3,
226
- parameters: {
227
- model: config.reaction_model ?? "mixed",
228
- pressure: 0.5,
229
- allow_coalitions: true,
230
- },
231
- };
232
- }
233
- /**
234
- * Singleton MiroFish client instance.
235
- * Configured via setMiroFishConfig().
236
- */
237
- let miroFishClient = null;
238
- /**
239
- * Configure the MiroFish connection.
240
- * Call this at startup if MiroFish is available.
241
- */
242
- function configureMiroFish(config) {
243
- miroFishClient = new MiroFishClient(config);
244
- }
245
- /**
246
- * Get the current MiroFish client (if configured).
247
- */
248
- function getMiroFishClient() {
249
- return miroFishClient;
250
- }
251
- /**
252
- * Run simulation through unified interface.
253
- *
254
- * Strategy:
255
- * 1. If MiroFish is configured and available → use it
256
- * 2. If MiroFish fails and fallback is enabled → use Echelon-native
257
- * 3. If MiroFish is not configured → use Echelon-native
258
- */
259
- async function runUnifiedSimulation(scenario, stakeholders, paths, swarmConfig, miroFishOverride) {
260
- // Determine which client to use
261
- const client = miroFishOverride
262
- ? new MiroFishClient(miroFishOverride)
263
- : miroFishClient;
264
- // Try MiroFish first if configured
265
- if (client) {
266
- try {
267
- const available = await client.isAvailable();
268
- if (available) {
269
- const request = buildMiroFishRequest(scenario, stakeholders, swarmConfig);
270
- const mfResult = await client.simulate(request);
271
- const result = miroFishResultToSwarmResult(mfResult);
272
- return {
273
- result,
274
- source: "mirofish",
275
- mirofish_simulation_id: mfResult.simulation_id,
276
- };
277
- }
278
- }
279
- catch (error) {
280
- const fallback = miroFishOverride?.fallbackToNative ?? client.getConfig().fallbackToNative ?? true;
281
- if (!fallback) {
282
- throw error;
283
- }
284
- // Log and fall through to native simulation
285
- console.warn("[MiroFish] Simulation failed, falling back to Echelon-native:", error instanceof Error ? error.message : "Unknown error");
286
- }
287
- }
288
- // Fall back to Echelon-native simulation
289
- const { runSwarmSimulation } = await Promise.resolve().then(() => __importStar(require("./swarmSimulation")));
290
- const result = await runSwarmSimulation(scenario, stakeholders, paths, swarmConfig);
291
- return {
292
- result,
293
- source: "echelon-native",
294
- };
295
- }