@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/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
- agentEConfig?: Partial<Omit<AgentEConfig, 'adapter'>>;
6
+ agentE?: Partial<Omit<AgentEConfig, 'adapter'>>;
7
+ validateState?: boolean;
8
+ corsOrigin?: string;
7
9
  }
8
- interface QueuedAdjustment {
9
- key: string;
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
- private readonly port;
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: QueuedAdjustment[];
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: 3000 });
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
- agentEConfig?: Partial<Omit<AgentEConfig, 'adapter'>>;
6
+ agentE?: Partial<Omit<AgentEConfig, 'adapter'>>;
7
+ validateState?: boolean;
8
+ corsOrigin?: string;
7
9
  }
8
- interface QueuedAdjustment {
9
- key: string;
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
- private readonly port;
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: QueuedAdjustment[];
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: 3000 });
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
- req.on("data", (chunk) => chunks.push(chunk));
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
- const validation = (0, import_core.validateEconomyState)(state);
81
- if (!validation.valid) {
82
- json(res, 400, {
83
- error: "Invalid state",
84
- validation
85
- });
86
- return;
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
- principle: a.principle.id,
96
- name: a.principle.name,
108
+ principleId: a.principle.id,
109
+ principleName: a.principle.name,
97
110
  severity: a.violation.severity,
98
111
  evidence: a.violation.evidence,
99
- suggestedAction: a.violation.suggestedAction
112
+ reasoning: a.violation.suggestedAction.reasoning
100
113
  })),
101
114
  health: result.health,
102
- decisions: result.decisions.map((d) => ({
103
- id: d.id,
104
- tick: d.tick,
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") ?? "50", 10);
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["action"] === "lock" && typeof config["param"] === "string") {
161
- server.lock(config["param"]);
162
- json(res, 200, { ok: true, action: "lock", param: config["param"] });
163
- } else if (config["action"] === "unlock" && typeof config["param"] === "string") {
164
- server.unlock(config["param"]);
165
- json(res, 200, { ok: true, action: "unlock", param: config["param"] });
166
- } else if (config["action"] === "constrain" && typeof config["param"] === "string" && typeof config["min"] === "number" && typeof config["max"] === "number") {
167
- server.constrain(config["param"], { min: config["min"], max: config["max"] });
168
- json(res, 200, { ok: true, action: "constrain", param: config["param"] });
169
- } else if (config["action"] === "mode" && (config["mode"] === "autonomous" || config["mode"] === "advisor")) {
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
- const validation = (0, import_core.validateEconomyState)(state);
204
- if (!validation.valid) {
205
- json(res, 400, { error: "Invalid state", validation });
206
- return;
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
- principle: d.principle.id,
213
- name: d.principle.name,
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
- json(res, 500, { error: "Internal server error" });
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", error: "Invalid JSON" });
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", error: 'Missing "type" field' });
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
- const validation = (0, import_core2.validateEconomyState)(state);
268
- if (!validation.valid) {
269
- send(ws, { type: "validation_error", validation });
270
- for (const w of validation.warnings) {
271
- send(ws, { type: "validation_warning", warning: w });
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
- principle: a.principle.id,
288
- name: a.principle.name,
303
+ principleId: a.principle.id,
304
+ principleName: a.principle.name,
289
305
  severity: a.violation.severity,
290
- suggestedAction: a.violation.suggestedAction
306
+ reasoning: a.violation.suggestedAction.reasoning
291
307
  })),
292
308
  health: result.health,
293
- decisions: result.decisions.map((d) => ({
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", error: "Tick processing failed" });
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", error: 'Missing "event" field' });
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
- const validation = (0, import_core2.validateEconomyState)(state);
331
- if (!validation.valid) {
332
- send(ws, { type: "validation_error", validation });
333
- return;
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
- principle: d.principle.id,
341
- name: d.principle.name,
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", error: `Unknown message type: "${msg.type}"` });
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 ?? 3e3;
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: config.agentEConfig?.mode ?? "autonomous",
413
- gracePeriod: config.agentEConfig?.gracePeriod ?? 0,
414
- checkInterval: config.agentEConfig?.checkInterval ?? 1,
415
- ...config.agentEConfig?.dominantRoles ? { dominantRoles: config.agentEConfig.dominantRoles } : {},
416
- ...config.agentEConfig?.idealDistribution ? { idealDistribution: config.agentEConfig.idealDistribution } : {},
417
- ...config.agentEConfig?.maxAdjustmentPercent !== void 0 ? { maxAdjustmentPercent: config.agentEConfig.maxAdjustmentPercent } : {},
418
- ...config.agentEConfig?.cooldownTicks !== void 0 ? { cooldownTicks: config.agentEConfig.cooldownTicks } : {},
419
- ...config.agentEConfig?.thresholds ? { thresholds: config.agentEConfig.thresholds } : {}
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 adjustments = [...this.adjustmentQueue];
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 diagnoser = this.agentE;
496
- const diagnoses = diagnoser.diagnoseNow();
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
  }