@johpaz/hive-core 1.0.7 → 1.0.10
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/package.json +10 -9
- package/src/agent/ethics.ts +70 -68
- package/src/agent/index.ts +48 -17
- package/src/agent/providers/index.ts +11 -5
- package/src/agent/soul.ts +19 -15
- package/src/agent/user.ts +19 -15
- package/src/agent/workspace.ts +6 -6
- package/src/agents/index.ts +4 -0
- package/src/agents/inter-agent-bus.test.ts +264 -0
- package/src/agents/inter-agent-bus.ts +279 -0
- package/src/agents/registry.test.ts +275 -0
- package/src/agents/registry.ts +273 -0
- package/src/agents/router.test.ts +229 -0
- package/src/agents/router.ts +251 -0
- package/src/agents/team-coordinator.test.ts +401 -0
- package/src/agents/team-coordinator.ts +480 -0
- package/src/canvas/canvas-manager.test.ts +159 -0
- package/src/canvas/canvas-manager.ts +219 -0
- package/src/canvas/canvas-tools.ts +189 -0
- package/src/canvas/index.ts +2 -0
- package/src/channels/whatsapp.ts +12 -12
- package/src/config/loader.ts +12 -9
- package/src/events/event-bus.test.ts +98 -0
- package/src/events/event-bus.ts +171 -0
- package/src/gateway/server.ts +131 -35
- package/src/index.ts +9 -1
- package/src/multi-agent/manager.ts +12 -12
- package/src/plugins/api.ts +129 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/loader.test.ts +285 -0
- package/src/plugins/loader.ts +363 -0
- package/src/resilience/circuit-breaker.test.ts +129 -0
- package/src/resilience/circuit-breaker.ts +223 -0
- package/src/security/google-chat.test.ts +219 -0
- package/src/security/google-chat.ts +269 -0
- package/src/security/index.ts +5 -0
- package/src/security/pairing.test.ts +302 -0
- package/src/security/pairing.ts +250 -0
- package/src/security/rate-limit.test.ts +239 -0
- package/src/security/rate-limit.ts +270 -0
- package/src/security/signal.test.ts +92 -0
- package/src/security/signal.ts +321 -0
- package/src/state/store.test.ts +190 -0
- package/src/state/store.ts +310 -0
- package/src/storage/sqlite.ts +3 -3
- package/src/tools/cron.ts +42 -2
- package/src/tools/dynamic-registry.test.ts +226 -0
- package/src/tools/dynamic-registry.ts +258 -0
- package/src/tools/fs.test.ts +127 -0
- package/src/tools/fs.ts +364 -0
- package/src/tools/index.ts +1 -0
- package/src/tools/read.ts +23 -19
- package/src/utils/logger.ts +112 -33
package/src/utils/logger.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { mkdirSync, unlinkSync, renameSync, existsSync } from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
|
|
4
4
|
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
@@ -12,6 +12,18 @@ export interface LoggerConfig {
|
|
|
12
12
|
console: boolean;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export interface LogMeta extends Record<string, unknown> {
|
|
16
|
+
correlationId?: string;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
userId?: string;
|
|
19
|
+
agentId?: string;
|
|
20
|
+
channel?: string;
|
|
21
|
+
toolName?: string;
|
|
22
|
+
duration?: number;
|
|
23
|
+
error?: string;
|
|
24
|
+
stack?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
15
27
|
const LOG_LEVELS: Record<LogLevel, number> = {
|
|
16
28
|
debug: 0,
|
|
17
29
|
info: 1,
|
|
@@ -78,16 +90,18 @@ function formatTimestamp(): string {
|
|
|
78
90
|
return new Date().toISOString();
|
|
79
91
|
}
|
|
80
92
|
|
|
81
|
-
function formatMessage(level: LogLevel, message: string, meta?: unknown): string {
|
|
93
|
+
function formatMessage(level: LogLevel, message: string, meta?: unknown, correlationId?: string): string {
|
|
82
94
|
const timestamp = formatTimestamp();
|
|
95
|
+
const corrStr = correlationId ? ` [${correlationId.slice(0, 8)}]` : "";
|
|
83
96
|
const metaStr = meta ? ` ${JSON.stringify(meta)}` : "";
|
|
84
|
-
return `[${timestamp}] [${level.toUpperCase()}] ${message}${metaStr}`;
|
|
97
|
+
return `[${timestamp}]${corrStr} [${level.toUpperCase()}] ${message}${metaStr}`;
|
|
85
98
|
}
|
|
86
99
|
|
|
87
100
|
export class Logger {
|
|
88
101
|
private config: LoggerConfig;
|
|
89
102
|
private logFile: string | null = null;
|
|
90
103
|
private currentSize = 0;
|
|
104
|
+
private correlationContext: LogMeta = {};
|
|
91
105
|
|
|
92
106
|
constructor(config: Partial<LoggerConfig> = {}) {
|
|
93
107
|
this.config = {
|
|
@@ -102,20 +116,35 @@ export class Logger {
|
|
|
102
116
|
this.initLogFile();
|
|
103
117
|
}
|
|
104
118
|
|
|
119
|
+
setCorrelationContext(context: Partial<LogMeta>): void {
|
|
120
|
+
this.correlationContext = { ...this.correlationContext, ...context };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
clearCorrelationContext(): void {
|
|
124
|
+
this.correlationContext = {};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getCorrelationId(): string | undefined {
|
|
128
|
+
return this.correlationContext.correlationId;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
withCorrelationId(id: string): this {
|
|
132
|
+
this.correlationContext.correlationId = id;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
|
|
105
136
|
private initLogFile(): void {
|
|
106
137
|
const logDir = expandPath(this.config.dir);
|
|
107
|
-
|
|
138
|
+
|
|
108
139
|
try {
|
|
109
|
-
if (!
|
|
110
|
-
|
|
140
|
+
if (!existsSync(logDir)) {
|
|
141
|
+
mkdirSync(logDir, { recursive: true });
|
|
111
142
|
}
|
|
112
143
|
|
|
113
144
|
this.logFile = path.join(logDir, `hive-${new Date().toISOString().split("T")[0]}.log`);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.currentSize = stats.size;
|
|
118
|
-
}
|
|
145
|
+
|
|
146
|
+
const file = Bun.file(this.logFile);
|
|
147
|
+
this.currentSize = file.size ?? 0;
|
|
119
148
|
} catch {
|
|
120
149
|
this.logFile = null;
|
|
121
150
|
}
|
|
@@ -129,13 +158,31 @@ export class Logger {
|
|
|
129
158
|
if (!this.config.console) return;
|
|
130
159
|
|
|
131
160
|
const color = COLORS[level];
|
|
132
|
-
const
|
|
133
|
-
const
|
|
161
|
+
const mergedMeta = this.mergeMeta(meta);
|
|
162
|
+
const displayMeta = this.config.redactSensitive && mergedMeta ? redact(mergedMeta) : mergedMeta;
|
|
163
|
+
const metaStr = displayMeta && Object.keys(displayMeta as object).length > 0
|
|
164
|
+
? ` ${JSON.stringify(displayMeta)}`
|
|
165
|
+
: "";
|
|
134
166
|
|
|
135
167
|
const prefix = `${COLORS.dim}${formatTimestamp()}${COLORS.reset}`;
|
|
168
|
+
const corrStr = this.correlationContext.correlationId
|
|
169
|
+
? ` ${COLORS.dim}[${this.correlationContext.correlationId.slice(0, 8)}]${COLORS.reset}`
|
|
170
|
+
: "";
|
|
136
171
|
const levelStr = `${color}${COLORS.bright}[${level.toUpperCase().padEnd(5)}]${COLORS.reset}`;
|
|
137
|
-
|
|
138
|
-
console.log(`${prefix} ${levelStr} ${message}${metaStr}`);
|
|
172
|
+
|
|
173
|
+
console.log(`${prefix}${corrStr} ${levelStr} ${message}${metaStr}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private mergeMeta(meta?: unknown): LogMeta | undefined {
|
|
177
|
+
if (!meta && Object.keys(this.correlationContext).length === 0) return undefined;
|
|
178
|
+
|
|
179
|
+
const contextWithoutCorrId = { ...this.correlationContext };
|
|
180
|
+
delete contextWithoutCorrId.correlationId;
|
|
181
|
+
|
|
182
|
+
if (!meta) return contextWithoutCorrId;
|
|
183
|
+
if (typeof meta !== "object") return meta as LogMeta;
|
|
184
|
+
|
|
185
|
+
return { ...contextWithoutCorrId, ...(meta as LogMeta) };
|
|
139
186
|
}
|
|
140
187
|
|
|
141
188
|
private writeToFile(message: string): void {
|
|
@@ -144,12 +191,15 @@ export class Logger {
|
|
|
144
191
|
try {
|
|
145
192
|
const line = message + "\n";
|
|
146
193
|
const bytes = Buffer.byteLength(line);
|
|
147
|
-
|
|
194
|
+
|
|
148
195
|
if (this.currentSize + bytes > this.config.maxSizeMB * 1024 * 1024) {
|
|
149
196
|
this.rotateLogs();
|
|
150
197
|
}
|
|
151
198
|
|
|
152
|
-
|
|
199
|
+
// Use sync append for logging reliability
|
|
200
|
+
const encoder = new TextEncoder();
|
|
201
|
+
const data = encoder.encode(line);
|
|
202
|
+
Bun.write(this.logFile, data).catch(() => { });
|
|
153
203
|
this.currentSize += bytes;
|
|
154
204
|
} catch {
|
|
155
205
|
// Silently fail if we can't write to log file
|
|
@@ -165,13 +215,13 @@ export class Logger {
|
|
|
165
215
|
for (let i = this.config.maxFiles - 1; i >= 1; i--) {
|
|
166
216
|
const oldFile = path.join(logDir, `${baseName}.${i}.log`);
|
|
167
217
|
const newFile = path.join(logDir, `${baseName}.${i + 1}.log`);
|
|
168
|
-
|
|
218
|
+
|
|
169
219
|
try {
|
|
170
|
-
if (
|
|
220
|
+
if (existsSync(oldFile)) {
|
|
171
221
|
if (i === this.config.maxFiles - 1) {
|
|
172
|
-
|
|
222
|
+
unlinkSync(oldFile);
|
|
173
223
|
} else {
|
|
174
|
-
|
|
224
|
+
renameSync(oldFile, newFile);
|
|
175
225
|
}
|
|
176
226
|
}
|
|
177
227
|
} catch {
|
|
@@ -180,7 +230,7 @@ export class Logger {
|
|
|
180
230
|
}
|
|
181
231
|
|
|
182
232
|
try {
|
|
183
|
-
|
|
233
|
+
renameSync(this.logFile, path.join(logDir, `${baseName}.1.log`));
|
|
184
234
|
this.currentSize = 0;
|
|
185
235
|
} catch {
|
|
186
236
|
// Continue even if rotation fails
|
|
@@ -189,34 +239,38 @@ export class Logger {
|
|
|
189
239
|
|
|
190
240
|
debug(message: string, meta?: unknown): void {
|
|
191
241
|
if (!this.shouldLog("debug")) return;
|
|
192
|
-
const
|
|
242
|
+
const mergedMeta = this.mergeMeta(meta);
|
|
243
|
+
const formatted = formatMessage("debug", message, mergedMeta, this.correlationContext.correlationId);
|
|
193
244
|
this.writeToConsole("debug", message, meta);
|
|
194
245
|
this.writeToFile(formatted);
|
|
195
246
|
}
|
|
196
247
|
|
|
197
248
|
info(message: string, meta?: unknown): void {
|
|
198
249
|
if (!this.shouldLog("info")) return;
|
|
199
|
-
const
|
|
250
|
+
const mergedMeta = this.mergeMeta(meta);
|
|
251
|
+
const formatted = formatMessage("info", message, mergedMeta, this.correlationContext.correlationId);
|
|
200
252
|
this.writeToConsole("info", message, meta);
|
|
201
253
|
this.writeToFile(formatted);
|
|
202
254
|
}
|
|
203
255
|
|
|
204
256
|
warn(message: string, meta?: unknown): void {
|
|
205
257
|
if (!this.shouldLog("warn")) return;
|
|
206
|
-
const
|
|
258
|
+
const mergedMeta = this.mergeMeta(meta);
|
|
259
|
+
const formatted = formatMessage("warn", message, mergedMeta, this.correlationContext.correlationId);
|
|
207
260
|
this.writeToConsole("warn", message, meta);
|
|
208
261
|
this.writeToFile(formatted);
|
|
209
262
|
}
|
|
210
263
|
|
|
211
264
|
error(message: string, meta?: unknown): void {
|
|
212
265
|
if (!this.shouldLog("error")) return;
|
|
213
|
-
const
|
|
266
|
+
const mergedMeta = this.mergeMeta(meta);
|
|
267
|
+
const formatted = formatMessage("error", message, mergedMeta, this.correlationContext.correlationId);
|
|
214
268
|
this.writeToConsole("error", message, meta);
|
|
215
269
|
this.writeToFile(formatted);
|
|
216
270
|
}
|
|
217
271
|
|
|
218
272
|
child(context: string): ChildLogger {
|
|
219
|
-
return new ChildLogger(this, context);
|
|
273
|
+
return new ChildLogger(this, context, this.correlationContext);
|
|
220
274
|
}
|
|
221
275
|
|
|
222
276
|
setLevel(level: LogLevel): void {
|
|
@@ -227,27 +281,52 @@ export class Logger {
|
|
|
227
281
|
export class ChildLogger {
|
|
228
282
|
constructor(
|
|
229
283
|
private parent: Logger,
|
|
230
|
-
private context: string
|
|
231
|
-
|
|
284
|
+
private context: string,
|
|
285
|
+
private correlationContext: LogMeta = {}
|
|
286
|
+
) { }
|
|
232
287
|
|
|
233
288
|
private prefix(message: string): string {
|
|
234
289
|
return `[${this.context}] ${message}`;
|
|
235
290
|
}
|
|
236
291
|
|
|
292
|
+
withCorrelationId(id: string): this {
|
|
293
|
+
this.correlationContext.correlationId = id;
|
|
294
|
+
return this;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
setContext(context: Partial<LogMeta>): void {
|
|
298
|
+
this.correlationContext = { ...this.correlationContext, ...context };
|
|
299
|
+
}
|
|
300
|
+
|
|
237
301
|
debug(message: string, meta?: unknown): void {
|
|
238
|
-
this.parent.debug(this.prefix(message), meta);
|
|
302
|
+
this.parent.debug(this.prefix(message), this.mergeMeta(meta));
|
|
239
303
|
}
|
|
240
304
|
|
|
241
305
|
info(message: string, meta?: unknown): void {
|
|
242
|
-
this.parent.info(this.prefix(message), meta);
|
|
306
|
+
this.parent.info(this.prefix(message), this.mergeMeta(meta));
|
|
243
307
|
}
|
|
244
308
|
|
|
245
309
|
warn(message: string, meta?: unknown): void {
|
|
246
|
-
this.parent.warn(this.prefix(message), meta);
|
|
310
|
+
this.parent.warn(this.prefix(message), this.mergeMeta(meta));
|
|
247
311
|
}
|
|
248
312
|
|
|
249
313
|
error(message: string, meta?: unknown): void {
|
|
250
|
-
this.parent.error(this.prefix(message), meta);
|
|
314
|
+
this.parent.error(this.prefix(message), this.mergeMeta(meta));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
child(subContext: string): ChildLogger {
|
|
318
|
+
return new ChildLogger(
|
|
319
|
+
this.parent,
|
|
320
|
+
`${this.context}:${subContext}`,
|
|
321
|
+
this.correlationContext
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private mergeMeta(meta?: unknown): LogMeta | undefined {
|
|
326
|
+
if (!meta && Object.keys(this.correlationContext).length === 0) return undefined;
|
|
327
|
+
if (!meta) return { ...this.correlationContext };
|
|
328
|
+
if (typeof meta !== "object") return meta as LogMeta;
|
|
329
|
+
return { ...this.correlationContext, ...(meta as LogMeta) };
|
|
251
330
|
}
|
|
252
331
|
}
|
|
253
332
|
|