@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.
- package/README.md +187 -535
- package/connectors/nv_mirofish_wrapper.py +841 -0
- package/connectors/nv_scienceclaw_wrapper.py +453 -0
- package/dist/adapters/scienceclaw.js +52 -2
- package/dist/assets/index-CH_VswRM.css +1 -0
- package/dist/assets/index-sT4b_z7w.js +686 -0
- package/dist/assets/{reportEngine-D2ZrMny8.js → reportEngine-Bu8bB5Yq.js} +1 -1
- package/dist/connectors/nv-scienceclaw-post.js +363 -0
- package/dist/engine/aiProvider.js +82 -3
- package/dist/engine/analyzer.js +12 -24
- package/dist/engine/cli.js +89 -114
- package/dist/engine/dynamicsGovernance.js +4 -0
- package/dist/engine/fullGovernedLoop.js +16 -1
- package/dist/engine/goalEngine.js +3 -4
- package/dist/engine/governance.js +18 -0
- package/dist/engine/index.js +19 -28
- package/dist/engine/intentTranslator.js +281 -0
- package/dist/engine/liveAdapter.js +100 -18
- package/dist/engine/liveVisualizer.js +2071 -1023
- package/dist/engine/primeRadiant.js +2 -8
- package/dist/engine/reasoningEngine.js +2 -7
- package/dist/engine/scenarioCapsule.js +5 -5
- package/dist/engine/swarmSimulation.js +1 -9
- package/dist/engine/universalAdapter.js +371 -0
- package/dist/engine/worldBridge.js +22 -8
- package/dist/index.html +2 -2
- package/dist/lib/reasoningEngine.js +17 -1
- package/dist/lib/simulationAdapter.js +11 -11
- package/dist/lib/swarmParser.js +1 -1
- package/dist/runtime/govern.js +160 -7
- package/dist/runtime/index.js +1 -4
- package/dist/runtime/types.js +91 -0
- package/package.json +23 -6
- package/dist/adapters/mirofish.js +0 -461
- package/dist/assets/index-B64NuIXu.css +0 -1
- package/dist/assets/index-BMkPevVr.js +0 -532
- package/dist/assets/mirotir-logo-DUexumBH.svg +0 -185
- 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>
|
package/dist/engine/mirofish.js
DELETED
|
@@ -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
|
-
}
|