@neuroverseos/governance 0.3.0 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.well-known/ai-plugin.json +34 -9
- package/AGENTS.md +72 -24
- package/README.md +352 -237
- package/dist/adapters/autoresearch.cjs +1152 -3
- package/dist/adapters/autoresearch.d.cts +11 -3
- package/dist/adapters/autoresearch.d.ts +11 -3
- package/dist/adapters/autoresearch.js +9 -4
- package/dist/adapters/deep-agents.cjs +1528 -0
- package/dist/adapters/deep-agents.d.cts +181 -0
- package/dist/adapters/deep-agents.d.ts +181 -0
- package/dist/adapters/deep-agents.js +17 -0
- package/dist/adapters/express.cjs +171 -32
- package/dist/adapters/express.d.cts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +5 -5
- package/dist/adapters/index.cjs +564 -121
- package/dist/adapters/index.d.cts +3 -1
- package/dist/adapters/index.d.ts +3 -1
- package/dist/adapters/index.js +38 -16
- package/dist/adapters/langchain.cjs +217 -57
- package/dist/adapters/langchain.d.cts +5 -5
- package/dist/adapters/langchain.d.ts +5 -5
- package/dist/adapters/langchain.js +6 -5
- package/dist/adapters/openai.cjs +219 -59
- package/dist/adapters/openai.d.cts +5 -5
- package/dist/adapters/openai.d.ts +5 -5
- package/dist/adapters/openai.js +6 -5
- package/dist/adapters/openclaw.cjs +217 -57
- package/dist/adapters/openclaw.d.cts +6 -6
- package/dist/adapters/openclaw.d.ts +6 -6
- package/dist/adapters/openclaw.js +6 -5
- package/dist/add-ROOZLU62.js +314 -0
- package/dist/behavioral-MJO34S6Q.js +118 -0
- package/dist/{bootstrap-GXVDZNF7.js → bootstrap-CQRZVOXK.js} +6 -4
- package/dist/bootstrap-emitter-Q7UIJZ2O.js +7 -0
- package/dist/bootstrap-parser-EEF36XDU.js +7 -0
- package/dist/browser.global.js +941 -0
- package/dist/{build-P42YFKQV.js → build-QKOBBC23.js} +7 -5
- package/dist/{chunk-COT5XS4V.js → chunk-3WQLXYTP.js} +17 -35
- package/dist/{chunk-ER62HNGF.js → chunk-4FLICVVA.js} +17 -37
- package/dist/chunk-5TPFNWRU.js +215 -0
- package/dist/chunk-5U2MQO5P.js +57 -0
- package/dist/{chunk-NF5POFCI.js → chunk-6S5CFQXY.js} +6 -4
- package/dist/{chunk-QPASI2BR.js → chunk-A7GKPPU7.js} +49 -10
- package/dist/{chunk-OGL7QXZS.js → chunk-B6OXJLJ5.js} +17 -3
- package/dist/{chunk-2PQU3VAN.js → chunk-BNKJPUPQ.js} +17 -35
- package/dist/chunk-BQZMOEML.js +43 -0
- package/dist/chunk-CNSO6XW5.js +207 -0
- package/dist/{chunk-JZPQGIKR.js → chunk-CTZHONLA.js} +65 -9
- package/dist/chunk-D2UCV5AK.js +326 -0
- package/dist/{chunk-XPDMYECO.js → chunk-EMQDLDAF.js} +1 -185
- package/dist/{chunk-GR6DGCZ2.js → chunk-F66BVUYB.js} +3 -3
- package/dist/{chunk-2NICNKOM.js → chunk-G7DJ6VOD.js} +5 -4
- package/dist/{chunk-4A7LISES.js → chunk-IS4WUH6Y.js} +45 -6
- package/dist/{chunk-MWDQ4MJB.js → chunk-MH7BT4VH.js} +5 -1
- package/dist/chunk-O5ABKEA7.js +304 -0
- package/dist/chunk-PVTQQS3Y.js +186 -0
- package/dist/{chunk-4QXB6PEO.js → chunk-QLPTHTVB.js} +37 -16
- package/dist/chunk-QWGCMQQD.js +16 -0
- package/dist/{chunk-T5EUJQE5.js → chunk-QXBFT7NI.js} +31 -2
- package/dist/{chunk-PDOZHZWL.js → chunk-TG6SEF24.js} +25 -4
- package/dist/chunk-U6U7EJZL.js +177 -0
- package/dist/{chunk-4JRYGIO7.js → chunk-W7LLXRGY.js} +110 -7
- package/dist/{chunk-BUWWN2NX.js → chunk-ZJTDUCC2.js} +9 -7
- package/dist/{chunk-FYS2CBUW.js → chunk-ZWI3NIXK.js} +10 -0
- package/dist/cli/neuroverse.cjs +5091 -2348
- package/dist/cli/neuroverse.js +52 -21
- package/dist/cli/plan.cjs +881 -41
- package/dist/cli/plan.js +7 -15
- package/dist/cli/run.cjs +289 -34
- package/dist/cli/run.js +4 -4
- package/dist/{configure-ai-TK67ZWZL.js → configure-ai-6TZ3MCSI.js} +1 -1
- package/dist/decision-flow-M63D47LO.js +61 -0
- package/dist/demo-G43RLCPK.js +469 -0
- package/dist/{derive-TLIV4OOU.js → derive-FJZVIPUZ.js} +5 -4
- package/dist/{doctor-XPDLEYXN.js → doctor-6BC6X2VO.js} +6 -4
- package/dist/equity-penalties-SG5IZQ7I.js +244 -0
- package/dist/{explain-IDCRWMPX.js → explain-RHBU2GBR.js} +6 -25
- package/dist/{guard-RV65TT4L.js → guard-AJCCGZMF.js} +8 -12
- package/dist/{guard-contract-WZx__PmU.d.cts → guard-contract-DqFcTScd.d.cts} +117 -5
- package/dist/{guard-contract-WZx__PmU.d.ts → guard-contract-DqFcTScd.d.ts} +117 -5
- package/dist/{guard-engine-JLTUARGU.js → guard-engine-PNR6MHCM.js} +3 -3
- package/dist/{impact-XPECYRLH.js → impact-3XVDSCBU.js} +5 -5
- package/dist/{improve-GPUBKTEA.js → improve-TQP4ECSY.js} +7 -26
- package/dist/index.cjs +5597 -4279
- package/dist/index.d.cts +597 -18
- package/dist/index.d.ts +597 -18
- package/dist/index.js +134 -41
- package/dist/{infer-world-7GVZWFX4.js → infer-world-IFXCACJ5.js} +1 -1
- package/dist/{init-PKPIYHYE.js → init-FYPV4SST.js} +1 -1
- package/dist/{init-world-VWMQZQC7.js → init-world-TI7ARHBT.js} +1 -1
- package/dist/mcp-server-5Y3ZM7TV.js +13 -0
- package/dist/{model-adapter-BB7G4MFI.js → model-adapter-VXEKB4LS.js} +1 -1
- package/dist/{playground-E664U4T6.js → playground-VZBNPPBO.js} +29 -19
- package/dist/{redteam-Z7WREJ44.js → redteam-MZPZD3EF.js} +4 -4
- package/dist/session-JYOARW54.js +15 -0
- package/dist/shared-7RLUHNMU.js +16 -0
- package/dist/shared-B8dvUUD8.d.cts +60 -0
- package/dist/shared-Dr5Wiay8.d.ts +60 -0
- package/dist/{simulate-VDOYQFRO.js → simulate-LJXYBC6M.js} +8 -33
- package/dist/{test-OGXJK4QU.js → test-BOOR4A5F.js} +4 -4
- package/dist/{trace-JVF67VR3.js → trace-PKV4KX56.js} +4 -4
- package/dist/{validate-LLBWVPGV.js → validate-RALX7CZS.js} +2 -2
- package/dist/{validate-engine-UIABSIHD.js → validate-engine-7ZXFVGF2.js} +1 -1
- package/dist/viz/assets/index-B8SaeJZZ.js +23 -0
- package/dist/viz/index.html +23 -0
- package/dist/{world-LAXO6DOX.js → world-BIP4GZBZ.js} +9 -11
- package/dist/world-loader-Y6HMQH2D.js +13 -0
- package/dist/worlds/coding-agent.nv-world.md +211 -0
- package/dist/worlds/research-agent.nv-world.md +169 -0
- package/dist/worlds/social-media.nv-world.md +198 -0
- package/dist/worlds/trading-agent.nv-world.md +218 -0
- package/examples/social-media-sim/bridge.py +209 -0
- package/examples/social-media-sim/simulation.py +927 -0
- package/package.json +30 -4
- package/policies/content-moderation-rules.txt +8 -0
- package/policies/marketing-rules.txt +8 -0
- package/policies/science-research-rules.txt +11 -0
- package/policies/social-media-rules.txt +7 -0
- package/policies/strict-rules.txt +8 -0
- package/policies/trading-rules.txt +8 -0
- package/simulate.html +1567 -0
- package/dist/chunk-YZFATT7X.js +0 -9
- package/dist/mcp-server-FPVSU32Z.js +0 -13
- package/dist/session-EKTRSR7C.js +0 -14
- package/dist/world-loader-HMPTOEA2.js +0 -9
|
@@ -35,17 +35,27 @@ __export(express_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(express_exports);
|
|
37
37
|
|
|
38
|
-
// src/engine/
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
// src/engine/text-utils.ts
|
|
39
|
+
function normalizeEventText(event) {
|
|
40
|
+
return [
|
|
41
|
+
event.intent,
|
|
42
|
+
event.tool ?? "",
|
|
43
|
+
event.scope ?? ""
|
|
44
44
|
].join(" ").toLowerCase();
|
|
45
|
-
|
|
45
|
+
}
|
|
46
|
+
function extractKeywords(text, minLength = 3) {
|
|
47
|
+
return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
|
|
48
|
+
}
|
|
49
|
+
function matchesAllKeywords(eventText, ruleText) {
|
|
50
|
+
const keywords = extractKeywords(ruleText);
|
|
51
|
+
if (keywords.length === 0) return false;
|
|
52
|
+
return keywords.every((kw) => eventText.includes(kw));
|
|
53
|
+
}
|
|
54
|
+
function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
|
|
55
|
+
const keywords = extractKeywords(ruleText);
|
|
46
56
|
if (keywords.length === 0) return false;
|
|
47
57
|
const matched = keywords.filter((kw) => eventText.includes(kw));
|
|
48
|
-
return matched.length >= Math.ceil(keywords.length *
|
|
58
|
+
return matched.length >= Math.ceil(keywords.length * threshold);
|
|
49
59
|
}
|
|
50
60
|
function tokenSimilarity(a, b) {
|
|
51
61
|
const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
@@ -58,6 +68,19 @@ function tokenSimilarity(a, b) {
|
|
|
58
68
|
const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
|
|
59
69
|
return union > 0 ? intersection / union : 0;
|
|
60
70
|
}
|
|
71
|
+
|
|
72
|
+
// src/engine/plan-engine.ts
|
|
73
|
+
function keywordMatch(eventText, step) {
|
|
74
|
+
const stepText = [
|
|
75
|
+
step.label,
|
|
76
|
+
step.description ?? "",
|
|
77
|
+
...step.tags ?? []
|
|
78
|
+
].join(" ");
|
|
79
|
+
return matchesKeywordThreshold(eventText, stepText, 0.5);
|
|
80
|
+
}
|
|
81
|
+
function tokenSimilarity2(a, b) {
|
|
82
|
+
return tokenSimilarity(a, b);
|
|
83
|
+
}
|
|
61
84
|
function findMatchingStep(eventText, event, steps) {
|
|
62
85
|
const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
|
|
63
86
|
if (pendingOrActive.length === 0) {
|
|
@@ -76,7 +99,7 @@ function findMatchingStep(eventText, event, steps) {
|
|
|
76
99
|
let bestScore = 0;
|
|
77
100
|
for (const step of pendingOrActive) {
|
|
78
101
|
const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
|
|
79
|
-
const score =
|
|
102
|
+
const score = tokenSimilarity2(intentText, stepText);
|
|
80
103
|
if (score > bestScore) {
|
|
81
104
|
bestScore = score;
|
|
82
105
|
bestStep = step;
|
|
@@ -117,7 +140,7 @@ function checkConstraints(event, eventText, constraints) {
|
|
|
117
140
|
continue;
|
|
118
141
|
}
|
|
119
142
|
if (constraint.type === "scope" && constraint.trigger) {
|
|
120
|
-
const keywords = constraint.trigger
|
|
143
|
+
const keywords = extractKeywords(constraint.trigger);
|
|
121
144
|
const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
|
|
122
145
|
checks.push({
|
|
123
146
|
constraintId: constraint.id,
|
|
@@ -163,11 +186,7 @@ function evaluatePlan(event, plan) {
|
|
|
163
186
|
progress
|
|
164
187
|
};
|
|
165
188
|
}
|
|
166
|
-
const eventText =
|
|
167
|
-
event.intent,
|
|
168
|
-
event.tool ?? "",
|
|
169
|
-
event.scope ?? ""
|
|
170
|
-
].join(" ").toLowerCase();
|
|
189
|
+
const eventText = normalizeEventText(event);
|
|
171
190
|
const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
|
|
172
191
|
if (!matched) {
|
|
173
192
|
return {
|
|
@@ -208,7 +227,7 @@ function evaluatePlan(event, plan) {
|
|
|
208
227
|
};
|
|
209
228
|
}
|
|
210
229
|
function buildPlanCheck(event, plan, verdict) {
|
|
211
|
-
const eventText =
|
|
230
|
+
const eventText = normalizeEventText(event);
|
|
212
231
|
const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
|
|
213
232
|
const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
|
|
214
233
|
const progress = getPlanProgress(plan);
|
|
@@ -310,11 +329,49 @@ function isExternalScope(scope) {
|
|
|
310
329
|
];
|
|
311
330
|
return !internalPatterns.some((p) => p.test(scope));
|
|
312
331
|
}
|
|
332
|
+
var MAX_INPUT_LENGTH = 1e5;
|
|
313
333
|
function evaluateGuard(event, world, options = {}) {
|
|
314
334
|
const startTime = performance.now();
|
|
315
335
|
const level = options.level ?? "standard";
|
|
316
336
|
const includeTrace = options.trace ?? false;
|
|
317
|
-
|
|
337
|
+
if (!event.intent || typeof event.intent !== "string") {
|
|
338
|
+
return {
|
|
339
|
+
status: "BLOCK",
|
|
340
|
+
reason: "GuardEvent.intent is required and must be a string",
|
|
341
|
+
ruleId: "safety-input-validation",
|
|
342
|
+
evidence: {
|
|
343
|
+
worldId: world.world?.world_id ?? "",
|
|
344
|
+
worldName: world.world?.name ?? "",
|
|
345
|
+
worldVersion: world.world?.version ?? "",
|
|
346
|
+
evaluatedAt: Date.now(),
|
|
347
|
+
invariantsSatisfied: 0,
|
|
348
|
+
invariantsTotal: 0,
|
|
349
|
+
guardsMatched: [],
|
|
350
|
+
rulesMatched: [],
|
|
351
|
+
enforcementLevel: level
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
|
|
356
|
+
if (inputLength > MAX_INPUT_LENGTH) {
|
|
357
|
+
return {
|
|
358
|
+
status: "BLOCK",
|
|
359
|
+
reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
|
|
360
|
+
ruleId: "safety-input-length",
|
|
361
|
+
evidence: {
|
|
362
|
+
worldId: world.world?.world_id ?? "",
|
|
363
|
+
worldName: world.world?.name ?? "",
|
|
364
|
+
worldVersion: world.world?.version ?? "",
|
|
365
|
+
evaluatedAt: Date.now(),
|
|
366
|
+
invariantsSatisfied: 0,
|
|
367
|
+
invariantsTotal: 0,
|
|
368
|
+
guardsMatched: [],
|
|
369
|
+
rulesMatched: [],
|
|
370
|
+
enforcementLevel: level
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
const eventText = normalizeEventText(event);
|
|
318
375
|
const invariantChecks = [];
|
|
319
376
|
const safetyChecks = [];
|
|
320
377
|
let planCheckResult;
|
|
@@ -327,6 +384,43 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
327
384
|
const guardsMatched = [];
|
|
328
385
|
const rulesMatched = [];
|
|
329
386
|
checkInvariantCoverage(world, invariantChecks);
|
|
387
|
+
if (event.roleId && options.agentStates) {
|
|
388
|
+
const agentState = options.agentStates.get(event.roleId);
|
|
389
|
+
if (agentState && agentState.cooldownRemaining > 0) {
|
|
390
|
+
decidingLayer = "safety";
|
|
391
|
+
decidingId = `penalize-cooldown-${event.roleId}`;
|
|
392
|
+
const verdict = buildVerdict(
|
|
393
|
+
"PENALIZE",
|
|
394
|
+
`Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
|
|
395
|
+
`penalize-cooldown-${event.roleId}`,
|
|
396
|
+
void 0,
|
|
397
|
+
world,
|
|
398
|
+
level,
|
|
399
|
+
invariantChecks,
|
|
400
|
+
guardsMatched,
|
|
401
|
+
rulesMatched,
|
|
402
|
+
includeTrace ? buildTrace(
|
|
403
|
+
invariantChecks,
|
|
404
|
+
safetyChecks,
|
|
405
|
+
planCheckResult,
|
|
406
|
+
roleChecks,
|
|
407
|
+
guardChecks,
|
|
408
|
+
kernelRuleChecks,
|
|
409
|
+
levelChecks,
|
|
410
|
+
decidingLayer,
|
|
411
|
+
decidingId,
|
|
412
|
+
startTime
|
|
413
|
+
) : void 0
|
|
414
|
+
);
|
|
415
|
+
verdict.intentRecord = {
|
|
416
|
+
originalIntent: event.intent,
|
|
417
|
+
finalAction: "blocked (agent frozen)",
|
|
418
|
+
enforcement: "PENALIZE",
|
|
419
|
+
consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
|
|
420
|
+
};
|
|
421
|
+
return verdict;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
330
424
|
if (options.sessionAllowlist) {
|
|
331
425
|
const key = eventToAllowlistKey(event);
|
|
332
426
|
if (options.sessionAllowlist.has(key)) {
|
|
@@ -454,7 +548,16 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
454
548
|
if (guardVerdict.status !== "ALLOW") {
|
|
455
549
|
decidingLayer = "guard";
|
|
456
550
|
decidingId = guardVerdict.ruleId;
|
|
457
|
-
|
|
551
|
+
const intentRecord = {
|
|
552
|
+
originalIntent: event.intent,
|
|
553
|
+
finalAction: guardVerdict.status === "MODIFY" ? guardVerdict.modifiedTo ?? "modified" : guardVerdict.status === "PENALIZE" ? "blocked + penalized" : guardVerdict.status === "REWARD" ? event.intent : guardVerdict.status === "NEUTRAL" ? event.intent : guardVerdict.status === "BLOCK" ? "blocked" : "paused",
|
|
554
|
+
ruleApplied: guardVerdict.ruleId,
|
|
555
|
+
enforcement: guardVerdict.status,
|
|
556
|
+
modifiedTo: guardVerdict.modifiedTo,
|
|
557
|
+
consequence: guardVerdict.consequence,
|
|
558
|
+
reward: guardVerdict.reward
|
|
559
|
+
};
|
|
560
|
+
const verdict = buildVerdict(
|
|
458
561
|
guardVerdict.status,
|
|
459
562
|
guardVerdict.reason,
|
|
460
563
|
guardVerdict.ruleId,
|
|
@@ -477,6 +580,10 @@ function evaluateGuard(event, world, options = {}) {
|
|
|
477
580
|
startTime
|
|
478
581
|
) : void 0
|
|
479
582
|
);
|
|
583
|
+
verdict.intentRecord = intentRecord;
|
|
584
|
+
if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
|
|
585
|
+
if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
|
|
586
|
+
return verdict;
|
|
480
587
|
}
|
|
481
588
|
}
|
|
482
589
|
const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
|
|
@@ -771,6 +878,21 @@ function checkGuards(event, eventText, world, checks, guardsMatched) {
|
|
|
771
878
|
if (actionMode === "pause") {
|
|
772
879
|
return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
|
|
773
880
|
}
|
|
881
|
+
if (actionMode === "penalize") {
|
|
882
|
+
const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
|
|
883
|
+
return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
|
|
884
|
+
}
|
|
885
|
+
if (actionMode === "reward") {
|
|
886
|
+
const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
|
|
887
|
+
return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
|
|
888
|
+
}
|
|
889
|
+
if (actionMode === "modify") {
|
|
890
|
+
const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
|
|
891
|
+
return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
|
|
892
|
+
}
|
|
893
|
+
if (actionMode === "neutral") {
|
|
894
|
+
return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
|
|
895
|
+
}
|
|
774
896
|
if (actionMode === "warn" && !warnResult) {
|
|
775
897
|
warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
|
|
776
898
|
}
|
|
@@ -880,9 +1002,7 @@ function checkLevelConstraints(event, level, checks) {
|
|
|
880
1002
|
return null;
|
|
881
1003
|
}
|
|
882
1004
|
function matchesKeywords(eventText, ruleText) {
|
|
883
|
-
|
|
884
|
-
if (keywords.length === 0) return false;
|
|
885
|
-
return keywords.every((kw) => eventText.includes(kw));
|
|
1005
|
+
return matchesAllKeywords(eventText, ruleText);
|
|
886
1006
|
}
|
|
887
1007
|
function eventToAllowlistKey(event) {
|
|
888
1008
|
return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
|
|
@@ -950,10 +1070,18 @@ async function loadWorldFromDirectory(dirPath) {
|
|
|
950
1070
|
const { join } = await import("path");
|
|
951
1071
|
const { readdirSync } = await import("fs");
|
|
952
1072
|
async function readJson(filename) {
|
|
1073
|
+
const filePath = join(dirPath, filename);
|
|
953
1074
|
try {
|
|
954
|
-
const content = await readFile(
|
|
1075
|
+
const content = await readFile(filePath, "utf-8");
|
|
955
1076
|
return JSON.parse(content);
|
|
956
|
-
} catch {
|
|
1077
|
+
} catch (err) {
|
|
1078
|
+
if (err instanceof Error && "code" in err && err.code === "ENOENT") {
|
|
1079
|
+
return void 0;
|
|
1080
|
+
}
|
|
1081
|
+
process.stderr.write(
|
|
1082
|
+
`[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
|
|
1083
|
+
`
|
|
1084
|
+
);
|
|
957
1085
|
return void 0;
|
|
958
1086
|
}
|
|
959
1087
|
}
|
|
@@ -975,10 +1103,23 @@ async function loadWorldFromDirectory(dirPath) {
|
|
|
975
1103
|
const rulesDir = join(dirPath, "rules");
|
|
976
1104
|
const ruleFiles = readdirSync(rulesDir).filter((f) => f.endsWith(".json")).sort();
|
|
977
1105
|
for (const file of ruleFiles) {
|
|
978
|
-
|
|
979
|
-
|
|
1106
|
+
try {
|
|
1107
|
+
const content = await readFile(join(rulesDir, file), "utf-8");
|
|
1108
|
+
rules.push(JSON.parse(content));
|
|
1109
|
+
} catch (err) {
|
|
1110
|
+
process.stderr.write(
|
|
1111
|
+
`[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
|
|
1112
|
+
`
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
} catch (err) {
|
|
1117
|
+
if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
|
|
1118
|
+
process.stderr.write(
|
|
1119
|
+
`[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
|
|
1120
|
+
`
|
|
1121
|
+
);
|
|
980
1122
|
}
|
|
981
|
-
} catch {
|
|
982
1123
|
}
|
|
983
1124
|
return {
|
|
984
1125
|
world: worldJson,
|
|
@@ -1013,10 +1154,7 @@ async function loadWorld(worldPath) {
|
|
|
1013
1154
|
if (info.isDirectory()) {
|
|
1014
1155
|
return loadWorldFromDirectory(worldPath);
|
|
1015
1156
|
}
|
|
1016
|
-
|
|
1017
|
-
throw new Error(".nv-world.zip loading not yet implemented \u2014 use a world directory");
|
|
1018
|
-
}
|
|
1019
|
-
throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory or .nv-world.zip`);
|
|
1157
|
+
throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
|
|
1020
1158
|
}
|
|
1021
1159
|
|
|
1022
1160
|
// src/adapters/express.ts
|
|
@@ -1060,8 +1198,9 @@ function defaultOnBlock(verdict, _req, res, statusCode) {
|
|
|
1060
1198
|
ruleId: verdict.ruleId,
|
|
1061
1199
|
status: verdict.status
|
|
1062
1200
|
};
|
|
1063
|
-
if (res.status && res.json) {
|
|
1064
|
-
res.status(statusCode)
|
|
1201
|
+
if (typeof res.status === "function" && typeof res.json === "function") {
|
|
1202
|
+
const r = res.status(statusCode);
|
|
1203
|
+
r.json(body);
|
|
1065
1204
|
} else if (res.send) {
|
|
1066
1205
|
res.statusCode = statusCode;
|
|
1067
1206
|
res.send(JSON.stringify(body));
|
package/dist/adapters/express.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createGovernanceMiddleware,
|
|
3
3
|
createGovernanceMiddlewareFromWorld
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-G7DJ6VOD.js";
|
|
5
|
+
import "../chunk-W7LLXRGY.js";
|
|
6
|
+
import "../chunk-QLPTHTVB.js";
|
|
7
|
+
import "../chunk-CTZHONLA.js";
|
|
8
|
+
import "../chunk-QWGCMQQD.js";
|
|
9
9
|
export {
|
|
10
10
|
createGovernanceMiddleware,
|
|
11
11
|
createGovernanceMiddlewareFromWorld
|