@agentxjs/core 1.9.1-dev
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 +31 -0
- package/src/agent/AgentStateMachine.ts +151 -0
- package/src/agent/README.md +296 -0
- package/src/agent/__tests__/AgentStateMachine.test.ts +346 -0
- package/src/agent/__tests__/createAgent.test.ts +728 -0
- package/src/agent/__tests__/engine/internal/messageAssemblerProcessor.test.ts +567 -0
- package/src/agent/__tests__/engine/internal/stateEventProcessor.test.ts +315 -0
- package/src/agent/__tests__/engine/internal/turnTrackerProcessor.test.ts +340 -0
- package/src/agent/__tests__/engine/mealy/Mealy.test.ts +370 -0
- package/src/agent/__tests__/engine/mealy/Store.test.ts +123 -0
- package/src/agent/__tests__/engine/mealy/combinators.test.ts +322 -0
- package/src/agent/createAgent.ts +467 -0
- package/src/agent/engine/AgentProcessor.ts +106 -0
- package/src/agent/engine/MealyMachine.ts +184 -0
- package/src/agent/engine/internal/index.ts +35 -0
- package/src/agent/engine/internal/messageAssemblerProcessor.ts +550 -0
- package/src/agent/engine/internal/stateEventProcessor.ts +313 -0
- package/src/agent/engine/internal/turnTrackerProcessor.ts +239 -0
- package/src/agent/engine/mealy/Mealy.ts +308 -0
- package/src/agent/engine/mealy/Processor.ts +70 -0
- package/src/agent/engine/mealy/Sink.ts +56 -0
- package/src/agent/engine/mealy/Source.ts +51 -0
- package/src/agent/engine/mealy/Store.ts +98 -0
- package/src/agent/engine/mealy/combinators.ts +176 -0
- package/src/agent/engine/mealy/index.ts +45 -0
- package/src/agent/index.ts +106 -0
- package/src/agent/types/engine.ts +395 -0
- package/src/agent/types/event.ts +478 -0
- package/src/agent/types/index.ts +197 -0
- package/src/agent/types/message.ts +387 -0
- package/src/common/index.ts +8 -0
- package/src/common/logger/ConsoleLogger.ts +137 -0
- package/src/common/logger/LoggerFactoryImpl.ts +123 -0
- package/src/common/logger/index.ts +26 -0
- package/src/common/logger/types.ts +98 -0
- package/src/container/Container.ts +185 -0
- package/src/container/index.ts +44 -0
- package/src/container/types.ts +71 -0
- package/src/driver/index.ts +42 -0
- package/src/driver/types.ts +363 -0
- package/src/event/EventBus.ts +260 -0
- package/src/event/README.md +237 -0
- package/src/event/__tests__/EventBus.test.ts +251 -0
- package/src/event/index.ts +46 -0
- package/src/event/types/agent.ts +512 -0
- package/src/event/types/base.ts +241 -0
- package/src/event/types/bus.ts +429 -0
- package/src/event/types/command.ts +749 -0
- package/src/event/types/container.ts +471 -0
- package/src/event/types/driver.ts +452 -0
- package/src/event/types/index.ts +26 -0
- package/src/event/types/session.ts +314 -0
- package/src/image/Image.ts +203 -0
- package/src/image/index.ts +36 -0
- package/src/image/types.ts +77 -0
- package/src/index.ts +20 -0
- package/src/mq/OffsetGenerator.ts +48 -0
- package/src/mq/README.md +166 -0
- package/src/mq/__tests__/OffsetGenerator.test.ts +121 -0
- package/src/mq/index.ts +18 -0
- package/src/mq/types.ts +172 -0
- package/src/network/RpcClient.ts +455 -0
- package/src/network/index.ts +76 -0
- package/src/network/jsonrpc.ts +336 -0
- package/src/network/protocol.ts +90 -0
- package/src/network/types.ts +284 -0
- package/src/persistence/index.ts +27 -0
- package/src/persistence/types.ts +226 -0
- package/src/runtime/AgentXRuntime.ts +501 -0
- package/src/runtime/index.ts +56 -0
- package/src/runtime/types.ts +236 -0
- package/src/session/Session.ts +71 -0
- package/src/session/index.ts +25 -0
- package/src/session/types.ts +77 -0
- package/src/workspace/index.ts +27 -0
- package/src/workspace/types.ts +131 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Types - Content Parts and Message Types
|
|
3
|
+
*
|
|
4
|
+
* This file defines:
|
|
5
|
+
* - Content Parts: TextPart, ThinkingPart, ImagePart, FilePart, ToolCallPart, ToolResultPart
|
|
6
|
+
* - Message Types: UserMessage, AssistantMessage, ToolCallMessage, ToolResultMessage, ErrorMessage
|
|
7
|
+
* - Message Role and Subtype discriminators
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Content Parts
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Text Part
|
|
18
|
+
*
|
|
19
|
+
* Plain text content in a message.
|
|
20
|
+
*/
|
|
21
|
+
export interface TextPart {
|
|
22
|
+
/** Content type discriminator */
|
|
23
|
+
type: "text";
|
|
24
|
+
|
|
25
|
+
/** The text content (supports Markdown) */
|
|
26
|
+
text: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Thinking Part
|
|
31
|
+
*
|
|
32
|
+
* AI's reasoning/thinking process (extended thinking).
|
|
33
|
+
*/
|
|
34
|
+
export interface ThinkingPart {
|
|
35
|
+
/** Content type discriminator */
|
|
36
|
+
type: "thinking";
|
|
37
|
+
|
|
38
|
+
/** The reasoning text */
|
|
39
|
+
reasoning: string;
|
|
40
|
+
|
|
41
|
+
/** Tokens used for thinking (optional) */
|
|
42
|
+
tokenCount?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Image Part
|
|
47
|
+
*
|
|
48
|
+
* Image content in a message.
|
|
49
|
+
*/
|
|
50
|
+
export interface ImagePart {
|
|
51
|
+
/** Content type discriminator */
|
|
52
|
+
type: "image";
|
|
53
|
+
|
|
54
|
+
/** Image data (base64-encoded string or URL) */
|
|
55
|
+
data: string;
|
|
56
|
+
|
|
57
|
+
/** Image MIME type */
|
|
58
|
+
mediaType: "image/png" | "image/jpeg" | "image/gif" | "image/webp";
|
|
59
|
+
|
|
60
|
+
/** Optional image name/filename */
|
|
61
|
+
name?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* File Part
|
|
66
|
+
*
|
|
67
|
+
* File attachment in a message (PDF, documents, etc.).
|
|
68
|
+
*/
|
|
69
|
+
export interface FilePart {
|
|
70
|
+
/** Content type discriminator */
|
|
71
|
+
type: "file";
|
|
72
|
+
|
|
73
|
+
/** File data (base64-encoded string or URL) */
|
|
74
|
+
data: string;
|
|
75
|
+
|
|
76
|
+
/** File MIME type (IANA media type) */
|
|
77
|
+
mediaType: string;
|
|
78
|
+
|
|
79
|
+
/** Optional filename */
|
|
80
|
+
filename?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Tool Call Part
|
|
85
|
+
*
|
|
86
|
+
* AI's request to invoke a tool.
|
|
87
|
+
*/
|
|
88
|
+
export interface ToolCallPart {
|
|
89
|
+
/** Content type discriminator */
|
|
90
|
+
type: "tool-call";
|
|
91
|
+
|
|
92
|
+
/** Unique identifier for this tool call */
|
|
93
|
+
id: string;
|
|
94
|
+
|
|
95
|
+
/** Tool name */
|
|
96
|
+
name: string;
|
|
97
|
+
|
|
98
|
+
/** Tool input parameters */
|
|
99
|
+
input: Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Tool Result Output
|
|
104
|
+
*
|
|
105
|
+
* Enhanced tool result format supporting multiple output types.
|
|
106
|
+
* Based on Vercel AI SDK and industry best practices.
|
|
107
|
+
*/
|
|
108
|
+
export type ToolResultOutput =
|
|
109
|
+
/**
|
|
110
|
+
* Plain text result
|
|
111
|
+
*/
|
|
112
|
+
| {
|
|
113
|
+
type: "text";
|
|
114
|
+
value: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* JSON result
|
|
119
|
+
*/
|
|
120
|
+
| {
|
|
121
|
+
type: "json";
|
|
122
|
+
value: unknown;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Text error
|
|
127
|
+
*/
|
|
128
|
+
| {
|
|
129
|
+
type: "error-text";
|
|
130
|
+
value: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* JSON error
|
|
135
|
+
*/
|
|
136
|
+
| {
|
|
137
|
+
type: "error-json";
|
|
138
|
+
value: unknown;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* User denied tool execution
|
|
143
|
+
*/
|
|
144
|
+
| {
|
|
145
|
+
type: "execution-denied";
|
|
146
|
+
reason?: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Rich content (multiple parts)
|
|
151
|
+
*/
|
|
152
|
+
| {
|
|
153
|
+
type: "content";
|
|
154
|
+
value: Array<TextPart | ImagePart | FilePart>;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Tool Result Part
|
|
159
|
+
*
|
|
160
|
+
* Result of tool execution.
|
|
161
|
+
*/
|
|
162
|
+
export interface ToolResultPart {
|
|
163
|
+
/** Content type discriminator */
|
|
164
|
+
type: "tool-result";
|
|
165
|
+
|
|
166
|
+
/** Tool call ID this result corresponds to */
|
|
167
|
+
id: string;
|
|
168
|
+
|
|
169
|
+
/** Tool name */
|
|
170
|
+
name: string;
|
|
171
|
+
|
|
172
|
+
/** Tool execution output */
|
|
173
|
+
output: ToolResultOutput;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Content Part
|
|
178
|
+
*
|
|
179
|
+
* Discriminated union of all content part types.
|
|
180
|
+
* Used in messages to support multi-modal and complex content.
|
|
181
|
+
*/
|
|
182
|
+
export type ContentPart =
|
|
183
|
+
| TextPart
|
|
184
|
+
| ThinkingPart
|
|
185
|
+
| ImagePart
|
|
186
|
+
| FilePart
|
|
187
|
+
| ToolCallPart
|
|
188
|
+
| ToolResultPart;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* User Content Part
|
|
192
|
+
*
|
|
193
|
+
* Subset of ContentPart types that users can send in messages.
|
|
194
|
+
* - TextPart: Plain text content
|
|
195
|
+
* - ImagePart: Image attachments (JPEG, PNG, GIF, WebP)
|
|
196
|
+
* - FilePart: File attachments (PDF, documents, etc.)
|
|
197
|
+
*/
|
|
198
|
+
export type UserContentPart = TextPart | ImagePart | FilePart;
|
|
199
|
+
|
|
200
|
+
// =============================================================================
|
|
201
|
+
// Message Types
|
|
202
|
+
// =============================================================================
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Message Role
|
|
206
|
+
*
|
|
207
|
+
* Represents who sent the message in the conversation.
|
|
208
|
+
* Five fundamental roles in the conversation.
|
|
209
|
+
*/
|
|
210
|
+
export type MessageRole = "user" | "assistant" | "tool" | "system" | "error";
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Message Subtype
|
|
214
|
+
*
|
|
215
|
+
* Represents the specific type/category of the message.
|
|
216
|
+
* Used together with role for serialization and type discrimination.
|
|
217
|
+
*/
|
|
218
|
+
export type MessageSubtype = "user" | "assistant" | "tool-call" | "tool-result" | "error";
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Token usage information
|
|
222
|
+
*/
|
|
223
|
+
export interface TokenUsage {
|
|
224
|
+
inputTokens: number;
|
|
225
|
+
outputTokens: number;
|
|
226
|
+
totalTokens?: number;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* User Message
|
|
231
|
+
*
|
|
232
|
+
* Message sent by the user.
|
|
233
|
+
* Can contain simple text or rich content (text, images, files).
|
|
234
|
+
*/
|
|
235
|
+
export interface UserMessage {
|
|
236
|
+
/** Unique identifier */
|
|
237
|
+
id: string;
|
|
238
|
+
|
|
239
|
+
/** Message role */
|
|
240
|
+
role: "user";
|
|
241
|
+
|
|
242
|
+
/** Message subtype for serialization */
|
|
243
|
+
subtype: "user";
|
|
244
|
+
|
|
245
|
+
/** Message content - can be simple string or array of parts */
|
|
246
|
+
content: string | UserContentPart[];
|
|
247
|
+
|
|
248
|
+
/** When this message was created (Unix timestamp in milliseconds) */
|
|
249
|
+
timestamp: number;
|
|
250
|
+
|
|
251
|
+
/** Parent message ID for threading (optional) */
|
|
252
|
+
parentId?: string;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Assistant Message
|
|
257
|
+
*
|
|
258
|
+
* Message generated by the AI assistant.
|
|
259
|
+
* Contains text, thinking process, or files.
|
|
260
|
+
*
|
|
261
|
+
* Note: Tool calls are separate - use ToolCallMessage for tool invocations.
|
|
262
|
+
*/
|
|
263
|
+
export interface AssistantMessage {
|
|
264
|
+
/** Unique identifier */
|
|
265
|
+
id: string;
|
|
266
|
+
|
|
267
|
+
/** Message role */
|
|
268
|
+
role: "assistant";
|
|
269
|
+
|
|
270
|
+
/** Message subtype for serialization */
|
|
271
|
+
subtype: "assistant";
|
|
272
|
+
|
|
273
|
+
/** Message content - can be simple string or array of parts */
|
|
274
|
+
content: string | Array<TextPart | ThinkingPart | FilePart>;
|
|
275
|
+
|
|
276
|
+
/** When this message was created (Unix timestamp in milliseconds) */
|
|
277
|
+
timestamp: number;
|
|
278
|
+
|
|
279
|
+
/** Parent message ID for threading (optional) */
|
|
280
|
+
parentId?: string;
|
|
281
|
+
|
|
282
|
+
/** Token usage for this AI response (optional) */
|
|
283
|
+
usage?: TokenUsage;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Tool Call Message
|
|
288
|
+
*
|
|
289
|
+
* Represents AI's request to invoke a tool.
|
|
290
|
+
* Emitted when tool call parameters are fully assembled.
|
|
291
|
+
*
|
|
292
|
+
* Subject: Assistant (AI decided to call a tool)
|
|
293
|
+
* Timing: At tool_use_content_block_stop
|
|
294
|
+
*/
|
|
295
|
+
export interface ToolCallMessage {
|
|
296
|
+
/** Unique message identifier */
|
|
297
|
+
id: string;
|
|
298
|
+
|
|
299
|
+
/** Message role - assistant initiates tool calls */
|
|
300
|
+
role: "assistant";
|
|
301
|
+
|
|
302
|
+
/** Message subtype for serialization */
|
|
303
|
+
subtype: "tool-call";
|
|
304
|
+
|
|
305
|
+
/** Tool call details */
|
|
306
|
+
toolCall: ToolCallPart;
|
|
307
|
+
|
|
308
|
+
/** When this message was created (Unix timestamp in milliseconds) */
|
|
309
|
+
timestamp: number;
|
|
310
|
+
|
|
311
|
+
/** Parent message ID (the assistant message that triggered this) */
|
|
312
|
+
parentId?: string;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Tool Result Message
|
|
317
|
+
*
|
|
318
|
+
* Represents the result of tool execution.
|
|
319
|
+
* Emitted after tool execution completes.
|
|
320
|
+
*
|
|
321
|
+
* Subject: Tool (execution completed with result)
|
|
322
|
+
* Timing: At tool_result event
|
|
323
|
+
*/
|
|
324
|
+
export interface ToolResultMessage {
|
|
325
|
+
/** Unique message identifier */
|
|
326
|
+
id: string;
|
|
327
|
+
|
|
328
|
+
/** Message role - tool returns results */
|
|
329
|
+
role: "tool";
|
|
330
|
+
|
|
331
|
+
/** Message subtype for serialization */
|
|
332
|
+
subtype: "tool-result";
|
|
333
|
+
|
|
334
|
+
/** Tool result details */
|
|
335
|
+
toolResult: ToolResultPart;
|
|
336
|
+
|
|
337
|
+
/** ID of the corresponding tool call */
|
|
338
|
+
toolCallId: string;
|
|
339
|
+
|
|
340
|
+
/** When this message was created (Unix timestamp in milliseconds) */
|
|
341
|
+
timestamp: number;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Error Message
|
|
346
|
+
*
|
|
347
|
+
* Message representing an error that occurred during conversation.
|
|
348
|
+
* Displayed in the chat history so users can see what went wrong.
|
|
349
|
+
*/
|
|
350
|
+
export interface ErrorMessage {
|
|
351
|
+
/** Unique identifier */
|
|
352
|
+
id: string;
|
|
353
|
+
|
|
354
|
+
/** Message role */
|
|
355
|
+
role: "error";
|
|
356
|
+
|
|
357
|
+
/** Message subtype for serialization */
|
|
358
|
+
subtype: "error";
|
|
359
|
+
|
|
360
|
+
/** Error message content (human-readable) */
|
|
361
|
+
content: string;
|
|
362
|
+
|
|
363
|
+
/** Error code (e.g., "rate_limit_error", "api_error") */
|
|
364
|
+
errorCode?: string;
|
|
365
|
+
|
|
366
|
+
/** When this error occurred (Unix timestamp in milliseconds) */
|
|
367
|
+
timestamp: number;
|
|
368
|
+
|
|
369
|
+
/** Parent message ID for threading (optional) */
|
|
370
|
+
parentId?: string;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Message
|
|
375
|
+
*
|
|
376
|
+
* Discriminated union of all message types.
|
|
377
|
+
* Use `subtype` field for precise type discrimination.
|
|
378
|
+
*
|
|
379
|
+
* Role: Who sent it (user, assistant, tool, system, error)
|
|
380
|
+
* Subtype: What type of message (user, assistant, tool-call, tool-result, error)
|
|
381
|
+
*/
|
|
382
|
+
export type Message =
|
|
383
|
+
| UserMessage
|
|
384
|
+
| AssistantMessage
|
|
385
|
+
| ToolCallMessage
|
|
386
|
+
| ToolResultMessage
|
|
387
|
+
| ErrorMessage;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConsoleLogger - Default logger implementation
|
|
3
|
+
*
|
|
4
|
+
* Simple console-based logger with color support.
|
|
5
|
+
* Used as fallback when no custom LoggerFactory is provided.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Logger, LogContext, LogLevel } from "./types";
|
|
9
|
+
|
|
10
|
+
export interface ConsoleLoggerOptions {
|
|
11
|
+
level?: LogLevel;
|
|
12
|
+
colors?: boolean;
|
|
13
|
+
timestamps?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ConsoleLogger implements Logger {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly level: LogLevel;
|
|
19
|
+
private readonly colors: boolean;
|
|
20
|
+
private readonly timestamps: boolean;
|
|
21
|
+
|
|
22
|
+
private static readonly COLORS = {
|
|
23
|
+
DEBUG: "\x1b[36m",
|
|
24
|
+
INFO: "\x1b[32m",
|
|
25
|
+
WARN: "\x1b[33m",
|
|
26
|
+
ERROR: "\x1b[31m",
|
|
27
|
+
RESET: "\x1b[0m",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
constructor(name: string, options: ConsoleLoggerOptions = {}) {
|
|
31
|
+
this.name = name;
|
|
32
|
+
this.level = options.level ?? "info";
|
|
33
|
+
this.colors = options.colors ?? this.isNodeEnvironment();
|
|
34
|
+
this.timestamps = options.timestamps ?? true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
debug(message: string, context?: LogContext): void {
|
|
38
|
+
if (this.isDebugEnabled()) {
|
|
39
|
+
this.log("DEBUG", message, context);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
info(message: string, context?: LogContext): void {
|
|
44
|
+
if (this.isInfoEnabled()) {
|
|
45
|
+
this.log("INFO", message, context);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
warn(message: string, context?: LogContext): void {
|
|
50
|
+
if (this.isWarnEnabled()) {
|
|
51
|
+
this.log("WARN", message, context);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
error(message: string | Error, context?: LogContext): void {
|
|
56
|
+
if (this.isErrorEnabled()) {
|
|
57
|
+
if (message instanceof Error) {
|
|
58
|
+
this.log("ERROR", message.message, { ...context, stack: message.stack });
|
|
59
|
+
} else {
|
|
60
|
+
this.log("ERROR", message, context);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
isDebugEnabled(): boolean {
|
|
66
|
+
return this.getLevelValue(this.level) <= this.getLevelValue("debug");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
isInfoEnabled(): boolean {
|
|
70
|
+
return this.getLevelValue(this.level) <= this.getLevelValue("info");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
isWarnEnabled(): boolean {
|
|
74
|
+
return this.getLevelValue(this.level) <= this.getLevelValue("warn");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
isErrorEnabled(): boolean {
|
|
78
|
+
return this.getLevelValue(this.level) <= this.getLevelValue("error");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private getLevelValue(level: LogLevel): number {
|
|
82
|
+
const levels: Record<LogLevel, number> = {
|
|
83
|
+
debug: 0,
|
|
84
|
+
info: 1,
|
|
85
|
+
warn: 2,
|
|
86
|
+
error: 3,
|
|
87
|
+
silent: 4,
|
|
88
|
+
};
|
|
89
|
+
return levels[level];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private log(level: string, message: string, context?: LogContext): void {
|
|
93
|
+
const parts: string[] = [];
|
|
94
|
+
|
|
95
|
+
if (this.timestamps) {
|
|
96
|
+
parts.push(new Date().toISOString());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (this.colors) {
|
|
100
|
+
const color = ConsoleLogger.COLORS[level as keyof typeof ConsoleLogger.COLORS];
|
|
101
|
+
parts.push(`${color}${level.padEnd(5)}${ConsoleLogger.COLORS.RESET}`);
|
|
102
|
+
} else {
|
|
103
|
+
parts.push(level.padEnd(5));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
parts.push(`[${this.name}]`);
|
|
107
|
+
parts.push(message);
|
|
108
|
+
|
|
109
|
+
const logLine = parts.join(" ");
|
|
110
|
+
const consoleMethod = this.getConsoleMethod(level);
|
|
111
|
+
|
|
112
|
+
if (context && Object.keys(context).length > 0) {
|
|
113
|
+
consoleMethod(logLine, context);
|
|
114
|
+
} else {
|
|
115
|
+
consoleMethod(logLine);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private getConsoleMethod(level: string): (...args: unknown[]) => void {
|
|
120
|
+
switch (level) {
|
|
121
|
+
case "DEBUG":
|
|
122
|
+
return console.debug.bind(console);
|
|
123
|
+
case "INFO":
|
|
124
|
+
return console.info.bind(console);
|
|
125
|
+
case "WARN":
|
|
126
|
+
return console.warn.bind(console);
|
|
127
|
+
case "ERROR":
|
|
128
|
+
return console.error.bind(console);
|
|
129
|
+
default:
|
|
130
|
+
return console.log.bind(console);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private isNodeEnvironment(): boolean {
|
|
135
|
+
return typeof process !== "undefined" && process.versions?.node !== undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoggerFactoryImpl - Central factory for creating logger instances
|
|
3
|
+
*
|
|
4
|
+
* Implements lazy initialization pattern:
|
|
5
|
+
* - createLogger() can be called at module level (before config)
|
|
6
|
+
* - Real logger is created on first use
|
|
7
|
+
* - External LoggerFactory can be injected via Runtime
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Logger, LoggerFactory, LogContext, LogLevel } from "./types";
|
|
11
|
+
import { ConsoleLogger, type ConsoleLoggerOptions } from "./ConsoleLogger";
|
|
12
|
+
|
|
13
|
+
// External factory injected via Runtime
|
|
14
|
+
let externalFactory: LoggerFactory | null = null;
|
|
15
|
+
|
|
16
|
+
// Version counter to invalidate cached real loggers
|
|
17
|
+
let factoryVersion = 0;
|
|
18
|
+
|
|
19
|
+
export interface LoggerFactoryConfig {
|
|
20
|
+
defaultImplementation?: (name: string) => Logger;
|
|
21
|
+
defaultLevel?: LogLevel;
|
|
22
|
+
consoleOptions?: Omit<ConsoleLoggerOptions, "level">;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Internal LoggerFactory implementation
|
|
27
|
+
*
|
|
28
|
+
* Uses lazy proxy pattern to allow module-level createLogger() calls.
|
|
29
|
+
*/
|
|
30
|
+
export class LoggerFactoryImpl {
|
|
31
|
+
private static loggers: Map<string, Logger> = new Map();
|
|
32
|
+
private static config: LoggerFactoryConfig = {
|
|
33
|
+
defaultLevel: "info",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
static getLogger(nameOrClass: string | (new (...args: unknown[]) => unknown)): Logger {
|
|
37
|
+
const name = typeof nameOrClass === "string" ? nameOrClass : nameOrClass.name;
|
|
38
|
+
|
|
39
|
+
if (this.loggers.has(name)) {
|
|
40
|
+
return this.loggers.get(name)!;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const lazyLogger = this.createLazyLogger(name);
|
|
44
|
+
this.loggers.set(name, lazyLogger);
|
|
45
|
+
return lazyLogger;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static configure(config: LoggerFactoryConfig): void {
|
|
49
|
+
this.config = { ...this.config, ...config };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static reset(): void {
|
|
53
|
+
this.loggers.clear();
|
|
54
|
+
this.config = { defaultLevel: "info" };
|
|
55
|
+
externalFactory = null;
|
|
56
|
+
factoryVersion++; // Invalidate all cached real loggers
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private static createLazyLogger(name: string): Logger {
|
|
60
|
+
let realLogger: Logger | null = null;
|
|
61
|
+
let loggerVersion = -1; // Track which factory version created this logger
|
|
62
|
+
|
|
63
|
+
const getRealLogger = (): Logger => {
|
|
64
|
+
// Recreate logger if factory version changed (setLoggerFactory was called)
|
|
65
|
+
if (!realLogger || loggerVersion !== factoryVersion) {
|
|
66
|
+
realLogger = this.createLogger(name);
|
|
67
|
+
loggerVersion = factoryVersion;
|
|
68
|
+
}
|
|
69
|
+
return realLogger;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
name,
|
|
74
|
+
level: this.config.defaultLevel || "info",
|
|
75
|
+
debug: (message: string, context?: LogContext) => getRealLogger().debug(message, context),
|
|
76
|
+
info: (message: string, context?: LogContext) => getRealLogger().info(message, context),
|
|
77
|
+
warn: (message: string, context?: LogContext) => getRealLogger().warn(message, context),
|
|
78
|
+
error: (message: string | Error, context?: LogContext) =>
|
|
79
|
+
getRealLogger().error(message, context),
|
|
80
|
+
isDebugEnabled: () => getRealLogger().isDebugEnabled(),
|
|
81
|
+
isInfoEnabled: () => getRealLogger().isInfoEnabled(),
|
|
82
|
+
isWarnEnabled: () => getRealLogger().isWarnEnabled(),
|
|
83
|
+
isErrorEnabled: () => getRealLogger().isErrorEnabled(),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private static createLogger(name: string): Logger {
|
|
88
|
+
if (externalFactory) {
|
|
89
|
+
return externalFactory.getLogger(name);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (this.config.defaultImplementation) {
|
|
93
|
+
return this.config.defaultImplementation(name);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return new ConsoleLogger(name, {
|
|
97
|
+
level: this.config.defaultLevel,
|
|
98
|
+
...this.config.consoleOptions,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Set external LoggerFactory (called by Runtime initialization)
|
|
105
|
+
*/
|
|
106
|
+
export function setLoggerFactory(factory: LoggerFactory): void {
|
|
107
|
+
externalFactory = factory;
|
|
108
|
+
LoggerFactoryImpl.reset();
|
|
109
|
+
externalFactory = factory;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Create a logger instance
|
|
114
|
+
*
|
|
115
|
+
* Safe to call at module level before Runtime is configured.
|
|
116
|
+
* Uses lazy initialization - actual logger is created on first use.
|
|
117
|
+
*
|
|
118
|
+
* @param name - Logger name (hierarchical, e.g., "engine/AgentEngine")
|
|
119
|
+
* @returns Logger instance (lazy proxy)
|
|
120
|
+
*/
|
|
121
|
+
export function createLogger(name: string): Logger {
|
|
122
|
+
return LoggerFactoryImpl.getLogger(name);
|
|
123
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger module
|
|
3
|
+
*
|
|
4
|
+
* Internal logger implementation for AgentX platform.
|
|
5
|
+
* Provides lazy-initialized logging with pluggable backends.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { createLogger } from "@anthropic-ai/sdk-core/common";
|
|
10
|
+
*
|
|
11
|
+
* // Safe at module level (before Runtime configured)
|
|
12
|
+
* const logger = createLogger("engine/AgentEngine");
|
|
13
|
+
*
|
|
14
|
+
* // Later, at runtime
|
|
15
|
+
* logger.info("Agent initialized", { agentId: "xxx" });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type { Logger, LoggerFactory, LogContext, LogLevel } from "./types";
|
|
20
|
+
export { ConsoleLogger, type ConsoleLoggerOptions } from "./ConsoleLogger";
|
|
21
|
+
export {
|
|
22
|
+
LoggerFactoryImpl,
|
|
23
|
+
type LoggerFactoryConfig,
|
|
24
|
+
setLoggerFactory,
|
|
25
|
+
createLogger,
|
|
26
|
+
} from "./LoggerFactoryImpl";
|