@neuroverseos/governance 0.1.6 → 0.2.2
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 +279 -423
- package/dist/adapters/express.cjs +242 -2
- package/dist/adapters/express.d.cts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +5 -3
- package/dist/adapters/index.cjs +337 -5
- package/dist/adapters/index.d.cts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +8 -6
- package/dist/adapters/langchain.cjs +297 -3
- package/dist/adapters/langchain.d.cts +8 -1
- package/dist/adapters/langchain.d.ts +8 -1
- package/dist/adapters/langchain.js +5 -3
- package/dist/adapters/openai.cjs +297 -3
- package/dist/adapters/openai.d.cts +8 -1
- package/dist/adapters/openai.d.ts +8 -1
- package/dist/adapters/openai.js +5 -3
- package/dist/adapters/openclaw.cjs +297 -3
- package/dist/adapters/openclaw.d.cts +8 -1
- package/dist/adapters/openclaw.d.ts +8 -1
- package/dist/adapters/openclaw.js +5 -3
- package/dist/{bootstrap-H4HHKQ5G.js → bootstrap-GXVDZNF7.js} +2 -1
- package/dist/{build-73KAVHEY.js → build-P42YFKQV.js} +34 -3
- package/dist/{chunk-Z2S2HIV5.js → chunk-2NICNKOM.js} +2 -2
- package/dist/{chunk-B4NF3OLW.js → chunk-4JRYGIO7.js} +56 -2
- package/dist/chunk-4QXB6PEO.js +232 -0
- package/dist/chunk-6CZSKEY5.js +164 -0
- package/dist/{chunk-O5OMJMIE.js → chunk-7P3S7MAY.js} +502 -2
- package/dist/chunk-A5W4GNQO.js +130 -0
- package/dist/chunk-AKW5YVCE.js +96 -0
- package/dist/chunk-DPVS43ZT.js +608 -0
- package/dist/{chunk-EIUHJXBB.js → chunk-GR6DGCZ2.js} +1 -1
- package/dist/chunk-KEST3MWO.js +324 -0
- package/dist/{chunk-D7BGWV2J.js → chunk-NF5POFCI.js} +5 -3
- package/dist/{chunk-FZQCRGUU.js → chunk-OHAC6HJE.js} +27 -3
- package/dist/chunk-OT6PXH54.js +61 -0
- package/dist/{chunk-ITJ3LCPG.js → chunk-PDOZHZWL.js} +1 -1
- package/dist/{chunk-T4X42QXC.js → chunk-Q6O7ZLO2.js} +0 -59
- package/dist/{chunk-FYPYZFV5.js → chunk-QPASI2BR.js} +1 -1
- package/dist/{chunk-EQXFOKH2.js → chunk-RWXVAH6P.js} +27 -3
- package/dist/{chunk-CROPZ75A.js → chunk-SKU3GAPD.js} +27 -3
- package/dist/chunk-YZFATT7X.js +9 -0
- package/dist/cli/neuroverse.cjs +5343 -732
- package/dist/cli/neuroverse.js +69 -13
- package/dist/cli/plan.cjs +1599 -0
- package/dist/cli/plan.d.cts +20 -0
- package/dist/cli/plan.d.ts +20 -0
- package/dist/cli/plan.js +361 -0
- package/dist/cli/run.cjs +1746 -0
- package/dist/cli/run.d.cts +20 -0
- package/dist/cli/run.d.ts +20 -0
- package/dist/cli/run.js +143 -0
- package/dist/{configure-ai-46JVG56I.js → configure-ai-TK67ZWZL.js} +5 -2
- package/dist/{derive-6NAEWLM5.js → derive-TLIV4OOU.js} +6 -4
- package/dist/doctor-QV6HELS5.js +170 -0
- package/dist/{explain-3B3VB6TL.js → explain-IDCRWMPX.js} +2 -1
- package/dist/{guard-67Y66P3I.js → guard-GFLQZY6U.js} +20 -6
- package/dist/{guard-contract-D_RQz9kt.d.ts → guard-contract-Cm91Kp4j.d.cts} +182 -2
- package/dist/{guard-contract-D_RQz9kt.d.cts → guard-contract-Cm91Kp4j.d.ts} +182 -2
- package/dist/guard-engine-JLTUARGU.js +10 -0
- package/dist/{impact-CHERK3O6.js → impact-XPECYRLH.js} +5 -3
- package/dist/{improve-YG6I6ERG.js → improve-GPUBKTEA.js} +4 -3
- package/dist/index.cjs +2135 -89
- package/dist/index.d.cts +481 -12
- package/dist/index.d.ts +481 -12
- package/dist/index.js +70 -20
- package/dist/{init-Z66T6TDI.js → init-PKPIYHYE.js} +2 -0
- package/dist/mcp-server-LZVJHBT5.js +13 -0
- package/dist/model-adapter-BB7G4MFI.js +11 -0
- package/dist/playground-FGOMASHN.js +550 -0
- package/dist/redteam-SK7AMIG3.js +357 -0
- package/dist/session-VISISNWJ.js +14 -0
- package/dist/{simulate-ETHHINZ4.js → simulate-VDOYQFRO.js} +2 -1
- package/dist/test-75AVHC3R.js +217 -0
- package/dist/{trace-3YODSSIP.js → trace-JVF67VR3.js} +4 -2
- package/dist/{validate-UVE6GKQU.js → validate-LLBWVPGV.js} +15 -6
- package/dist/validate-engine-UIABSIHD.js +7 -0
- package/dist/{world-WLNHL5XC.js → world-LAXO6DOX.js} +87 -7
- package/dist/world-loader-HMPTOEA2.js +9 -0
- package/package.json +19 -5
- package/dist/validate-engine-657D75OG.js +0 -6
- /package/dist/{chunk-M3TZFGHO.js → chunk-JZPQGIKR.js} +0 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import {
|
|
2
|
+
evaluateGuard
|
|
3
|
+
} from "./chunk-4JRYGIO7.js";
|
|
4
|
+
import {
|
|
5
|
+
loadWorld
|
|
6
|
+
} from "./chunk-JZPQGIKR.js";
|
|
7
|
+
import {
|
|
8
|
+
advancePlan,
|
|
9
|
+
evaluatePlan,
|
|
10
|
+
getPlanProgress
|
|
11
|
+
} from "./chunk-4QXB6PEO.js";
|
|
12
|
+
|
|
13
|
+
// src/runtime/session.ts
|
|
14
|
+
async function defaultToolExecutor(name, args) {
|
|
15
|
+
return `Tool "${name}" executed successfully with args: ${JSON.stringify(args)}`;
|
|
16
|
+
}
|
|
17
|
+
var SessionManager = class {
|
|
18
|
+
config;
|
|
19
|
+
state;
|
|
20
|
+
engineOptions;
|
|
21
|
+
executor;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
this.executor = config.toolExecutor ?? defaultToolExecutor;
|
|
25
|
+
this.engineOptions = {
|
|
26
|
+
trace: config.trace ?? false,
|
|
27
|
+
level: config.level,
|
|
28
|
+
plan: config.plan
|
|
29
|
+
};
|
|
30
|
+
this.state = {
|
|
31
|
+
active: false,
|
|
32
|
+
world: config.world,
|
|
33
|
+
plan: config.plan,
|
|
34
|
+
progress: config.plan ? getPlanProgress(config.plan) : void 0,
|
|
35
|
+
actionsEvaluated: 0,
|
|
36
|
+
actionsAllowed: 0,
|
|
37
|
+
actionsBlocked: 0,
|
|
38
|
+
actionsPaused: 0
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Initialize the session — load world from disk if needed.
|
|
43
|
+
*/
|
|
44
|
+
async start() {
|
|
45
|
+
if (this.config.worldPath && !this.config.world) {
|
|
46
|
+
this.state.world = await loadWorld(this.config.worldPath);
|
|
47
|
+
}
|
|
48
|
+
if (!this.state.world) {
|
|
49
|
+
throw new Error("No world provided. Use --world or pass a world definition.");
|
|
50
|
+
}
|
|
51
|
+
this.state.active = true;
|
|
52
|
+
return this.getState();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Evaluate a single event against governance.
|
|
56
|
+
* Returns the verdict without executing anything.
|
|
57
|
+
*/
|
|
58
|
+
evaluate(event) {
|
|
59
|
+
this.engineOptions.plan = this.state.plan;
|
|
60
|
+
const verdict = evaluateGuard(event, this.state.world, this.engineOptions);
|
|
61
|
+
this.state.actionsEvaluated++;
|
|
62
|
+
if (verdict.status === "ALLOW") this.state.actionsAllowed++;
|
|
63
|
+
if (verdict.status === "BLOCK") this.state.actionsBlocked++;
|
|
64
|
+
if (verdict.status === "PAUSE") this.state.actionsPaused++;
|
|
65
|
+
this.config.onVerdict?.(verdict, event);
|
|
66
|
+
return verdict;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Evaluate and execute a tool call.
|
|
70
|
+
* Returns the execution result or block reason.
|
|
71
|
+
*/
|
|
72
|
+
async executeToolCall(toolCall) {
|
|
73
|
+
let args;
|
|
74
|
+
try {
|
|
75
|
+
args = JSON.parse(toolCall.function.arguments);
|
|
76
|
+
} catch {
|
|
77
|
+
args = { raw: toolCall.function.arguments };
|
|
78
|
+
}
|
|
79
|
+
const event = {
|
|
80
|
+
intent: toolCall.function.name,
|
|
81
|
+
tool: toolCall.function.name,
|
|
82
|
+
args,
|
|
83
|
+
direction: "input"
|
|
84
|
+
};
|
|
85
|
+
const verdict = this.evaluate(event);
|
|
86
|
+
if (verdict.status === "BLOCK") {
|
|
87
|
+
return { allowed: false, verdict };
|
|
88
|
+
}
|
|
89
|
+
if (verdict.status === "PAUSE") {
|
|
90
|
+
return { allowed: false, verdict };
|
|
91
|
+
}
|
|
92
|
+
const result = await this.executor(toolCall.function.name, args);
|
|
93
|
+
this.config.onToolResult?.(toolCall.function.name, result);
|
|
94
|
+
if (this.state.plan) {
|
|
95
|
+
const planVerdict = evaluatePlan(event, this.state.plan);
|
|
96
|
+
if (planVerdict.matchedStep) {
|
|
97
|
+
const advResult = advancePlan(this.state.plan, planVerdict.matchedStep);
|
|
98
|
+
if (advResult.success && advResult.plan) {
|
|
99
|
+
this.state.plan = advResult.plan;
|
|
100
|
+
this.engineOptions.plan = this.state.plan;
|
|
101
|
+
}
|
|
102
|
+
this.state.progress = getPlanProgress(this.state.plan);
|
|
103
|
+
this.config.onPlanProgress?.(this.state.progress);
|
|
104
|
+
if (this.state.progress.completed === this.state.progress.total) {
|
|
105
|
+
this.config.onPlanComplete?.();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { allowed: true, verdict, result };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Process a model response — evaluate and execute all tool calls.
|
|
113
|
+
* Returns results for each tool call.
|
|
114
|
+
*/
|
|
115
|
+
async processModelResponse(response, model) {
|
|
116
|
+
if (response.toolCalls.length === 0) {
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
for (const toolCall of response.toolCalls) {
|
|
120
|
+
const { allowed, verdict, result } = await this.executeToolCall(toolCall);
|
|
121
|
+
if (allowed && result) {
|
|
122
|
+
const nextResponse = await model.sendToolResult(toolCall.id, result);
|
|
123
|
+
if (nextResponse.toolCalls.length > 0) {
|
|
124
|
+
return this.processModelResponse(nextResponse, model);
|
|
125
|
+
}
|
|
126
|
+
return nextResponse;
|
|
127
|
+
} else {
|
|
128
|
+
const reason = verdict.reason ?? "Action blocked by governance.";
|
|
129
|
+
const nextResponse = await model.sendBlockedResult(toolCall.id, reason);
|
|
130
|
+
if (nextResponse.toolCalls.length > 0) {
|
|
131
|
+
return this.processModelResponse(nextResponse, model);
|
|
132
|
+
}
|
|
133
|
+
return nextResponse;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return response;
|
|
137
|
+
}
|
|
138
|
+
/** Get current session state. */
|
|
139
|
+
getState() {
|
|
140
|
+
return { ...this.state };
|
|
141
|
+
}
|
|
142
|
+
/** Stop the session. */
|
|
143
|
+
stop() {
|
|
144
|
+
this.state.active = false;
|
|
145
|
+
return this.getState();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
async function runPipeMode(config) {
|
|
149
|
+
const session = new SessionManager(config);
|
|
150
|
+
await session.start();
|
|
151
|
+
const state = session.getState();
|
|
152
|
+
process.stderr.write(`[neuroverse] Pipe mode active
|
|
153
|
+
`);
|
|
154
|
+
process.stderr.write(`[neuroverse] World: ${state.world.world.name}
|
|
155
|
+
`);
|
|
156
|
+
if (state.plan) {
|
|
157
|
+
process.stderr.write(`[neuroverse] Plan: ${state.plan.plan_id} (${state.plan.objective})
|
|
158
|
+
`);
|
|
159
|
+
}
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
let buffer = "";
|
|
162
|
+
process.stdin.setEncoding("utf-8");
|
|
163
|
+
process.stdin.on("data", (chunk) => {
|
|
164
|
+
buffer += chunk;
|
|
165
|
+
const lines = buffer.split("\n");
|
|
166
|
+
buffer = lines.pop() ?? "";
|
|
167
|
+
for (const line of lines) {
|
|
168
|
+
const trimmed = line.trim();
|
|
169
|
+
if (!trimmed) continue;
|
|
170
|
+
try {
|
|
171
|
+
const event = JSON.parse(trimmed);
|
|
172
|
+
if (!event.intent) {
|
|
173
|
+
process.stderr.write(`[neuroverse] Warning: event missing "intent" field
|
|
174
|
+
`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const verdict = session.evaluate(event);
|
|
178
|
+
process.stdout.write(JSON.stringify(verdict) + "\n");
|
|
179
|
+
} catch (err) {
|
|
180
|
+
process.stderr.write(`[neuroverse] Error parsing line: ${err}
|
|
181
|
+
`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
process.stdin.on("end", () => {
|
|
186
|
+
if (buffer.trim()) {
|
|
187
|
+
try {
|
|
188
|
+
const event = JSON.parse(buffer.trim());
|
|
189
|
+
if (event.intent) {
|
|
190
|
+
const verdict = session.evaluate(event);
|
|
191
|
+
process.stdout.write(JSON.stringify(verdict) + "\n");
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const finalState = session.stop();
|
|
197
|
+
process.stderr.write(
|
|
198
|
+
`[neuroverse] Session complete: ${finalState.actionsEvaluated} evaluated, ${finalState.actionsAllowed} allowed, ${finalState.actionsBlocked} blocked, ${finalState.actionsPaused} paused
|
|
199
|
+
`
|
|
200
|
+
);
|
|
201
|
+
resolve();
|
|
202
|
+
});
|
|
203
|
+
process.stdin.on("error", reject);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
async function runInteractiveMode(config, model) {
|
|
207
|
+
const session = new SessionManager(config);
|
|
208
|
+
await session.start();
|
|
209
|
+
const state = session.getState();
|
|
210
|
+
process.stdout.write("\n");
|
|
211
|
+
process.stdout.write(` World: ${state.world.world.name}
|
|
212
|
+
`);
|
|
213
|
+
if (state.plan) {
|
|
214
|
+
process.stdout.write(` Plan: ${state.plan.plan_id}
|
|
215
|
+
`);
|
|
216
|
+
process.stdout.write(` Goal: ${state.plan.objective}
|
|
217
|
+
`);
|
|
218
|
+
process.stdout.write(` Steps: ${state.progress?.total ?? 0}
|
|
219
|
+
`);
|
|
220
|
+
}
|
|
221
|
+
process.stdout.write(` Type "exit" to end session.
|
|
222
|
+
`);
|
|
223
|
+
process.stdout.write("\n");
|
|
224
|
+
const readline = await import("readline");
|
|
225
|
+
const rl = readline.createInterface({
|
|
226
|
+
input: process.stdin,
|
|
227
|
+
output: process.stdout,
|
|
228
|
+
prompt: "> "
|
|
229
|
+
});
|
|
230
|
+
const printProgress = () => {
|
|
231
|
+
const s = session.getState();
|
|
232
|
+
if (s.progress) {
|
|
233
|
+
process.stdout.write(
|
|
234
|
+
` [plan: ${s.progress.completed}/${s.progress.total} (${s.progress.percentage}%)]
|
|
235
|
+
`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
rl.prompt();
|
|
240
|
+
rl.on("line", async (input) => {
|
|
241
|
+
const trimmed = input.trim();
|
|
242
|
+
if (!trimmed) {
|
|
243
|
+
rl.prompt();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (trimmed === "exit" || trimmed === "quit") {
|
|
247
|
+
const finalState = session.stop();
|
|
248
|
+
process.stdout.write("\n");
|
|
249
|
+
process.stdout.write(` Session complete.
|
|
250
|
+
`);
|
|
251
|
+
process.stdout.write(` Actions: ${finalState.actionsEvaluated} evaluated`);
|
|
252
|
+
process.stdout.write(`, ${finalState.actionsAllowed} allowed`);
|
|
253
|
+
process.stdout.write(`, ${finalState.actionsBlocked} blocked
|
|
254
|
+
`);
|
|
255
|
+
if (finalState.progress) {
|
|
256
|
+
process.stdout.write(
|
|
257
|
+
` Plan: ${finalState.progress.completed}/${finalState.progress.total} steps completed
|
|
258
|
+
`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
process.stdout.write("\n");
|
|
262
|
+
rl.close();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (trimmed === "status") {
|
|
266
|
+
const s = session.getState();
|
|
267
|
+
process.stdout.write(`
|
|
268
|
+
World: ${s.world.world.name}
|
|
269
|
+
`);
|
|
270
|
+
process.stdout.write(` Actions: ${s.actionsEvaluated} evaluated
|
|
271
|
+
`);
|
|
272
|
+
process.stdout.write(` Allowed: ${s.actionsAllowed} | Blocked: ${s.actionsBlocked} | Paused: ${s.actionsPaused}
|
|
273
|
+
`);
|
|
274
|
+
if (s.progress && s.plan) {
|
|
275
|
+
process.stdout.write(` Plan: ${s.plan.plan_id} \u2014 ${s.progress.completed}/${s.progress.total} (${s.progress.percentage}%)
|
|
276
|
+
`);
|
|
277
|
+
for (const step of s.plan.steps) {
|
|
278
|
+
const icon = step.status === "completed" ? "[x]" : "[ ]";
|
|
279
|
+
process.stdout.write(` ${icon} ${step.label}
|
|
280
|
+
`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
process.stdout.write("\n");
|
|
284
|
+
rl.prompt();
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
const response = await model.chat(trimmed);
|
|
289
|
+
if (response.toolCalls.length > 0) {
|
|
290
|
+
const finalResponse = await session.processModelResponse(response, model);
|
|
291
|
+
if (finalResponse.content) {
|
|
292
|
+
process.stdout.write(`
|
|
293
|
+
${finalResponse.content}
|
|
294
|
+
|
|
295
|
+
`);
|
|
296
|
+
}
|
|
297
|
+
printProgress();
|
|
298
|
+
} else if (response.content) {
|
|
299
|
+
process.stdout.write(`
|
|
300
|
+
${response.content}
|
|
301
|
+
|
|
302
|
+
`);
|
|
303
|
+
}
|
|
304
|
+
} catch (err) {
|
|
305
|
+
process.stderr.write(`
|
|
306
|
+
Error: ${err}
|
|
307
|
+
|
|
308
|
+
`);
|
|
309
|
+
}
|
|
310
|
+
rl.prompt();
|
|
311
|
+
});
|
|
312
|
+
rl.on("close", () => {
|
|
313
|
+
session.stop();
|
|
314
|
+
});
|
|
315
|
+
return new Promise((resolve) => {
|
|
316
|
+
rl.on("close", resolve);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export {
|
|
321
|
+
SessionManager,
|
|
322
|
+
runPipeMode,
|
|
323
|
+
runInteractiveMode
|
|
324
|
+
};
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createProvider
|
|
2
|
+
createProvider
|
|
3
|
+
} from "./chunk-Q6O7ZLO2.js";
|
|
4
|
+
import {
|
|
3
5
|
loadConfig
|
|
4
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OT6PXH54.js";
|
|
5
7
|
import {
|
|
6
8
|
emitWorldDefinition,
|
|
7
9
|
parseWorldMarkdown
|
|
8
10
|
} from "./chunk-XPDMYECO.js";
|
|
9
11
|
import {
|
|
10
12
|
validateWorld
|
|
11
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7P3S7MAY.js";
|
|
12
14
|
|
|
13
15
|
// src/engine/derive-normalizer.ts
|
|
14
16
|
function findSections(lines) {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluateGuard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4JRYGIO7.js";
|
|
4
4
|
import {
|
|
5
5
|
loadWorld
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JZPQGIKR.js";
|
|
7
|
+
import {
|
|
8
|
+
advancePlan,
|
|
9
|
+
evaluatePlan,
|
|
10
|
+
getPlanProgress
|
|
11
|
+
} from "./chunk-4QXB6PEO.js";
|
|
7
12
|
|
|
8
13
|
// src/adapters/openai.ts
|
|
9
14
|
var GovernanceBlockedError = class extends Error {
|
|
@@ -34,12 +39,15 @@ var GovernedToolExecutor = class {
|
|
|
34
39
|
engineOptions;
|
|
35
40
|
mapFn;
|
|
36
41
|
blockMsg;
|
|
42
|
+
activePlan;
|
|
37
43
|
constructor(world, options = {}) {
|
|
38
44
|
this.world = world;
|
|
39
45
|
this.options = options;
|
|
46
|
+
this.activePlan = options.plan;
|
|
40
47
|
this.engineOptions = {
|
|
41
48
|
trace: options.trace ?? false,
|
|
42
|
-
level: options.level
|
|
49
|
+
level: options.level,
|
|
50
|
+
plan: this.activePlan
|
|
43
51
|
};
|
|
44
52
|
this.mapFn = options.mapFunctionCall ?? defaultMapFunctionCall;
|
|
45
53
|
this.blockMsg = options.blockMessage ?? defaultBlockMessage;
|
|
@@ -56,8 +64,24 @@ var GovernedToolExecutor = class {
|
|
|
56
64
|
args = { raw: toolCall.function.arguments };
|
|
57
65
|
}
|
|
58
66
|
const event = this.mapFn(toolCall.function.name, args);
|
|
67
|
+
this.engineOptions.plan = this.activePlan;
|
|
59
68
|
const verdict = evaluateGuard(event, this.world, this.engineOptions);
|
|
60
69
|
this.options.onEvaluate?.(verdict, event);
|
|
70
|
+
if (verdict.status === "ALLOW" && this.activePlan) {
|
|
71
|
+
const planVerdict = evaluatePlan(event, this.activePlan);
|
|
72
|
+
if (planVerdict.matchedStep) {
|
|
73
|
+
const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
|
|
74
|
+
if (advResult.success && advResult.plan) {
|
|
75
|
+
this.activePlan = advResult.plan;
|
|
76
|
+
this.engineOptions.plan = this.activePlan;
|
|
77
|
+
}
|
|
78
|
+
const progress = getPlanProgress(this.activePlan);
|
|
79
|
+
this.options.onPlanProgress?.(progress);
|
|
80
|
+
if (progress.completed === progress.total) {
|
|
81
|
+
this.options.onPlanComplete?.();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
61
85
|
return verdict;
|
|
62
86
|
}
|
|
63
87
|
/**
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/providers/config-manager.ts
|
|
2
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
function getConfigDir() {
|
|
6
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
7
|
+
if (xdg) return join(xdg, "neuroverse");
|
|
8
|
+
return join(homedir(), ".neuroverse");
|
|
9
|
+
}
|
|
10
|
+
function getConfigPath() {
|
|
11
|
+
return join(getConfigDir(), "config.json");
|
|
12
|
+
}
|
|
13
|
+
async function loadConfig() {
|
|
14
|
+
try {
|
|
15
|
+
const raw = await readFile(getConfigPath(), "utf-8");
|
|
16
|
+
const parsed = JSON.parse(raw);
|
|
17
|
+
if (!parsed.provider || !parsed.model || !parsed.apiKey) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
provider: parsed.provider,
|
|
22
|
+
model: parsed.model,
|
|
23
|
+
apiKey: parsed.apiKey,
|
|
24
|
+
endpoint: parsed.endpoint ?? null
|
|
25
|
+
};
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function saveConfig(config) {
|
|
31
|
+
const dir = getConfigDir();
|
|
32
|
+
await mkdir(dir, { recursive: true });
|
|
33
|
+
const configPath = getConfigPath();
|
|
34
|
+
const content = JSON.stringify(
|
|
35
|
+
{
|
|
36
|
+
provider: config.provider,
|
|
37
|
+
model: config.model,
|
|
38
|
+
apiKey: config.apiKey,
|
|
39
|
+
endpoint: config.endpoint
|
|
40
|
+
},
|
|
41
|
+
null,
|
|
42
|
+
2
|
|
43
|
+
);
|
|
44
|
+
await writeFile(configPath, content, { mode: 384 });
|
|
45
|
+
await chmod(configPath, 384);
|
|
46
|
+
}
|
|
47
|
+
function redactConfig(config) {
|
|
48
|
+
return {
|
|
49
|
+
provider: config.provider,
|
|
50
|
+
model: config.model,
|
|
51
|
+
apiKey: config.apiKey ? `${config.apiKey.slice(0, 4)}...${config.apiKey.slice(-4)}` : "(not set)",
|
|
52
|
+
endpoint: config.endpoint
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
getConfigPath,
|
|
58
|
+
loadConfig,
|
|
59
|
+
saveConfig,
|
|
60
|
+
redactConfig
|
|
61
|
+
};
|
|
@@ -42,61 +42,6 @@ function createProvider(config) {
|
|
|
42
42
|
return new ChatCompletionsProvider(config);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
// src/providers/config-manager.ts
|
|
46
|
-
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
47
|
-
import { join } from "path";
|
|
48
|
-
import { homedir } from "os";
|
|
49
|
-
function getConfigDir() {
|
|
50
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
51
|
-
if (xdg) return join(xdg, "neuroverse");
|
|
52
|
-
return join(homedir(), ".neuroverse");
|
|
53
|
-
}
|
|
54
|
-
function getConfigPath() {
|
|
55
|
-
return join(getConfigDir(), "config.json");
|
|
56
|
-
}
|
|
57
|
-
async function loadConfig() {
|
|
58
|
-
try {
|
|
59
|
-
const raw = await readFile(getConfigPath(), "utf-8");
|
|
60
|
-
const parsed = JSON.parse(raw);
|
|
61
|
-
if (!parsed.provider || !parsed.model || !parsed.apiKey) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
provider: parsed.provider,
|
|
66
|
-
model: parsed.model,
|
|
67
|
-
apiKey: parsed.apiKey,
|
|
68
|
-
endpoint: parsed.endpoint ?? null
|
|
69
|
-
};
|
|
70
|
-
} catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
async function saveConfig(config) {
|
|
75
|
-
const dir = getConfigDir();
|
|
76
|
-
await mkdir(dir, { recursive: true });
|
|
77
|
-
const configPath = getConfigPath();
|
|
78
|
-
const content = JSON.stringify(
|
|
79
|
-
{
|
|
80
|
-
provider: config.provider,
|
|
81
|
-
model: config.model,
|
|
82
|
-
apiKey: config.apiKey,
|
|
83
|
-
endpoint: config.endpoint
|
|
84
|
-
},
|
|
85
|
-
null,
|
|
86
|
-
2
|
|
87
|
-
);
|
|
88
|
-
await writeFile(configPath, content, { mode: 384 });
|
|
89
|
-
await chmod(configPath, 384);
|
|
90
|
-
}
|
|
91
|
-
function redactConfig(config) {
|
|
92
|
-
return {
|
|
93
|
-
provider: config.provider,
|
|
94
|
-
model: config.model,
|
|
95
|
-
apiKey: config.apiKey ? `${config.apiKey.slice(0, 4)}...${config.apiKey.slice(-4)}` : "(not set)",
|
|
96
|
-
endpoint: config.endpoint
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
45
|
// src/contracts/derive-contract.ts
|
|
101
46
|
var DERIVE_EXIT_CODES = {
|
|
102
47
|
SUCCESS: 0,
|
|
@@ -112,10 +57,6 @@ var CONFIGURE_AI_EXIT_CODES = {
|
|
|
112
57
|
|
|
113
58
|
export {
|
|
114
59
|
createProvider,
|
|
115
|
-
getConfigPath,
|
|
116
|
-
loadConfig,
|
|
117
|
-
saveConfig,
|
|
118
|
-
redactConfig,
|
|
119
60
|
DERIVE_EXIT_CODES,
|
|
120
61
|
CONFIGURE_AI_EXIT_CODES
|
|
121
62
|
};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluateGuard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4JRYGIO7.js";
|
|
4
4
|
import {
|
|
5
5
|
loadWorld
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JZPQGIKR.js";
|
|
7
|
+
import {
|
|
8
|
+
advancePlan,
|
|
9
|
+
evaluatePlan,
|
|
10
|
+
getPlanProgress
|
|
11
|
+
} from "./chunk-4QXB6PEO.js";
|
|
7
12
|
|
|
8
13
|
// src/adapters/langchain.ts
|
|
9
14
|
var GovernanceBlockedError = class extends Error {
|
|
@@ -31,12 +36,15 @@ var NeuroVerseCallbackHandler = class {
|
|
|
31
36
|
options;
|
|
32
37
|
engineOptions;
|
|
33
38
|
mapToolCall;
|
|
39
|
+
activePlan;
|
|
34
40
|
constructor(world, options = {}) {
|
|
35
41
|
this.world = world;
|
|
36
42
|
this.options = options;
|
|
43
|
+
this.activePlan = options.plan;
|
|
37
44
|
this.engineOptions = {
|
|
38
45
|
trace: options.trace ?? false,
|
|
39
|
-
level: options.level
|
|
46
|
+
level: options.level,
|
|
47
|
+
plan: this.activePlan
|
|
40
48
|
};
|
|
41
49
|
this.mapToolCall = options.mapToolCall ?? defaultMapToolCall;
|
|
42
50
|
}
|
|
@@ -55,6 +63,7 @@ var NeuroVerseCallbackHandler = class {
|
|
|
55
63
|
parsedInput = { raw: input };
|
|
56
64
|
}
|
|
57
65
|
const event = this.mapToolCall(tool.name, parsedInput);
|
|
66
|
+
this.engineOptions.plan = this.activePlan;
|
|
58
67
|
const verdict = evaluateGuard(event, this.world, this.engineOptions);
|
|
59
68
|
this.options.onEvaluate?.(verdict, event);
|
|
60
69
|
if (verdict.status === "BLOCK") {
|
|
@@ -67,6 +76,21 @@ var NeuroVerseCallbackHandler = class {
|
|
|
67
76
|
throw new GovernanceBlockedError(verdict, event);
|
|
68
77
|
}
|
|
69
78
|
}
|
|
79
|
+
if (verdict.status === "ALLOW" && this.activePlan) {
|
|
80
|
+
const planVerdict = evaluatePlan(event, this.activePlan);
|
|
81
|
+
if (planVerdict.matchedStep) {
|
|
82
|
+
const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
|
|
83
|
+
if (advResult.success && advResult.plan) {
|
|
84
|
+
this.activePlan = advResult.plan;
|
|
85
|
+
this.engineOptions.plan = this.activePlan;
|
|
86
|
+
}
|
|
87
|
+
const progress = getPlanProgress(this.activePlan);
|
|
88
|
+
this.options.onPlanProgress?.(progress);
|
|
89
|
+
if (progress.completed === progress.total) {
|
|
90
|
+
this.options.onPlanComplete?.();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
70
94
|
}
|
|
71
95
|
};
|
|
72
96
|
async function createNeuroVerseCallbackHandler(worldPath, options) {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
evaluateGuard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4JRYGIO7.js";
|
|
4
4
|
import {
|
|
5
5
|
loadWorld
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JZPQGIKR.js";
|
|
7
|
+
import {
|
|
8
|
+
advancePlan,
|
|
9
|
+
evaluatePlan,
|
|
10
|
+
getPlanProgress
|
|
11
|
+
} from "./chunk-4QXB6PEO.js";
|
|
7
12
|
|
|
8
13
|
// src/adapters/openclaw.ts
|
|
9
14
|
var GovernanceBlockedError = class extends Error {
|
|
@@ -31,12 +36,15 @@ var NeuroVersePlugin = class {
|
|
|
31
36
|
options;
|
|
32
37
|
engineOptions;
|
|
33
38
|
mapAction;
|
|
39
|
+
activePlan;
|
|
34
40
|
constructor(world, options = {}) {
|
|
35
41
|
this.world = world;
|
|
36
42
|
this.options = options;
|
|
43
|
+
this.activePlan = options.plan;
|
|
37
44
|
this.engineOptions = {
|
|
38
45
|
trace: options.trace ?? false,
|
|
39
|
-
level: options.level
|
|
46
|
+
level: options.level,
|
|
47
|
+
plan: this.activePlan
|
|
40
48
|
};
|
|
41
49
|
this.mapAction = options.mapAction ?? defaultMapAction;
|
|
42
50
|
}
|
|
@@ -48,6 +56,7 @@ var NeuroVersePlugin = class {
|
|
|
48
56
|
*/
|
|
49
57
|
beforeAction(action) {
|
|
50
58
|
const event = this.mapAction(action, "input");
|
|
59
|
+
this.engineOptions.plan = this.activePlan;
|
|
51
60
|
const verdict = evaluateGuard(event, this.world, this.engineOptions);
|
|
52
61
|
const result = {
|
|
53
62
|
allowed: verdict.status === "ALLOW",
|
|
@@ -58,6 +67,21 @@ var NeuroVersePlugin = class {
|
|
|
58
67
|
if (verdict.status === "BLOCK") {
|
|
59
68
|
throw new GovernanceBlockedError(verdict, action);
|
|
60
69
|
}
|
|
70
|
+
if (verdict.status === "ALLOW" && this.activePlan) {
|
|
71
|
+
const planVerdict = evaluatePlan(event, this.activePlan);
|
|
72
|
+
if (planVerdict.matchedStep) {
|
|
73
|
+
const advResult = advancePlan(this.activePlan, planVerdict.matchedStep);
|
|
74
|
+
if (advResult.success && advResult.plan) {
|
|
75
|
+
this.activePlan = advResult.plan;
|
|
76
|
+
this.engineOptions.plan = this.activePlan;
|
|
77
|
+
}
|
|
78
|
+
const progress = getPlanProgress(this.activePlan);
|
|
79
|
+
this.options.onPlanProgress?.(progress);
|
|
80
|
+
if (progress.completed === progress.total) {
|
|
81
|
+
this.options.onPlanComplete?.();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
61
85
|
return result;
|
|
62
86
|
}
|
|
63
87
|
/**
|