@agent-e/server 1.4.0 → 1.4.4
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/dist/AgentEServer-45WN6DK4.mjs +7 -0
- package/dist/{chunk-VNNX52KX.mjs → chunk-QU3P7LLI.mjs} +143 -115
- package/dist/chunk-QU3P7LLI.mjs.map +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +538 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +28 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +14 -8
- package/dist/index.d.ts +14 -8
- package/dist/index.js +143 -115
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +26 -4
- package/dist/AgentEServer-IF7QK2SK.mjs +0 -7
- package/dist/chunk-VNNX52KX.mjs.map +0 -1
- /package/dist/{AgentEServer-IF7QK2SK.mjs.map → AgentEServer-45WN6DK4.mjs.map} +0 -0
package/dist/index.d.mts
CHANGED
|
@@ -3,12 +3,15 @@ import { AgentEConfig, AgentE, EconomyState, EconomicEvent, Diagnosis, AgentEMod
|
|
|
3
3
|
interface ServerConfig {
|
|
4
4
|
port?: number;
|
|
5
5
|
host?: string;
|
|
6
|
-
|
|
6
|
+
agentE?: Partial<Omit<AgentEConfig, 'adapter'>>;
|
|
7
|
+
validateState?: boolean;
|
|
8
|
+
corsOrigin?: string;
|
|
7
9
|
}
|
|
8
|
-
interface
|
|
9
|
-
|
|
10
|
+
interface EnrichedAdjustment {
|
|
11
|
+
parameter: string;
|
|
10
12
|
value: number;
|
|
11
13
|
currency?: string;
|
|
14
|
+
reasoning: string;
|
|
12
15
|
}
|
|
13
16
|
declare class AgentEServer {
|
|
14
17
|
private readonly agentE;
|
|
@@ -16,10 +19,12 @@ declare class AgentEServer {
|
|
|
16
19
|
private lastState;
|
|
17
20
|
private adjustmentQueue;
|
|
18
21
|
private alerts;
|
|
19
|
-
|
|
22
|
+
readonly port: number;
|
|
20
23
|
private readonly host;
|
|
21
24
|
private readonly startedAt;
|
|
22
25
|
private cleanupWs;
|
|
26
|
+
readonly validateState: boolean;
|
|
27
|
+
readonly corsOrigin: string;
|
|
23
28
|
constructor(config?: ServerConfig);
|
|
24
29
|
start(): Promise<void>;
|
|
25
30
|
stop(): Promise<void>;
|
|
@@ -35,13 +40,14 @@ declare class AgentEServer {
|
|
|
35
40
|
* 2. Set state
|
|
36
41
|
* 3. Ingest events
|
|
37
42
|
* 4. Run agentE.tick(state)
|
|
38
|
-
* 5. Drain adjustment queue
|
|
43
|
+
* 5. Drain adjustment queue, enrich with reasoning from decisions
|
|
39
44
|
* 6. Return response
|
|
40
45
|
*/
|
|
41
46
|
processTick(state: EconomyState, events?: EconomicEvent[]): Promise<{
|
|
42
|
-
adjustments:
|
|
47
|
+
adjustments: EnrichedAdjustment[];
|
|
43
48
|
alerts: Diagnosis[];
|
|
44
49
|
health: number;
|
|
50
|
+
tick: number;
|
|
45
51
|
decisions: ReturnType<AgentE['getDecisions']>;
|
|
46
52
|
}>;
|
|
47
53
|
/**
|
|
@@ -66,10 +72,10 @@ declare class AgentEServer {
|
|
|
66
72
|
* @example
|
|
67
73
|
* ```ts
|
|
68
74
|
* import { startServer } from '@agent-e/server';
|
|
69
|
-
* const server = await startServer({ port:
|
|
75
|
+
* const server = await startServer({ port: 3100 });
|
|
70
76
|
* // POST /tick, GET /health, etc.
|
|
71
77
|
* ```
|
|
72
78
|
*/
|
|
73
79
|
declare function startServer(config?: ServerConfig): Promise<AgentEServer>;
|
|
74
80
|
|
|
75
|
-
export { AgentEServer, type ServerConfig, startServer };
|
|
81
|
+
export { AgentEServer, type EnrichedAdjustment, type ServerConfig, startServer };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,12 +3,15 @@ import { AgentEConfig, AgentE, EconomyState, EconomicEvent, Diagnosis, AgentEMod
|
|
|
3
3
|
interface ServerConfig {
|
|
4
4
|
port?: number;
|
|
5
5
|
host?: string;
|
|
6
|
-
|
|
6
|
+
agentE?: Partial<Omit<AgentEConfig, 'adapter'>>;
|
|
7
|
+
validateState?: boolean;
|
|
8
|
+
corsOrigin?: string;
|
|
7
9
|
}
|
|
8
|
-
interface
|
|
9
|
-
|
|
10
|
+
interface EnrichedAdjustment {
|
|
11
|
+
parameter: string;
|
|
10
12
|
value: number;
|
|
11
13
|
currency?: string;
|
|
14
|
+
reasoning: string;
|
|
12
15
|
}
|
|
13
16
|
declare class AgentEServer {
|
|
14
17
|
private readonly agentE;
|
|
@@ -16,10 +19,12 @@ declare class AgentEServer {
|
|
|
16
19
|
private lastState;
|
|
17
20
|
private adjustmentQueue;
|
|
18
21
|
private alerts;
|
|
19
|
-
|
|
22
|
+
readonly port: number;
|
|
20
23
|
private readonly host;
|
|
21
24
|
private readonly startedAt;
|
|
22
25
|
private cleanupWs;
|
|
26
|
+
readonly validateState: boolean;
|
|
27
|
+
readonly corsOrigin: string;
|
|
23
28
|
constructor(config?: ServerConfig);
|
|
24
29
|
start(): Promise<void>;
|
|
25
30
|
stop(): Promise<void>;
|
|
@@ -35,13 +40,14 @@ declare class AgentEServer {
|
|
|
35
40
|
* 2. Set state
|
|
36
41
|
* 3. Ingest events
|
|
37
42
|
* 4. Run agentE.tick(state)
|
|
38
|
-
* 5. Drain adjustment queue
|
|
43
|
+
* 5. Drain adjustment queue, enrich with reasoning from decisions
|
|
39
44
|
* 6. Return response
|
|
40
45
|
*/
|
|
41
46
|
processTick(state: EconomyState, events?: EconomicEvent[]): Promise<{
|
|
42
|
-
adjustments:
|
|
47
|
+
adjustments: EnrichedAdjustment[];
|
|
43
48
|
alerts: Diagnosis[];
|
|
44
49
|
health: number;
|
|
50
|
+
tick: number;
|
|
45
51
|
decisions: ReturnType<AgentE['getDecisions']>;
|
|
46
52
|
}>;
|
|
47
53
|
/**
|
|
@@ -66,10 +72,10 @@ declare class AgentEServer {
|
|
|
66
72
|
* @example
|
|
67
73
|
* ```ts
|
|
68
74
|
* import { startServer } from '@agent-e/server';
|
|
69
|
-
* const server = await startServer({ port:
|
|
75
|
+
* const server = await startServer({ port: 3100 });
|
|
70
76
|
* // POST /tick, GET /health, etc.
|
|
71
77
|
* ```
|
|
72
78
|
*/
|
|
73
79
|
declare function startServer(config?: ServerConfig): Promise<AgentEServer>;
|
|
74
80
|
|
|
75
|
-
export { AgentEServer, type ServerConfig, startServer };
|
|
81
|
+
export { AgentEServer, type EnrichedAdjustment, type ServerConfig, startServer };
|
package/dist/index.js
CHANGED
|
@@ -31,31 +31,41 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
33
|
// src/routes.ts
|
|
34
|
-
function setCorsHeaders(res) {
|
|
35
|
-
res.setHeader("Access-Control-Allow-Origin",
|
|
34
|
+
function setCorsHeaders(res, origin) {
|
|
35
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
36
36
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
37
37
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
38
38
|
}
|
|
39
|
-
function json(res, status, data) {
|
|
40
|
-
setCorsHeaders(res);
|
|
39
|
+
function json(res, status, data, origin) {
|
|
40
|
+
setCorsHeaders(res, origin);
|
|
41
41
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
42
42
|
res.end(JSON.stringify(data));
|
|
43
43
|
}
|
|
44
44
|
function readBody(req) {
|
|
45
45
|
return new Promise((resolve, reject) => {
|
|
46
46
|
const chunks = [];
|
|
47
|
-
|
|
47
|
+
let totalBytes = 0;
|
|
48
|
+
req.on("data", (chunk) => {
|
|
49
|
+
totalBytes += chunk.length;
|
|
50
|
+
if (totalBytes > MAX_BODY_BYTES) {
|
|
51
|
+
req.destroy();
|
|
52
|
+
reject(new Error("Request body too large"));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
chunks.push(chunk);
|
|
56
|
+
});
|
|
48
57
|
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
|
|
49
58
|
req.on("error", reject);
|
|
50
59
|
});
|
|
51
60
|
}
|
|
52
61
|
function createRouteHandler(server) {
|
|
62
|
+
const cors = server.corsOrigin;
|
|
53
63
|
return async (req, res) => {
|
|
54
64
|
const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
55
65
|
const path = url.pathname;
|
|
56
66
|
const method = req.method?.toUpperCase() ?? "GET";
|
|
57
67
|
if (method === "OPTIONS") {
|
|
58
|
-
setCorsHeaders(res);
|
|
68
|
+
setCorsHeaders(res, cors);
|
|
59
69
|
res.writeHead(204);
|
|
60
70
|
res.end();
|
|
61
71
|
return;
|
|
@@ -67,47 +77,44 @@ function createRouteHandler(server) {
|
|
|
67
77
|
try {
|
|
68
78
|
parsed = JSON.parse(body);
|
|
69
79
|
} catch {
|
|
70
|
-
json(res, 400, { error: "Invalid JSON" });
|
|
80
|
+
json(res, 400, { error: "Invalid JSON" }, cors);
|
|
71
81
|
return;
|
|
72
82
|
}
|
|
73
83
|
if (!parsed || typeof parsed !== "object") {
|
|
74
|
-
json(res, 400, { error: "Body must be a JSON object" });
|
|
84
|
+
json(res, 400, { error: "Body must be a JSON object" }, cors);
|
|
75
85
|
return;
|
|
76
86
|
}
|
|
77
87
|
const payload = parsed;
|
|
78
88
|
const state = payload["state"] ?? parsed;
|
|
79
89
|
const events = payload["events"];
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
if (server.validateState) {
|
|
91
|
+
const validation = (0, import_core.validateEconomyState)(state);
|
|
92
|
+
if (!validation.valid) {
|
|
93
|
+
json(res, 400, {
|
|
94
|
+
error: "invalid_state",
|
|
95
|
+
validationErrors: validation.errors
|
|
96
|
+
}, cors);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
87
99
|
}
|
|
88
100
|
const result = await server.processTick(
|
|
89
101
|
state,
|
|
90
102
|
Array.isArray(events) ? events : void 0
|
|
91
103
|
);
|
|
104
|
+
const warnings = server.validateState ? (0, import_core.validateEconomyState)(state).warnings : [];
|
|
92
105
|
json(res, 200, {
|
|
93
106
|
adjustments: result.adjustments,
|
|
94
107
|
alerts: result.alerts.map((a) => ({
|
|
95
|
-
|
|
96
|
-
|
|
108
|
+
principleId: a.principle.id,
|
|
109
|
+
principleName: a.principle.name,
|
|
97
110
|
severity: a.violation.severity,
|
|
98
111
|
evidence: a.violation.evidence,
|
|
99
|
-
|
|
112
|
+
reasoning: a.violation.suggestedAction.reasoning
|
|
100
113
|
})),
|
|
101
114
|
health: result.health,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
principle: d.diagnosis.principle.id,
|
|
106
|
-
parameter: d.plan.parameter,
|
|
107
|
-
result: d.result,
|
|
108
|
-
reasoning: d.reasoning
|
|
109
|
-
}))
|
|
110
|
-
});
|
|
115
|
+
tick: result.tick,
|
|
116
|
+
...warnings.length > 0 ? { validationWarnings: warnings } : {}
|
|
117
|
+
}, cors);
|
|
111
118
|
return;
|
|
112
119
|
}
|
|
113
120
|
if (path === "/health" && method === "GET") {
|
|
@@ -118,11 +125,11 @@ function createRouteHandler(server) {
|
|
|
118
125
|
mode: agentE.getMode(),
|
|
119
126
|
activePlans: agentE.getActivePlans().length,
|
|
120
127
|
uptime: server.getUptime()
|
|
121
|
-
});
|
|
128
|
+
}, cors);
|
|
122
129
|
return;
|
|
123
130
|
}
|
|
124
131
|
if (path === "/decisions" && method === "GET") {
|
|
125
|
-
const limit = parseInt(url.searchParams.get("limit") ?? "
|
|
132
|
+
const limit = parseInt(url.searchParams.get("limit") ?? "100", 10);
|
|
126
133
|
const since = url.searchParams.get("since");
|
|
127
134
|
const agentE = server.getAgentE();
|
|
128
135
|
let decisions;
|
|
@@ -131,20 +138,7 @@ function createRouteHandler(server) {
|
|
|
131
138
|
} else {
|
|
132
139
|
decisions = agentE.log.latest(limit);
|
|
133
140
|
}
|
|
134
|
-
json(res, 200, {
|
|
135
|
-
decisions: decisions.map((d) => ({
|
|
136
|
-
id: d.id,
|
|
137
|
-
tick: d.tick,
|
|
138
|
-
timestamp: d.timestamp,
|
|
139
|
-
principle: d.diagnosis.principle.id,
|
|
140
|
-
principeName: d.diagnosis.principle.name,
|
|
141
|
-
parameter: d.plan.parameter,
|
|
142
|
-
currentValue: d.plan.currentValue,
|
|
143
|
-
targetValue: d.plan.targetValue,
|
|
144
|
-
result: d.result,
|
|
145
|
-
reasoning: d.reasoning
|
|
146
|
-
}))
|
|
147
|
-
});
|
|
141
|
+
json(res, 200, { decisions }, cors);
|
|
148
142
|
return;
|
|
149
143
|
}
|
|
150
144
|
if (path === "/config" && method === "POST") {
|
|
@@ -153,27 +147,32 @@ function createRouteHandler(server) {
|
|
|
153
147
|
try {
|
|
154
148
|
parsed = JSON.parse(body);
|
|
155
149
|
} catch {
|
|
156
|
-
json(res, 400, { error: "Invalid JSON" });
|
|
150
|
+
json(res, 400, { error: "Invalid JSON" }, cors);
|
|
157
151
|
return;
|
|
158
152
|
}
|
|
159
153
|
const config = parsed;
|
|
160
|
-
if (config["
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
154
|
+
if (Array.isArray(config["lock"])) {
|
|
155
|
+
for (const param of config["lock"]) {
|
|
156
|
+
if (typeof param === "string") server.lock(param);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (Array.isArray(config["unlock"])) {
|
|
160
|
+
for (const param of config["unlock"]) {
|
|
161
|
+
if (typeof param === "string") server.unlock(param);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (Array.isArray(config["constrain"])) {
|
|
165
|
+
for (const c of config["constrain"]) {
|
|
166
|
+
if (c && typeof c === "object" && typeof c["param"] === "string" && typeof c["min"] === "number" && typeof c["max"] === "number") {
|
|
167
|
+
const constraint = c;
|
|
168
|
+
server.constrain(constraint.param, { min: constraint.min, max: constraint.max });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (config["mode"] === "autonomous" || config["mode"] === "advisor") {
|
|
170
173
|
server.setMode(config["mode"]);
|
|
171
|
-
json(res, 200, { ok: true, action: "mode", mode: config["mode"] });
|
|
172
|
-
} else {
|
|
173
|
-
json(res, 400, {
|
|
174
|
-
error: "Invalid config action. Use: lock, unlock, constrain, or mode"
|
|
175
|
-
});
|
|
176
174
|
}
|
|
175
|
+
json(res, 200, { ok: true }, cors);
|
|
177
176
|
return;
|
|
178
177
|
}
|
|
179
178
|
if (path === "/principles" && method === "GET") {
|
|
@@ -186,7 +185,7 @@ function createRouteHandler(server) {
|
|
|
186
185
|
category: p.category,
|
|
187
186
|
description: p.description
|
|
188
187
|
}))
|
|
189
|
-
});
|
|
188
|
+
}, cors);
|
|
190
189
|
return;
|
|
191
190
|
}
|
|
192
191
|
if (path === "/diagnose" && method === "POST") {
|
|
@@ -195,40 +194,44 @@ function createRouteHandler(server) {
|
|
|
195
194
|
try {
|
|
196
195
|
parsed = JSON.parse(body);
|
|
197
196
|
} catch {
|
|
198
|
-
json(res, 400, { error: "Invalid JSON" });
|
|
197
|
+
json(res, 400, { error: "Invalid JSON" }, cors);
|
|
199
198
|
return;
|
|
200
199
|
}
|
|
201
200
|
const payload = parsed;
|
|
202
201
|
const state = payload["state"] ?? parsed;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
202
|
+
if (server.validateState) {
|
|
203
|
+
const validation = (0, import_core.validateEconomyState)(state);
|
|
204
|
+
if (!validation.valid) {
|
|
205
|
+
json(res, 400, { error: "invalid_state", validationErrors: validation.errors }, cors);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
207
208
|
}
|
|
208
209
|
const result = server.diagnoseOnly(state);
|
|
209
210
|
json(res, 200, {
|
|
210
211
|
health: result.health,
|
|
211
212
|
diagnoses: result.diagnoses.map((d) => ({
|
|
212
|
-
|
|
213
|
-
|
|
213
|
+
principleId: d.principle.id,
|
|
214
|
+
principleName: d.principle.name,
|
|
214
215
|
severity: d.violation.severity,
|
|
215
216
|
evidence: d.violation.evidence,
|
|
216
217
|
suggestedAction: d.violation.suggestedAction
|
|
217
218
|
}))
|
|
218
|
-
});
|
|
219
|
+
}, cors);
|
|
219
220
|
return;
|
|
220
221
|
}
|
|
221
|
-
json(res, 404, { error: "Not found" });
|
|
222
|
+
json(res, 404, { error: "Not found" }, cors);
|
|
222
223
|
} catch (err) {
|
|
223
|
-
|
|
224
|
+
console.error("[AgentE Server] Unhandled route error:", err);
|
|
225
|
+
json(res, 500, { error: "Internal server error" }, cors);
|
|
224
226
|
}
|
|
225
227
|
};
|
|
226
228
|
}
|
|
227
|
-
var import_core;
|
|
229
|
+
var import_core, MAX_BODY_BYTES;
|
|
228
230
|
var init_routes = __esm({
|
|
229
231
|
"src/routes.ts"() {
|
|
230
232
|
"use strict";
|
|
231
233
|
import_core = require("@agent-e/core");
|
|
234
|
+
MAX_BODY_BYTES = 1048576;
|
|
232
235
|
}
|
|
233
236
|
});
|
|
234
237
|
|
|
@@ -240,40 +243,53 @@ function send(ws, data) {
|
|
|
240
243
|
}
|
|
241
244
|
function createWebSocketHandler(httpServer, server) {
|
|
242
245
|
const wss = new import_ws.WebSocketServer({ server: httpServer });
|
|
246
|
+
const aliveMap = /* @__PURE__ */ new WeakMap();
|
|
243
247
|
const heartbeatInterval = setInterval(() => {
|
|
244
248
|
for (const ws of wss.clients) {
|
|
245
249
|
if (ws.readyState === import_ws.WebSocket.OPEN) {
|
|
250
|
+
if (aliveMap.get(ws) === false) {
|
|
251
|
+
ws.terminate();
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
aliveMap.set(ws, false);
|
|
246
255
|
ws.ping();
|
|
247
256
|
}
|
|
248
257
|
}
|
|
249
258
|
}, 3e4);
|
|
250
259
|
wss.on("connection", (ws) => {
|
|
260
|
+
console.log("[AgentE Server] Client connected");
|
|
261
|
+
aliveMap.set(ws, true);
|
|
262
|
+
ws.on("pong", () => {
|
|
263
|
+
aliveMap.set(ws, true);
|
|
264
|
+
});
|
|
265
|
+
ws.on("close", () => {
|
|
266
|
+
console.log("[AgentE Server] Client disconnected");
|
|
267
|
+
});
|
|
251
268
|
ws.on("message", async (raw) => {
|
|
252
269
|
let msg;
|
|
253
270
|
try {
|
|
254
271
|
msg = JSON.parse(raw.toString());
|
|
255
272
|
} catch {
|
|
256
|
-
send(ws, { type: "error",
|
|
273
|
+
send(ws, { type: "error", message: "Malformed JSON" });
|
|
257
274
|
return;
|
|
258
275
|
}
|
|
259
276
|
if (!msg.type || typeof msg.type !== "string") {
|
|
260
|
-
send(ws, { type: "error",
|
|
277
|
+
send(ws, { type: "error", message: 'Missing "type" field' });
|
|
261
278
|
return;
|
|
262
279
|
}
|
|
263
280
|
switch (msg.type) {
|
|
264
281
|
case "tick": {
|
|
265
282
|
const state = msg["state"];
|
|
266
283
|
const events = msg["events"];
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
if (server.validateState) {
|
|
285
|
+
const validation = (0, import_core2.validateEconomyState)(state);
|
|
286
|
+
if (!validation.valid) {
|
|
287
|
+
send(ws, { type: "validation_error", validationErrors: validation.errors });
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (validation.warnings.length > 0) {
|
|
291
|
+
send(ws, { type: "validation_warning", validationWarnings: validation.warnings });
|
|
272
292
|
}
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
for (const w of validation.warnings) {
|
|
276
|
-
send(ws, { type: "validation_warning", warning: w });
|
|
277
293
|
}
|
|
278
294
|
try {
|
|
279
295
|
const result = await server.processTick(
|
|
@@ -284,22 +300,16 @@ function createWebSocketHandler(httpServer, server) {
|
|
|
284
300
|
type: "tick_result",
|
|
285
301
|
adjustments: result.adjustments,
|
|
286
302
|
alerts: result.alerts.map((a) => ({
|
|
287
|
-
|
|
288
|
-
|
|
303
|
+
principleId: a.principle.id,
|
|
304
|
+
principleName: a.principle.name,
|
|
289
305
|
severity: a.violation.severity,
|
|
290
|
-
|
|
306
|
+
reasoning: a.violation.suggestedAction.reasoning
|
|
291
307
|
})),
|
|
292
308
|
health: result.health,
|
|
293
|
-
|
|
294
|
-
id: d.id,
|
|
295
|
-
tick: d.tick,
|
|
296
|
-
principle: d.diagnosis.principle.id,
|
|
297
|
-
parameter: d.plan.parameter,
|
|
298
|
-
result: d.result
|
|
299
|
-
}))
|
|
309
|
+
tick: result.tick
|
|
300
310
|
});
|
|
301
311
|
} catch (err) {
|
|
302
|
-
send(ws, { type: "error",
|
|
312
|
+
send(ws, { type: "error", message: "Tick processing failed" });
|
|
303
313
|
}
|
|
304
314
|
break;
|
|
305
315
|
}
|
|
@@ -309,7 +319,7 @@ function createWebSocketHandler(httpServer, server) {
|
|
|
309
319
|
server.getAgentE().ingest(event);
|
|
310
320
|
send(ws, { type: "event_ack" });
|
|
311
321
|
} else {
|
|
312
|
-
send(ws, { type: "error",
|
|
322
|
+
send(ws, { type: "error", message: 'Missing "event" field' });
|
|
313
323
|
}
|
|
314
324
|
break;
|
|
315
325
|
}
|
|
@@ -327,18 +337,20 @@ function createWebSocketHandler(httpServer, server) {
|
|
|
327
337
|
}
|
|
328
338
|
case "diagnose": {
|
|
329
339
|
const state = msg["state"];
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
340
|
+
if (server.validateState) {
|
|
341
|
+
const validation = (0, import_core2.validateEconomyState)(state);
|
|
342
|
+
if (!validation.valid) {
|
|
343
|
+
send(ws, { type: "validation_error", validationErrors: validation.errors });
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
334
346
|
}
|
|
335
347
|
const result = server.diagnoseOnly(state);
|
|
336
348
|
send(ws, {
|
|
337
349
|
type: "diagnose_result",
|
|
338
350
|
health: result.health,
|
|
339
351
|
diagnoses: result.diagnoses.map((d) => ({
|
|
340
|
-
|
|
341
|
-
|
|
352
|
+
principleId: d.principle.id,
|
|
353
|
+
principleName: d.principle.name,
|
|
342
354
|
severity: d.violation.severity,
|
|
343
355
|
suggestedAction: d.violation.suggestedAction
|
|
344
356
|
}))
|
|
@@ -346,7 +358,7 @@ function createWebSocketHandler(httpServer, server) {
|
|
|
346
358
|
break;
|
|
347
359
|
}
|
|
348
360
|
default:
|
|
349
|
-
send(ws, { type: "error",
|
|
361
|
+
send(ws, { type: "error", message: `Unknown message type: "${msg.type}"` });
|
|
350
362
|
}
|
|
351
363
|
});
|
|
352
364
|
});
|
|
@@ -384,8 +396,10 @@ var init_AgentEServer = __esm({
|
|
|
384
396
|
this.alerts = [];
|
|
385
397
|
this.startedAt = Date.now();
|
|
386
398
|
this.cleanupWs = null;
|
|
387
|
-
this.port = config.port ??
|
|
399
|
+
this.port = config.port ?? 3100;
|
|
388
400
|
this.host = config.host ?? "0.0.0.0";
|
|
401
|
+
this.validateState = config.validateState ?? true;
|
|
402
|
+
this.corsOrigin = config.corsOrigin ?? "*";
|
|
389
403
|
const adapter = {
|
|
390
404
|
getState: () => {
|
|
391
405
|
if (!this.lastState) {
|
|
@@ -407,16 +421,17 @@ var init_AgentEServer = __esm({
|
|
|
407
421
|
this.adjustmentQueue.push({ key, value });
|
|
408
422
|
}
|
|
409
423
|
};
|
|
424
|
+
const agentECfg = config.agentE ?? {};
|
|
410
425
|
const agentEConfig = {
|
|
411
426
|
adapter,
|
|
412
|
-
mode:
|
|
413
|
-
gracePeriod:
|
|
414
|
-
checkInterval:
|
|
415
|
-
...
|
|
416
|
-
...
|
|
417
|
-
...
|
|
418
|
-
...
|
|
419
|
-
...
|
|
427
|
+
mode: agentECfg.mode ?? "autonomous",
|
|
428
|
+
gracePeriod: agentECfg.gracePeriod ?? 0,
|
|
429
|
+
checkInterval: agentECfg.checkInterval ?? 1,
|
|
430
|
+
...agentECfg.dominantRoles ? { dominantRoles: agentECfg.dominantRoles } : {},
|
|
431
|
+
...agentECfg.idealDistribution ? { idealDistribution: agentECfg.idealDistribution } : {},
|
|
432
|
+
...agentECfg.maxAdjustmentPercent !== void 0 ? { maxAdjustmentPercent: agentECfg.maxAdjustmentPercent } : {},
|
|
433
|
+
...agentECfg.cooldownTicks !== void 0 ? { cooldownTicks: agentECfg.cooldownTicks } : {},
|
|
434
|
+
...agentECfg.thresholds ? { thresholds: agentECfg.thresholds } : {}
|
|
420
435
|
};
|
|
421
436
|
this.agentE = new import_core3.AgentE(agentEConfig);
|
|
422
437
|
this.agentE.on("alert", (diagnosis) => {
|
|
@@ -430,6 +445,8 @@ var init_AgentEServer = __esm({
|
|
|
430
445
|
this.cleanupWs = createWebSocketHandler(this.server, this);
|
|
431
446
|
return new Promise((resolve) => {
|
|
432
447
|
this.server.listen(this.port, this.host, () => {
|
|
448
|
+
const addr = this.getAddress();
|
|
449
|
+
console.log(`[AgentE Server] Listening on http://${addr.host}:${addr.port}`);
|
|
433
450
|
resolve();
|
|
434
451
|
});
|
|
435
452
|
});
|
|
@@ -463,7 +480,7 @@ var init_AgentEServer = __esm({
|
|
|
463
480
|
* 2. Set state
|
|
464
481
|
* 3. Ingest events
|
|
465
482
|
* 4. Run agentE.tick(state)
|
|
466
|
-
* 5. Drain adjustment queue
|
|
483
|
+
* 5. Drain adjustment queue, enrich with reasoning from decisions
|
|
467
484
|
* 6. Return response
|
|
468
485
|
*/
|
|
469
486
|
async processTick(state, events) {
|
|
@@ -476,13 +493,25 @@ var init_AgentEServer = __esm({
|
|
|
476
493
|
}
|
|
477
494
|
}
|
|
478
495
|
await this.agentE.tick(state);
|
|
479
|
-
const
|
|
496
|
+
const rawAdj = [...this.adjustmentQueue];
|
|
480
497
|
this.adjustmentQueue = [];
|
|
481
498
|
const decisions = this.agentE.getDecisions({ since: state.tick, until: state.tick });
|
|
499
|
+
const adjustments = rawAdj.map((adj) => {
|
|
500
|
+
const decision = decisions.find(
|
|
501
|
+
(d) => d.plan.parameter === adj.key && d.result === "applied"
|
|
502
|
+
);
|
|
503
|
+
return {
|
|
504
|
+
parameter: adj.key,
|
|
505
|
+
value: adj.value,
|
|
506
|
+
...adj.currency ? { currency: adj.currency } : {},
|
|
507
|
+
reasoning: decision?.diagnosis.violation.suggestedAction.reasoning ?? ""
|
|
508
|
+
};
|
|
509
|
+
});
|
|
482
510
|
return {
|
|
483
511
|
adjustments,
|
|
484
512
|
alerts: [...this.alerts],
|
|
485
513
|
health: this.agentE.getHealth(),
|
|
514
|
+
tick: state.tick,
|
|
486
515
|
decisions
|
|
487
516
|
};
|
|
488
517
|
}
|
|
@@ -492,9 +521,8 @@ var init_AgentEServer = __esm({
|
|
|
492
521
|
diagnoseOnly(state) {
|
|
493
522
|
const prevState = this.lastState;
|
|
494
523
|
this.lastState = state;
|
|
495
|
-
const
|
|
496
|
-
const
|
|
497
|
-
const health = diagnoser.getHealth();
|
|
524
|
+
const diagnoses = this.agentE.diagnoseNow();
|
|
525
|
+
const health = this.agentE.getHealth();
|
|
498
526
|
this.lastState = prevState;
|
|
499
527
|
return { diagnoses, health };
|
|
500
528
|
}
|