@neuroverseos/nv-sim 0.1.2 → 0.1.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 +562 -68
- package/dist/adapters/mirofish.js +461 -0
- package/dist/adapters/scienceclaw.js +750 -0
- package/dist/assets/index-B64NuIXu.css +1 -0
- package/dist/assets/index-DbzSnYxr.js +532 -0
- package/dist/assets/mirotir-logo-DUexumBH.svg +185 -0
- package/dist/assets/reportEngine-DKWTrP6-.js +1 -0
- package/dist/components/ConstraintsPanel.js +11 -0
- package/dist/components/StakeholderBuilder.js +32 -0
- package/dist/components/ui/badge.js +24 -0
- package/dist/components/ui/button.js +70 -0
- package/dist/components/ui/card.js +57 -0
- package/dist/components/ui/input.js +44 -0
- package/dist/components/ui/label.js +45 -0
- package/dist/components/ui/select.js +70 -0
- package/dist/engine/aiProvider.js +681 -0
- package/dist/engine/auditTrace.js +352 -0
- package/dist/engine/behavioralAnalysis.js +605 -0
- package/dist/engine/cli.js +1408 -299
- package/dist/engine/dynamicsGovernance.js +588 -0
- package/dist/engine/fullGovernedLoop.js +367 -0
- package/dist/engine/governance.js +8 -3
- package/dist/engine/governedSimulation.js +114 -17
- package/dist/engine/index.js +56 -1
- package/dist/engine/liveAdapter.js +342 -0
- package/dist/engine/liveVisualizer.js +4284 -0
- package/dist/engine/metrics/science.metrics.js +335 -0
- package/dist/engine/narrativeInjection.js +360 -0
- package/dist/engine/policyEnforcement.js +1611 -0
- package/dist/engine/policyEngine.js +799 -0
- package/dist/engine/primeRadiant.js +540 -0
- package/dist/engine/reasoningEngine.js +57 -3
- package/dist/engine/reportEngine.js +97 -0
- package/dist/engine/scenarioCapsule.js +56 -0
- package/dist/engine/scenarioComparison.js +463 -0
- package/dist/engine/scenarioLibrary.js +248 -0
- package/dist/engine/swarmSimulation.js +54 -1
- package/dist/engine/worldComparison.js +358 -0
- package/dist/engine/worldStorage.js +232 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.html +23 -0
- package/dist/lib/reasoningEngine.js +290 -0
- package/dist/lib/simulationAdapter.js +686 -0
- package/dist/lib/swarmParser.js +291 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/utils.js +8 -0
- package/dist/placeholder.svg +1 -0
- package/dist/robots.txt +14 -0
- package/dist/runtime/govern.js +473 -0
- package/dist/runtime/index.js +75 -0
- package/dist/runtime/types.js +11 -0
- package/package.json +17 -12
- package/variants/.gitkeep +0 -0
package/dist/engine/index.js
CHANGED
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
* Mirotir helps you decide WHAT TO DO → the brain
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.
|
|
24
|
+
exports.policyToWorld = exports.validatePolicy = exports.parseRulesFromText = exports.suggestExperiments = exports.formatPolicyDiagnostics = exports.formatGuidedNextSteps = exports.exportEnforcementReportJSON = exports.formatEnforcementReport = exports.createEnforcementSession = exports.formatCrossRunComparison = exports.formatBehavioralAnalysis = exports.compareBehaviorAcrossRuns = exports.detectBehavioralShifts = exports.computeActionDistributions = exports.buildAgentTrajectories = exports.classifyBehavior = exports.analyzeBehavior = exports.TRADING_DEMO = exports.runGovernedComparison = exports.analyzeMiroFishSimulation = exports.DEFAULT_MIROFISH_CONFIG = exports.buildMiroFishRequest = exports.miroFishResultToSwarmResult = exports.stakeholdersToMiroFishAgents = exports.runUnifiedSimulation = exports.getMiroFishClient = exports.configureMiroFish = exports.MiroFishError = exports.MiroFishClient = exports.runSwarmSimulation = exports.initNeuroverseModule = exports.validationToEnforcedConstraints = exports.simulationToGovernanceSignals = exports.verdictToConstitutionalChecks = exports.validateScenarioWorld = exports.runWorldSimulation = exports.evaluateScenarioGuard = exports.buildWorldFromScenario = exports.runFullGovernanceChecks = exports.runGovernanceChecks = exports.processReasonRequest = exports.SCENARIO_TEMPLATES = exports.getPresetCapsule = exports.extractCapsuleFromUrl = exports.buildShareableUrl = exports.decodeCapsule = exports.encodeCapsule = exports.capsuleToReasonRequest = exports.createCapsule = exports.runGoalReasoning = void 0;
|
|
25
|
+
exports.EXAMPLE_WORLD_STATES = exports.EXAMPLE_ACTIONS = exports.createGovernor = exports.govern = exports.extractTrace = exports.generateGovernedReport = exports.formatAuditTrail = exports.searchAuditTrails = exports.loadAuditSession = exports.listAuditSessions = exports.AuditTrail = exports.evaluateAIAction = exports.listAIProviders = exports.getDefaultProviderName = exports.getAIProvider = exports.registerAIProvider = exports.generateAIReaction = exports.generateDeterministicReport = exports.OpenAICompatibleProvider = exports.AnthropicProvider = exports.DeterministicProvider = exports.AI_ROLES = exports.parseReasonRequestBody = exports.handleRunPreset = exports.handleGetPreset = exports.handleListPresets = exports.handleHealthCheck = exports.handleCreateCapsule = exports.handleReasonFromCapsule = exports.handleReasonRequest = exports.applyQuickFix = exports.runPolicyPipeline = void 0;
|
|
25
26
|
// Goal-Directed Strategy Engine
|
|
26
27
|
var goalEngine_1 = require("./goalEngine");
|
|
27
28
|
Object.defineProperty(exports, "runGoalReasoning", { enumerable: true, get: function () { return goalEngine_1.runGoalReasoning; } });
|
|
@@ -70,6 +71,28 @@ Object.defineProperty(exports, "analyzeMiroFishSimulation", { enumerable: true,
|
|
|
70
71
|
var governedSimulation_1 = require("./governedSimulation");
|
|
71
72
|
Object.defineProperty(exports, "runGovernedComparison", { enumerable: true, get: function () { return governedSimulation_1.runGovernedComparison; } });
|
|
72
73
|
Object.defineProperty(exports, "TRADING_DEMO", { enumerable: true, get: function () { return governedSimulation_1.TRADING_DEMO; } });
|
|
74
|
+
var behavioralAnalysis_1 = require("./behavioralAnalysis");
|
|
75
|
+
Object.defineProperty(exports, "analyzeBehavior", { enumerable: true, get: function () { return behavioralAnalysis_1.analyzeBehavior; } });
|
|
76
|
+
Object.defineProperty(exports, "classifyBehavior", { enumerable: true, get: function () { return behavioralAnalysis_1.classifyBehavior; } });
|
|
77
|
+
Object.defineProperty(exports, "buildAgentTrajectories", { enumerable: true, get: function () { return behavioralAnalysis_1.buildAgentTrajectories; } });
|
|
78
|
+
Object.defineProperty(exports, "computeActionDistributions", { enumerable: true, get: function () { return behavioralAnalysis_1.computeActionDistributions; } });
|
|
79
|
+
Object.defineProperty(exports, "detectBehavioralShifts", { enumerable: true, get: function () { return behavioralAnalysis_1.detectBehavioralShifts; } });
|
|
80
|
+
Object.defineProperty(exports, "compareBehaviorAcrossRuns", { enumerable: true, get: function () { return behavioralAnalysis_1.compareBehaviorAcrossRuns; } });
|
|
81
|
+
Object.defineProperty(exports, "formatBehavioralAnalysis", { enumerable: true, get: function () { return behavioralAnalysis_1.formatBehavioralAnalysis; } });
|
|
82
|
+
Object.defineProperty(exports, "formatCrossRunComparison", { enumerable: true, get: function () { return behavioralAnalysis_1.formatCrossRunComparison; } });
|
|
83
|
+
var policyEnforcement_1 = require("./policyEnforcement");
|
|
84
|
+
Object.defineProperty(exports, "createEnforcementSession", { enumerable: true, get: function () { return policyEnforcement_1.createEnforcementSession; } });
|
|
85
|
+
Object.defineProperty(exports, "formatEnforcementReport", { enumerable: true, get: function () { return policyEnforcement_1.formatEnforcementReport; } });
|
|
86
|
+
Object.defineProperty(exports, "exportEnforcementReportJSON", { enumerable: true, get: function () { return policyEnforcement_1.exportEnforcementReportJSON; } });
|
|
87
|
+
Object.defineProperty(exports, "formatGuidedNextSteps", { enumerable: true, get: function () { return policyEnforcement_1.formatGuidedNextSteps; } });
|
|
88
|
+
Object.defineProperty(exports, "formatPolicyDiagnostics", { enumerable: true, get: function () { return policyEnforcement_1.formatPolicyDiagnostics; } });
|
|
89
|
+
Object.defineProperty(exports, "suggestExperiments", { enumerable: true, get: function () { return policyEnforcement_1.suggestExperiments; } });
|
|
90
|
+
var policyEngine_1 = require("./policyEngine");
|
|
91
|
+
Object.defineProperty(exports, "parseRulesFromText", { enumerable: true, get: function () { return policyEngine_1.parseRulesFromText; } });
|
|
92
|
+
Object.defineProperty(exports, "validatePolicy", { enumerable: true, get: function () { return policyEngine_1.validatePolicy; } });
|
|
93
|
+
Object.defineProperty(exports, "policyToWorld", { enumerable: true, get: function () { return policyEngine_1.policyToWorld; } });
|
|
94
|
+
Object.defineProperty(exports, "runPolicyPipeline", { enumerable: true, get: function () { return policyEngine_1.runPolicyPipeline; } });
|
|
95
|
+
Object.defineProperty(exports, "applyQuickFix", { enumerable: true, get: function () { return policyEngine_1.applyQuickFix; } });
|
|
73
96
|
// API Route Handlers
|
|
74
97
|
var api_1 = require("./api");
|
|
75
98
|
Object.defineProperty(exports, "handleReasonRequest", { enumerable: true, get: function () { return api_1.handleReasonRequest; } });
|
|
@@ -80,3 +103,35 @@ Object.defineProperty(exports, "handleListPresets", { enumerable: true, get: fun
|
|
|
80
103
|
Object.defineProperty(exports, "handleGetPreset", { enumerable: true, get: function () { return api_1.handleGetPreset; } });
|
|
81
104
|
Object.defineProperty(exports, "handleRunPreset", { enumerable: true, get: function () { return api_1.handleRunPreset; } });
|
|
82
105
|
Object.defineProperty(exports, "parseReasonRequestBody", { enumerable: true, get: function () { return api_1.parseReasonRequestBody; } });
|
|
106
|
+
var aiProvider_1 = require("./aiProvider");
|
|
107
|
+
Object.defineProperty(exports, "AI_ROLES", { enumerable: true, get: function () { return aiProvider_1.AI_ROLES; } });
|
|
108
|
+
Object.defineProperty(exports, "DeterministicProvider", { enumerable: true, get: function () { return aiProvider_1.DeterministicProvider; } });
|
|
109
|
+
Object.defineProperty(exports, "AnthropicProvider", { enumerable: true, get: function () { return aiProvider_1.AnthropicProvider; } });
|
|
110
|
+
Object.defineProperty(exports, "OpenAICompatibleProvider", { enumerable: true, get: function () { return aiProvider_1.OpenAICompatibleProvider; } });
|
|
111
|
+
Object.defineProperty(exports, "generateDeterministicReport", { enumerable: true, get: function () { return aiProvider_1.generateDeterministicReport; } });
|
|
112
|
+
Object.defineProperty(exports, "generateAIReaction", { enumerable: true, get: function () { return aiProvider_1.generateAIReaction; } });
|
|
113
|
+
Object.defineProperty(exports, "registerAIProvider", { enumerable: true, get: function () { return aiProvider_1.registerAIProvider; } });
|
|
114
|
+
Object.defineProperty(exports, "getAIProvider", { enumerable: true, get: function () { return aiProvider_1.getAIProvider; } });
|
|
115
|
+
Object.defineProperty(exports, "getDefaultProviderName", { enumerable: true, get: function () { return aiProvider_1.getDefaultProviderName; } });
|
|
116
|
+
Object.defineProperty(exports, "listAIProviders", { enumerable: true, get: function () { return aiProvider_1.listAIProviders; } });
|
|
117
|
+
Object.defineProperty(exports, "evaluateAIAction", { enumerable: true, get: function () { return aiProvider_1.evaluateAIAction; } });
|
|
118
|
+
var auditTrace_1 = require("./auditTrace");
|
|
119
|
+
Object.defineProperty(exports, "AuditTrail", { enumerable: true, get: function () { return auditTrace_1.AuditTrail; } });
|
|
120
|
+
Object.defineProperty(exports, "listAuditSessions", { enumerable: true, get: function () { return auditTrace_1.listAuditSessions; } });
|
|
121
|
+
Object.defineProperty(exports, "loadAuditSession", { enumerable: true, get: function () { return auditTrace_1.loadAuditSession; } });
|
|
122
|
+
Object.defineProperty(exports, "searchAuditTrails", { enumerable: true, get: function () { return auditTrace_1.searchAuditTrails; } });
|
|
123
|
+
Object.defineProperty(exports, "formatAuditTrail", { enumerable: true, get: function () { return auditTrace_1.formatAuditTrail; } });
|
|
124
|
+
var reportEngine_1 = require("./reportEngine");
|
|
125
|
+
Object.defineProperty(exports, "generateGovernedReport", { enumerable: true, get: function () { return reportEngine_1.generateGovernedReport; } });
|
|
126
|
+
Object.defineProperty(exports, "extractTrace", { enumerable: true, get: function () { return reportEngine_1.extractTrace; } });
|
|
127
|
+
// NeuroVerse Governance Runtime — the wrapper that makes governance real
|
|
128
|
+
// Drop into ANY agent system: govern(action, worldState, policyText)
|
|
129
|
+
var govern_1 = require("../runtime/govern");
|
|
130
|
+
Object.defineProperty(exports, "govern", { enumerable: true, get: function () { return govern_1.govern; } });
|
|
131
|
+
Object.defineProperty(exports, "createGovernor", { enumerable: true, get: function () { return govern_1.createGovernor; } });
|
|
132
|
+
Object.defineProperty(exports, "EXAMPLE_ACTIONS", { enumerable: true, get: function () { return govern_1.EXAMPLE_ACTIONS; } });
|
|
133
|
+
Object.defineProperty(exports, "EXAMPLE_WORLD_STATES", { enumerable: true, get: function () { return govern_1.EXAMPLE_WORLD_STATES; } });
|
|
134
|
+
// Live Simulation Adapters — plug ANY running simulator into governance + trace
|
|
135
|
+
// NOTE: liveAdapter.ts uses Node.js APIs (child_process, events) and is NOT
|
|
136
|
+
// exported here to avoid Vite browser bundle errors. Import directly from
|
|
137
|
+
// "./liveAdapter" in CLI/server code only.
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Live Simulation Adapter
|
|
4
|
+
*
|
|
5
|
+
* Connects ANY running simulator into the NV-SIM governance + trace pipeline.
|
|
6
|
+
* Instead of running our own swarm simulation, we ingest live events from an
|
|
7
|
+
* external simulator process, normalize them, and feed them through governance.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* External Simulator (running process / stream)
|
|
11
|
+
* ↓ stdout / WebSocket / SSE
|
|
12
|
+
* LiveSimulationAdapter (parse + normalize)
|
|
13
|
+
* ↓ LiveSimulationRound
|
|
14
|
+
* Governance Engine (evaluate guards)
|
|
15
|
+
* ↓ verdicts
|
|
16
|
+
* Trace UI (causality visualization)
|
|
17
|
+
*
|
|
18
|
+
* Supported adapter types:
|
|
19
|
+
* - ProcessAdapter: spawn a child process, parse stdout
|
|
20
|
+
* - StreamAdapter: connect to WebSocket/SSE endpoint (future)
|
|
21
|
+
*
|
|
22
|
+
* Every adapter emits the same LiveSimulationRound events, regardless of source.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.ADAPTER_REGISTRY = void 0;
|
|
26
|
+
exports.createProcessAdapter = createProcessAdapter;
|
|
27
|
+
exports.parseMiroFishLine = parseMiroFishLine;
|
|
28
|
+
exports.parseGenericJsonLine = parseGenericJsonLine;
|
|
29
|
+
exports.createAdapter = createAdapter;
|
|
30
|
+
const child_process_1 = require("child_process");
|
|
31
|
+
const events_1 = require("events");
|
|
32
|
+
function createParserState() {
|
|
33
|
+
return {
|
|
34
|
+
currentRound: 0,
|
|
35
|
+
pendingActions: [],
|
|
36
|
+
pendingEvents: [],
|
|
37
|
+
pendingDynamics: [],
|
|
38
|
+
buffer: {},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Process adapter — spawns a child process and parses its stdout.
|
|
43
|
+
*
|
|
44
|
+
* Usage:
|
|
45
|
+
* const adapter = createProcessAdapter({
|
|
46
|
+
* type: "process",
|
|
47
|
+
* label: "MiroFish (Live)",
|
|
48
|
+
* command: "node",
|
|
49
|
+
* args: ["mirofish.js"],
|
|
50
|
+
* parser: parseMiroFishLine,
|
|
51
|
+
* });
|
|
52
|
+
* adapter.on("round", (round) => { ... });
|
|
53
|
+
* await adapter.start();
|
|
54
|
+
*/
|
|
55
|
+
function createProcessAdapter(config) {
|
|
56
|
+
const emitter = new events_1.EventEmitter();
|
|
57
|
+
let proc = null;
|
|
58
|
+
let _status = "idle";
|
|
59
|
+
const state = createParserState();
|
|
60
|
+
function setStatus(s) {
|
|
61
|
+
_status = s;
|
|
62
|
+
emitter.emit("status", s);
|
|
63
|
+
}
|
|
64
|
+
Object.defineProperties(emitter, {
|
|
65
|
+
status: { get: () => _status },
|
|
66
|
+
source: { get: () => config.type },
|
|
67
|
+
label: { get: () => config.label },
|
|
68
|
+
});
|
|
69
|
+
emitter.start = async function start() {
|
|
70
|
+
setStatus("connecting");
|
|
71
|
+
proc = (0, child_process_1.spawn)(config.command, config.args, {
|
|
72
|
+
cwd: config.cwd,
|
|
73
|
+
env: { ...process.env, ...config.env },
|
|
74
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
75
|
+
});
|
|
76
|
+
let lineBuffer = "";
|
|
77
|
+
proc.stdout?.on("data", (chunk) => {
|
|
78
|
+
lineBuffer += chunk.toString();
|
|
79
|
+
const lines = lineBuffer.split("\n");
|
|
80
|
+
// Keep incomplete last line in buffer
|
|
81
|
+
lineBuffer = lines.pop() ?? "";
|
|
82
|
+
for (const line of lines) {
|
|
83
|
+
const trimmed = line.trim();
|
|
84
|
+
if (!trimmed)
|
|
85
|
+
continue;
|
|
86
|
+
try {
|
|
87
|
+
const round = config.parser(trimmed, state);
|
|
88
|
+
if (round) {
|
|
89
|
+
emitter.emit("round", round);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
// Parser error — log but don't crash
|
|
94
|
+
emitter.emit("error", new Error(`Parser error: ${err}`));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (_status === "connecting") {
|
|
98
|
+
setStatus("streaming");
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
proc.stderr?.on("data", (chunk) => {
|
|
102
|
+
// stderr is informational — don't treat as error
|
|
103
|
+
const msg = chunk.toString().trim();
|
|
104
|
+
if (msg) {
|
|
105
|
+
emitter.emit("log", msg);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
proc.on("close", (code) => {
|
|
109
|
+
// Flush any remaining buffer
|
|
110
|
+
if (lineBuffer.trim()) {
|
|
111
|
+
try {
|
|
112
|
+
const round = config.parser(lineBuffer.trim(), state);
|
|
113
|
+
if (round)
|
|
114
|
+
emitter.emit("round", round);
|
|
115
|
+
}
|
|
116
|
+
catch { /* ignore */ }
|
|
117
|
+
}
|
|
118
|
+
if (code === 0) {
|
|
119
|
+
setStatus("completed");
|
|
120
|
+
emitter.emit("complete");
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
setStatus("error");
|
|
124
|
+
emitter.emit("error", new Error(`Process exited with code ${code}`));
|
|
125
|
+
}
|
|
126
|
+
proc = null;
|
|
127
|
+
});
|
|
128
|
+
proc.on("error", (err) => {
|
|
129
|
+
setStatus("error");
|
|
130
|
+
emitter.emit("error", err);
|
|
131
|
+
proc = null;
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
emitter.stop = async function stop() {
|
|
135
|
+
if (proc) {
|
|
136
|
+
proc.kill("SIGTERM");
|
|
137
|
+
// Give it 3s to exit gracefully, then force
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
if (proc)
|
|
140
|
+
proc.kill("SIGKILL");
|
|
141
|
+
}, 3000);
|
|
142
|
+
}
|
|
143
|
+
setStatus("idle");
|
|
144
|
+
};
|
|
145
|
+
return emitter;
|
|
146
|
+
}
|
|
147
|
+
// ============================================
|
|
148
|
+
// MIROFISH STDOUT PARSER
|
|
149
|
+
// ============================================
|
|
150
|
+
/**
|
|
151
|
+
* Parses MiroFish stdout line-by-line.
|
|
152
|
+
*
|
|
153
|
+
* Expected MiroFish output formats:
|
|
154
|
+
*
|
|
155
|
+
* JSON-per-line (preferred):
|
|
156
|
+
* {"step":1,"agent_actions":[{"agent_id":"a1","action":"buy","sentiment":0.5,"confidence":0.8}]}
|
|
157
|
+
*
|
|
158
|
+
* Key-value (fallback):
|
|
159
|
+
* [step 1] agent=swarm_1 action=panic_sell sentiment=-0.7 confidence=0.6
|
|
160
|
+
* [step 1] event=market_crash severity=major
|
|
161
|
+
* [step 1] emergent=herd_behavior
|
|
162
|
+
* [step 2] ...
|
|
163
|
+
*
|
|
164
|
+
* We emit a LiveSimulationRound when we detect a new step number
|
|
165
|
+
* (meaning the previous step is complete).
|
|
166
|
+
*/
|
|
167
|
+
function parseMiroFishLine(line, state) {
|
|
168
|
+
// Try JSON first
|
|
169
|
+
if (line.startsWith("{")) {
|
|
170
|
+
try {
|
|
171
|
+
const data = JSON.parse(line);
|
|
172
|
+
if (data.step != null && Array.isArray(data.agent_actions)) {
|
|
173
|
+
// Parse adaptation data if present
|
|
174
|
+
let adaptation;
|
|
175
|
+
if (data.adaptation) {
|
|
176
|
+
const a = data.adaptation;
|
|
177
|
+
adaptation = {
|
|
178
|
+
count: a.count ?? 0,
|
|
179
|
+
rate: a.rate ?? 0,
|
|
180
|
+
deltas: (a.deltas ?? []).map((d) => ({
|
|
181
|
+
agent: d.agent ?? "unknown",
|
|
182
|
+
intended: d.intended ?? "",
|
|
183
|
+
actual: d.actual ?? "",
|
|
184
|
+
decision: d.decision ?? "BLOCK",
|
|
185
|
+
rule: d.rule,
|
|
186
|
+
reason: d.reason,
|
|
187
|
+
shift: d.shift ?? "unknown",
|
|
188
|
+
})),
|
|
189
|
+
intendedDistribution: a.intended_distribution ?? {},
|
|
190
|
+
actualDistribution: a.actual_distribution ?? {},
|
|
191
|
+
clusterPatterns: (a.cluster_patterns ?? []).map((c) => ({
|
|
192
|
+
type: c.type ?? "unknown",
|
|
193
|
+
strength: c.strength ?? 0,
|
|
194
|
+
agents: c.agents ?? 0,
|
|
195
|
+
})),
|
|
196
|
+
narrative: a.narrative ?? "",
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
// Complete step as JSON — emit immediately
|
|
200
|
+
return {
|
|
201
|
+
round: data.step,
|
|
202
|
+
source: "mirofish",
|
|
203
|
+
agentActions: data.agent_actions.map((a) => ({
|
|
204
|
+
agent: a.agent_id ?? a.agent ?? "unknown",
|
|
205
|
+
action: a.action ?? "",
|
|
206
|
+
impact: a.sentiment ?? a.impact ?? 0,
|
|
207
|
+
confidence: a.confidence ?? 0.5,
|
|
208
|
+
...(a.verdict ? { verdict: { status: a.verdict.status, rule: a.verdict.rule, reason: a.verdict.reason } } : {}),
|
|
209
|
+
})),
|
|
210
|
+
systemEvents: (data.system_events ?? []).map((e) => typeof e === "string"
|
|
211
|
+
? { id: e, label: e }
|
|
212
|
+
: { id: e.id ?? e.event ?? "unknown", label: e.label ?? e.event ?? e.id ?? "", severity: e.severity }),
|
|
213
|
+
emergentDynamics: data.emergent_patterns ?? data.emergent ?? [],
|
|
214
|
+
adaptation,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch { /* not JSON, fall through to key-value parsing */ }
|
|
219
|
+
}
|
|
220
|
+
// Key-value format: [step N] key=value ...
|
|
221
|
+
const stepMatch = line.match(/\[step\s+(\d+)\]/i);
|
|
222
|
+
if (!stepMatch)
|
|
223
|
+
return null;
|
|
224
|
+
const stepNum = parseInt(stepMatch[1], 10);
|
|
225
|
+
let result = null;
|
|
226
|
+
// If new step, flush previous
|
|
227
|
+
if (stepNum > state.currentRound && state.currentRound > 0) {
|
|
228
|
+
result = {
|
|
229
|
+
round: state.currentRound,
|
|
230
|
+
source: "mirofish",
|
|
231
|
+
agentActions: [...state.pendingActions],
|
|
232
|
+
systemEvents: state.pendingEvents.length > 0 ? [...state.pendingEvents] : undefined,
|
|
233
|
+
emergentDynamics: state.pendingDynamics.length > 0 ? [...state.pendingDynamics] : undefined,
|
|
234
|
+
};
|
|
235
|
+
state.pendingActions = [];
|
|
236
|
+
state.pendingEvents = [];
|
|
237
|
+
state.pendingDynamics = [];
|
|
238
|
+
}
|
|
239
|
+
state.currentRound = stepNum;
|
|
240
|
+
const rest = line.slice(stepMatch.index + stepMatch[0].length).trim();
|
|
241
|
+
// Parse agent action
|
|
242
|
+
const agentMatch = rest.match(/agent=(\S+)\s+action=(\S+)(?:\s+sentiment=([-\d.]+))?(?:\s+confidence=([-\d.]+))?/);
|
|
243
|
+
if (agentMatch) {
|
|
244
|
+
state.pendingActions.push({
|
|
245
|
+
agent: agentMatch[1],
|
|
246
|
+
action: agentMatch[2],
|
|
247
|
+
impact: agentMatch[3] ? parseFloat(agentMatch[3]) : 0,
|
|
248
|
+
confidence: agentMatch[4] ? parseFloat(agentMatch[4]) : 0.5,
|
|
249
|
+
});
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
// Parse system event
|
|
253
|
+
const eventMatch = rest.match(/event=(\S+)(?:\s+severity=(\S+))?/);
|
|
254
|
+
if (eventMatch) {
|
|
255
|
+
state.pendingEvents.push({
|
|
256
|
+
id: eventMatch[1],
|
|
257
|
+
label: eventMatch[1].replace(/_/g, " "),
|
|
258
|
+
severity: eventMatch[2],
|
|
259
|
+
});
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
// Parse emergent behavior
|
|
263
|
+
const emergentMatch = rest.match(/emergent=(.+)/);
|
|
264
|
+
if (emergentMatch) {
|
|
265
|
+
state.pendingDynamics.push(emergentMatch[1].trim());
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
// ============================================
|
|
271
|
+
// GENERIC JSON PARSER (works for any JSON-per-line simulator)
|
|
272
|
+
// ============================================
|
|
273
|
+
/**
|
|
274
|
+
* Generic JSON-per-line parser.
|
|
275
|
+
* Expects each line to be a JSON object with at minimum:
|
|
276
|
+
* { "step": N, "agents": [{ "id": "...", "action": "...", "impact": 0.5 }] }
|
|
277
|
+
*/
|
|
278
|
+
function parseGenericJsonLine(line, _state) {
|
|
279
|
+
if (!line.startsWith("{"))
|
|
280
|
+
return null;
|
|
281
|
+
try {
|
|
282
|
+
const data = JSON.parse(line);
|
|
283
|
+
const step = data.step ?? data.tick ?? data.round ?? data.time;
|
|
284
|
+
if (step == null)
|
|
285
|
+
return null;
|
|
286
|
+
const agents = (data.agents ?? data.agent_actions ?? []).map((a) => ({
|
|
287
|
+
agent: a.id ?? a.agent ?? a.agent_id ?? "unknown",
|
|
288
|
+
action: a.action ?? a.behavior ?? "",
|
|
289
|
+
impact: a.impact ?? a.sentiment ?? a.value ?? 0,
|
|
290
|
+
confidence: a.confidence ?? 0.5,
|
|
291
|
+
}));
|
|
292
|
+
return {
|
|
293
|
+
round: typeof step === "number" ? step : parseInt(step, 10),
|
|
294
|
+
source: "generic",
|
|
295
|
+
agentActions: agents,
|
|
296
|
+
systemEvents: (data.events ?? []).map((e) => typeof e === "string"
|
|
297
|
+
? { id: e, label: e }
|
|
298
|
+
: { id: e.id ?? "unknown", label: e.label ?? e.id ?? "", severity: e.severity }),
|
|
299
|
+
emergentDynamics: data.dynamics ?? data.emergent ?? [],
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
exports.ADAPTER_REGISTRY = {
|
|
307
|
+
mirofish: {
|
|
308
|
+
id: "mirofish",
|
|
309
|
+
label: "MiroFish (Live)",
|
|
310
|
+
description: "Spawn MiroFish swarm simulation and stream agent behavior",
|
|
311
|
+
createConfig: (opts = {}) => ({
|
|
312
|
+
type: "process",
|
|
313
|
+
label: "MiroFish (Live)",
|
|
314
|
+
command: opts.command ?? "node",
|
|
315
|
+
args: (opts.args ?? "mirofish.js").split(" "),
|
|
316
|
+
cwd: opts.cwd,
|
|
317
|
+
parser: parseMiroFishLine,
|
|
318
|
+
}),
|
|
319
|
+
},
|
|
320
|
+
generic: {
|
|
321
|
+
id: "generic",
|
|
322
|
+
label: "Generic JSON Process",
|
|
323
|
+
description: "Spawn any process that outputs JSON-per-line simulation data",
|
|
324
|
+
createConfig: (opts = {}) => ({
|
|
325
|
+
type: "process",
|
|
326
|
+
label: opts.label ?? "External Simulator",
|
|
327
|
+
command: opts.command ?? "python",
|
|
328
|
+
args: (opts.args ?? "sim.py").split(" "),
|
|
329
|
+
cwd: opts.cwd,
|
|
330
|
+
parser: parseGenericJsonLine,
|
|
331
|
+
}),
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Create an adapter from the registry.
|
|
336
|
+
*/
|
|
337
|
+
function createAdapter(adapterId, options) {
|
|
338
|
+
const entry = exports.ADAPTER_REGISTRY[adapterId];
|
|
339
|
+
if (!entry)
|
|
340
|
+
return null;
|
|
341
|
+
return createProcessAdapter(entry.createConfig(options));
|
|
342
|
+
}
|