@louloulinx/metagpt 0.1.3

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.
Files changed (113) hide show
  1. package/.eslintrc.json +23 -0
  2. package/.prettierrc +7 -0
  3. package/LICENSE +21 -0
  4. package/README-CN.md +754 -0
  5. package/README.md +238 -0
  6. package/bun.lock +1023 -0
  7. package/doc/TutorialAssistant.md +114 -0
  8. package/doc/VercelLLMProvider.md +164 -0
  9. package/eslint.config.js +55 -0
  10. package/examples/data-interpreter-example.ts +173 -0
  11. package/examples/qwen-direct-example.ts +60 -0
  12. package/examples/qwen-example.ts +62 -0
  13. package/examples/tutorial-assistant-example.ts +97 -0
  14. package/jest.config.ts +22 -0
  15. package/output/tutorials/Go/350/257/255/350/250/200/347/274/226/347/250/213/346/225/231/347/250/213_2025-02-25T09-35-15-436Z.md +2208 -0
  16. package/output/tutorials/Rust/346/225/231/347/250/213_2025-02-25T08-27-27-632Z.md +1967 -0
  17. package/output/tutorials//345/246/202/344/275/225/344/275/277/347/224/250TypeScript/345/274/200/345/217/221Node.js/345/272/224/347/224/250_2025-02-25T08-14-39-605Z.md +1721 -0
  18. package/output/tutorials//346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/346/225/231/347/250/213_2025-02-25T10-45-03-605Z.md +902 -0
  19. package/output/tutorials//346/232/250/345/215/227/345/244/247/345/255/246/346/225/260/345/255/227/347/273/217/346/265/216/345/255/246/345/244/215/350/257/225/350/265/204/346/226/231_2025-02-25T11-16-59-133Z.md +719 -0
  20. package/package.json +58 -0
  21. package/plan-cn.md +321 -0
  22. package/plan.md +154 -0
  23. package/src/actions/analyze-task.ts +65 -0
  24. package/src/actions/base-action.ts +103 -0
  25. package/src/actions/di/execute-nb-code.ts +247 -0
  26. package/src/actions/di/write-analysis-code.ts +234 -0
  27. package/src/actions/write-tutorial.ts +232 -0
  28. package/src/config/browser.ts +33 -0
  29. package/src/config/config.ts +345 -0
  30. package/src/config/embedding.ts +26 -0
  31. package/src/config/llm.ts +36 -0
  32. package/src/config/mermaid.ts +37 -0
  33. package/src/config/omniparse.ts +25 -0
  34. package/src/config/redis.ts +34 -0
  35. package/src/config/s3.ts +33 -0
  36. package/src/config/search.ts +30 -0
  37. package/src/config/workspace.ts +20 -0
  38. package/src/index.ts +40 -0
  39. package/src/management/team.ts +168 -0
  40. package/src/memory/longterm.ts +218 -0
  41. package/src/memory/manager.ts +160 -0
  42. package/src/memory/types.ts +100 -0
  43. package/src/memory/working.ts +154 -0
  44. package/src/monitoring/system.ts +413 -0
  45. package/src/monitoring/types.ts +230 -0
  46. package/src/plugin/manager.ts +79 -0
  47. package/src/plugin/types.ts +114 -0
  48. package/src/provider/vercel-llm.ts +314 -0
  49. package/src/rag/base-rag.ts +194 -0
  50. package/src/rag/document-qa.ts +102 -0
  51. package/src/roles/base-role.ts +155 -0
  52. package/src/roles/data-interpreter.ts +360 -0
  53. package/src/roles/engineer.ts +1 -0
  54. package/src/roles/tutorial-assistant.ts +217 -0
  55. package/src/skills/base-skill.ts +144 -0
  56. package/src/skills/code-review.ts +120 -0
  57. package/src/tools/base-tool.ts +155 -0
  58. package/src/tools/file-system.ts +204 -0
  59. package/src/tools/tool-recommend.d.ts +14 -0
  60. package/src/tools/tool-recommend.ts +31 -0
  61. package/src/types/action.ts +38 -0
  62. package/src/types/config.ts +129 -0
  63. package/src/types/document.ts +354 -0
  64. package/src/types/llm.ts +64 -0
  65. package/src/types/memory.ts +36 -0
  66. package/src/types/message.ts +193 -0
  67. package/src/types/rag.ts +86 -0
  68. package/src/types/role.ts +67 -0
  69. package/src/types/skill.ts +71 -0
  70. package/src/types/task.ts +32 -0
  71. package/src/types/team.ts +55 -0
  72. package/src/types/tool.ts +77 -0
  73. package/src/types/workflow.ts +133 -0
  74. package/src/utils/common.ts +73 -0
  75. package/src/utils/yaml.ts +67 -0
  76. package/src/websocket/browser-client.ts +187 -0
  77. package/src/websocket/client.ts +186 -0
  78. package/src/websocket/server.ts +169 -0
  79. package/src/websocket/types.ts +125 -0
  80. package/src/workflow/executor.ts +193 -0
  81. package/src/workflow/executors/action-executor.ts +72 -0
  82. package/src/workflow/executors/condition-executor.ts +118 -0
  83. package/src/workflow/executors/parallel-executor.ts +201 -0
  84. package/src/workflow/executors/role-executor.ts +76 -0
  85. package/src/workflow/executors/sequence-executor.ts +196 -0
  86. package/tests/actions.test.ts +105 -0
  87. package/tests/benchmark/performance.test.ts +147 -0
  88. package/tests/config/config.test.ts +115 -0
  89. package/tests/config.test.ts +106 -0
  90. package/tests/e2e/setup.ts +74 -0
  91. package/tests/e2e/workflow.test.ts +88 -0
  92. package/tests/llm.test.ts +84 -0
  93. package/tests/memory/memory.test.ts +164 -0
  94. package/tests/memory.test.ts +63 -0
  95. package/tests/monitoring/monitoring.test.ts +225 -0
  96. package/tests/plugin/plugin.test.ts +183 -0
  97. package/tests/provider/bailian-llm.test.ts +98 -0
  98. package/tests/rag.test.ts +162 -0
  99. package/tests/roles.test.ts +88 -0
  100. package/tests/skills.test.ts +166 -0
  101. package/tests/team.test.ts +143 -0
  102. package/tests/tools.test.ts +170 -0
  103. package/tests/types/document.test.ts +181 -0
  104. package/tests/types/message.test.ts +122 -0
  105. package/tests/utils/yaml.test.ts +110 -0
  106. package/tests/utils.test.ts +74 -0
  107. package/tests/websocket/browser-client.test.ts +1 -0
  108. package/tests/websocket/websocket.test.ts +42 -0
  109. package/tests/workflow/parallel-executor.test.ts +224 -0
  110. package/tests/workflow/sequence-executor.test.ts +207 -0
  111. package/tests/workflow.test.ts +290 -0
  112. package/tsconfig.json +27 -0
  113. package/typedoc.json +25 -0
@@ -0,0 +1,154 @@
1
+ import type { WorkingMemory } from './types';
2
+ import type { MemoryEntrySchema, MemoryQueryOptions } from './types';
3
+ import type { z } from 'zod';
4
+ import { v4 as uuidv4 } from 'uuid';
5
+
6
+ /**
7
+ * In-memory implementation of working memory
8
+ */
9
+ export class WorkingMemoryImpl implements WorkingMemory {
10
+ private memories: Map<string, z.infer<typeof MemoryEntrySchema>> = new Map();
11
+ private focusId: string | null = null;
12
+
13
+ /**
14
+ * Add a new memory
15
+ */
16
+ public async add(
17
+ content: string,
18
+ type: string,
19
+ metadata: Record<string, any> = {}
20
+ ): Promise<z.infer<typeof MemoryEntrySchema>> {
21
+ const memory = {
22
+ id: uuidv4(),
23
+ content,
24
+ type,
25
+ timestamp: Date.now(),
26
+ metadata,
27
+ importance: metadata.importance ?? 0.5,
28
+ embedding: metadata.embedding ?? [],
29
+ };
30
+
31
+ this.memories.set(memory.id, memory);
32
+ return memory;
33
+ }
34
+
35
+ /**
36
+ * Get a memory by ID
37
+ */
38
+ public async get(id: string): Promise<z.infer<typeof MemoryEntrySchema> | null> {
39
+ return this.memories.get(id) || null;
40
+ }
41
+
42
+ /**
43
+ * Search memories by query options
44
+ */
45
+ public async search(options: MemoryQueryOptions): Promise<z.infer<typeof MemoryEntrySchema>[]> {
46
+ let results = Array.from(this.memories.values());
47
+
48
+ // Apply filters
49
+ if (options.type) {
50
+ results = results.filter(m => m.type === options.type);
51
+ }
52
+
53
+ if (options.startTime) {
54
+ results = results.filter(m => m.timestamp >= options.startTime!);
55
+ }
56
+
57
+ if (options.endTime) {
58
+ results = results.filter(m => m.timestamp <= options.endTime!);
59
+ }
60
+
61
+ if (typeof options.minImportance === 'number') {
62
+ results = results.filter(m => m.importance >= options.minImportance!);
63
+ }
64
+
65
+ if (options.metadata) {
66
+ results = results.filter(m => {
67
+ return Object.entries(options.metadata!).every(([key, value]) => {
68
+ if (typeof value === 'function') {
69
+ return value(m.metadata[key]);
70
+ }
71
+ return m.metadata[key] === value;
72
+ });
73
+ });
74
+ }
75
+
76
+ if (options.content) {
77
+ const searchContent = options.content.toLowerCase();
78
+ results = results.filter(m =>
79
+ m.content.toLowerCase().includes(searchContent)
80
+ );
81
+ }
82
+
83
+ // Sort by timestamp and importance
84
+ results.sort((a, b) => {
85
+ const importanceDiff = b.importance - a.importance;
86
+ return importanceDiff !== 0 ? importanceDiff : b.timestamp - a.timestamp;
87
+ });
88
+
89
+ // Apply limit
90
+ if (options.limit) {
91
+ results = results.slice(0, options.limit);
92
+ }
93
+
94
+ return results;
95
+ }
96
+
97
+ /**
98
+ * Update a memory
99
+ */
100
+ public async update(
101
+ id: string,
102
+ updates: Partial<z.infer<typeof MemoryEntrySchema>>
103
+ ): Promise<void> {
104
+ const memory = this.memories.get(id);
105
+ if (!memory) {
106
+ throw new Error(`Memory ${id} not found`);
107
+ }
108
+
109
+ Object.assign(memory, updates);
110
+ this.memories.set(id, memory);
111
+ }
112
+
113
+ /**
114
+ * Delete a memory
115
+ */
116
+ public async delete(id: string): Promise<void> {
117
+ this.memories.delete(id);
118
+ if (this.focusId === id) {
119
+ this.focusId = null;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Clear all memories
125
+ */
126
+ public async clear(): Promise<void> {
127
+ this.memories.clear();
128
+ this.focusId = null;
129
+ }
130
+
131
+ /**
132
+ * Get current focus of attention
133
+ */
134
+ public async getFocus(): Promise<z.infer<typeof MemoryEntrySchema> | null> {
135
+ return this.focusId ? this.memories.get(this.focusId) || null : null;
136
+ }
137
+
138
+ /**
139
+ * Set focus of attention
140
+ */
141
+ public async setFocus(id: string): Promise<void> {
142
+ if (!this.memories.has(id)) {
143
+ throw new Error(`Memory ${id} not found`);
144
+ }
145
+ this.focusId = id;
146
+ }
147
+
148
+ /**
149
+ * Clear focus of attention
150
+ */
151
+ public async clearFocus(): Promise<void> {
152
+ this.focusId = null;
153
+ }
154
+ }
@@ -0,0 +1,413 @@
1
+ import { z } from 'zod';
2
+ import type {
3
+ Counter,
4
+ Gauge,
5
+ Histogram,
6
+ Summary,
7
+ MetricCollector,
8
+ Tracer,
9
+ Logger,
10
+ MonitoringSystem,
11
+ } from './types';
12
+ import {
13
+ MetricType,
14
+ MetricSchema,
15
+ TraceSpanSchema,
16
+ LogLevel,
17
+ } from './types';
18
+
19
+ /**
20
+ * In-memory counter metric implementation
21
+ */
22
+ class CounterImpl implements Counter {
23
+ private values: Map<string, number> = new Map();
24
+
25
+ constructor(private options: z.infer<typeof MetricSchema>) {}
26
+
27
+ public inc(value = 1, labels: Record<string, string> = {}): void {
28
+ const key = this.getKey(labels);
29
+ const current = this.values.get(key) || 0;
30
+ this.values.set(key, current + value);
31
+ }
32
+
33
+ public getValue(labels: Record<string, string> = {}): number {
34
+ return this.values.get(this.getKey(labels)) || 0;
35
+ }
36
+
37
+ private getKey(labels: Record<string, string>): string {
38
+ return JSON.stringify(labels);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * In-memory gauge metric implementation
44
+ */
45
+ class GaugeImpl implements Gauge {
46
+ private values: Map<string, number> = new Map();
47
+
48
+ constructor(private options: z.infer<typeof MetricSchema>) {}
49
+
50
+ public set(value: number, labels: Record<string, string> = {}): void {
51
+ this.values.set(this.getKey(labels), value);
52
+ }
53
+
54
+ public inc(value = 1, labels: Record<string, string> = {}): void {
55
+ const key = this.getKey(labels);
56
+ const current = this.values.get(key) || 0;
57
+ this.values.set(key, current + value);
58
+ }
59
+
60
+ public dec(value = 1, labels: Record<string, string> = {}): void {
61
+ this.inc(-value, labels);
62
+ }
63
+
64
+ public getValue(labels: Record<string, string> = {}): number {
65
+ return this.values.get(this.getKey(labels)) || 0;
66
+ }
67
+
68
+ private getKey(labels: Record<string, string>): string {
69
+ return JSON.stringify(labels);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * In-memory histogram metric implementation
75
+ */
76
+ class HistogramImpl implements Histogram {
77
+ private buckets: Map<string, Record<number, number>> = new Map();
78
+ private defaultBuckets = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
79
+
80
+ constructor(private options: z.infer<typeof MetricSchema>) {}
81
+
82
+ public observe(value: number, labels: Record<string, string> = {}): void {
83
+ const key = this.getKey(labels);
84
+ let bucketValues = this.buckets.get(key);
85
+ if (!bucketValues) {
86
+ bucketValues = this.defaultBuckets.reduce((acc, bound) => {
87
+ acc[bound] = 0;
88
+ return acc;
89
+ }, {} as Record<number, number>);
90
+ this.buckets.set(key, bucketValues);
91
+ }
92
+
93
+ for (const bound of this.defaultBuckets) {
94
+ if (value <= bound) {
95
+ bucketValues[bound]++;
96
+ }
97
+ }
98
+ }
99
+
100
+ public getBuckets(labels: Record<string, string> = {}): Record<number, number> {
101
+ return this.buckets.get(this.getKey(labels)) || {};
102
+ }
103
+
104
+ private getKey(labels: Record<string, string>): string {
105
+ return JSON.stringify(labels);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * In-memory summary metric implementation
111
+ */
112
+ class SummaryImpl implements Summary {
113
+ private values: Map<string, number[]> = new Map();
114
+ private defaultQuantiles = [0.5, 0.9, 0.95, 0.99];
115
+
116
+ constructor(private options: z.infer<typeof MetricSchema>) {}
117
+
118
+ public observe(value: number, labels: Record<string, string> = {}): void {
119
+ const key = this.getKey(labels);
120
+ let values = this.values.get(key);
121
+ if (!values) {
122
+ values = [];
123
+ this.values.set(key, values);
124
+ }
125
+ values.push(value);
126
+ }
127
+
128
+ public getQuantiles(labels: Record<string, string> = {}): Record<number, number> {
129
+ const values = this.values.get(this.getKey(labels)) || [];
130
+ if (values.length === 0) return {};
131
+
132
+ values.sort((a, b) => a - b);
133
+ return this.defaultQuantiles.reduce((acc, q) => {
134
+ const index = Math.ceil(q * values.length) - 1;
135
+ acc[q] = values[index];
136
+ return acc;
137
+ }, {} as Record<number, number>);
138
+ }
139
+
140
+ private getKey(labels: Record<string, string>): string {
141
+ return JSON.stringify(labels);
142
+ }
143
+ }
144
+
145
+ /**
146
+ * In-memory metric collector implementation with Prometheus export support
147
+ */
148
+ class MetricCollectorImpl implements MetricCollector {
149
+ private metrics: Map<string, Counter | Gauge | Histogram | Summary> = new Map();
150
+
151
+ public counter(options: z.infer<typeof MetricSchema>): Counter {
152
+ const key = this.getKey(options.name, MetricType.COUNTER);
153
+ let metric = this.metrics.get(key) as Counter;
154
+ if (!metric) {
155
+ metric = new CounterImpl(options);
156
+ this.metrics.set(key, metric);
157
+ }
158
+ return metric;
159
+ }
160
+
161
+ public gauge(options: z.infer<typeof MetricSchema>): Gauge {
162
+ const key = this.getKey(options.name, MetricType.GAUGE);
163
+ let metric = this.metrics.get(key) as Gauge;
164
+ if (!metric) {
165
+ metric = new GaugeImpl(options);
166
+ this.metrics.set(key, metric);
167
+ }
168
+ return metric;
169
+ }
170
+
171
+ public histogram(options: z.infer<typeof MetricSchema>): Histogram {
172
+ const key = this.getKey(options.name, MetricType.HISTOGRAM);
173
+ let metric = this.metrics.get(key) as Histogram;
174
+ if (!metric) {
175
+ metric = new HistogramImpl(options);
176
+ this.metrics.set(key, metric);
177
+ }
178
+ return metric;
179
+ }
180
+
181
+ public summary(options: z.infer<typeof MetricSchema>): Summary {
182
+ const key = this.getKey(options.name, MetricType.SUMMARY);
183
+ let metric = this.metrics.get(key) as Summary;
184
+ if (!metric) {
185
+ metric = new SummaryImpl(options);
186
+ this.metrics.set(key, metric);
187
+ }
188
+ return metric;
189
+ }
190
+
191
+ private getKey(name: string, type: MetricType): string {
192
+ return `${type}:${name}`;
193
+ }
194
+
195
+ /**
196
+ * Export metrics in Prometheus format
197
+ * @returns Prometheus formatted metrics string
198
+ */
199
+ public exportPrometheus(): string {
200
+ const lines: string[] = [];
201
+
202
+ for (const [key, metric] of this.metrics.entries()) {
203
+ const [type, name] = key.split(':');
204
+ const help = `# HELP ${name} ${(metric as any).options.description}`;
205
+ const typeHelp = `# TYPE ${name} ${type.toLowerCase()}`;
206
+ lines.push(help, typeHelp);
207
+
208
+ if (metric instanceof CounterImpl || metric instanceof GaugeImpl) {
209
+ lines.push(`${name} ${metric.getValue()}`);
210
+ } else if (metric instanceof HistogramImpl) {
211
+ const buckets = metric.getBuckets();
212
+ Object.entries(buckets).forEach(([bound, count]) => {
213
+ lines.push(`${name}_bucket{le="${bound}"} ${count}`);
214
+ });
215
+ } else if (metric instanceof SummaryImpl) {
216
+ const quantiles = metric.getQuantiles();
217
+ Object.entries(quantiles).forEach(([q, value]) => {
218
+ lines.push(`${name}{quantile="${q}"} ${value}`);
219
+ });
220
+ }
221
+ }
222
+
223
+ return lines.join('\n');
224
+ }
225
+ }
226
+
227
+ /**
228
+ * In-memory tracer implementation with context propagation
229
+ */
230
+ class TracerImpl implements Tracer {
231
+ private spans: Map<string, z.infer<typeof TraceSpanSchema>> = new Map();
232
+ private activeSpans: Map<string, z.infer<typeof TraceSpanSchema>> = new Map();
233
+
234
+ public startSpan(name: string, options: {
235
+ parent?: z.infer<typeof TraceSpanSchema>;
236
+ kind?: z.infer<typeof TraceSpanSchema>['kind'];
237
+ attributes?: Record<string, any>;
238
+ } = {}): z.infer<typeof TraceSpanSchema> {
239
+ // Use active span as parent if not specified
240
+ const parent = options.parent || this.getActiveSpan();
241
+ const span = TraceSpanSchema.parse({
242
+ id: crypto.randomUUID(),
243
+ traceId: parent?.traceId || crypto.randomUUID(),
244
+ parentId: parent?.id,
245
+ name,
246
+ startTime: Date.now(),
247
+ kind: options.kind,
248
+ attributes: options.attributes,
249
+ });
250
+ this.spans.set(span.id, span);
251
+ this.setActiveSpan(span);
252
+ return span;
253
+ }
254
+
255
+ public endSpan(span: z.infer<typeof TraceSpanSchema>): void {
256
+ const storedSpan = this.spans.get(span.id);
257
+ if (storedSpan) {
258
+ storedSpan.endTime = Date.now();
259
+ this.clearActiveSpan(span);
260
+ }
261
+ }
262
+
263
+ public addEvent(span: z.infer<typeof TraceSpanSchema>, name: string, attributes: Record<string, any> = {}): void {
264
+ const storedSpan = this.spans.get(span.id);
265
+ if (storedSpan) {
266
+ storedSpan.events.push({
267
+ name,
268
+ timestamp: Date.now(),
269
+ attributes,
270
+ });
271
+ }
272
+ }
273
+
274
+ public setStatus(span: z.infer<typeof TraceSpanSchema>, status: z.infer<typeof TraceSpanSchema>['status'], error?: any): void {
275
+ const storedSpan = this.spans.get(span.id);
276
+ if (storedSpan) {
277
+ storedSpan.status = status;
278
+ if (error) {
279
+ storedSpan.error = error;
280
+ }
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Get active span for the current context
286
+ * @returns Currently active span or undefined
287
+ */
288
+ public getActiveSpan(): z.infer<typeof TraceSpanSchema> | undefined {
289
+ return Array.from(this.activeSpans.values())[0];
290
+ }
291
+
292
+ /**
293
+ * Set active span for the current context
294
+ * @param span - Span to set as active
295
+ */
296
+ public setActiveSpan(span: z.infer<typeof TraceSpanSchema>): void {
297
+ this.activeSpans.set(span.id, span);
298
+ }
299
+
300
+ /**
301
+ * Clear active span for the current context
302
+ * @param span - Span to clear
303
+ */
304
+ public clearActiveSpan(span: z.infer<typeof TraceSpanSchema>): void {
305
+ this.activeSpans.delete(span.id);
306
+ }
307
+ }
308
+
309
+ /**
310
+ * In-memory logger implementation with trace context correlation
311
+ */
312
+ class LoggerImpl implements Logger {
313
+ private logs: any[] = [];
314
+ private tracer?: TracerImpl;
315
+
316
+ constructor(tracer?: TracerImpl) {
317
+ this.tracer = tracer;
318
+ }
319
+
320
+ public debug(message: string, context: Record<string, any> = {}): void {
321
+ this.log(LogLevel.DEBUG, message, undefined, context);
322
+ }
323
+
324
+ public info(message: string, context: Record<string, any> = {}): void {
325
+ this.log(LogLevel.INFO, message, undefined, context);
326
+ }
327
+
328
+ public warn(message: string, context: Record<string, any> = {}): void {
329
+ this.log(LogLevel.WARN, message, undefined, context);
330
+ }
331
+
332
+ public error(message: string, error?: Error, context: Record<string, any> = {}): void {
333
+ this.log(LogLevel.ERROR, message, error, context);
334
+ }
335
+
336
+ private log(level: LogLevel, message: string, error?: Error, context: Record<string, any> = {}): void {
337
+ // Get current trace context
338
+ const activeSpan = this.tracer?.getActiveSpan();
339
+ const entry = {
340
+ timestamp: Date.now(),
341
+ level,
342
+ message,
343
+ context: {
344
+ ...context,
345
+ error: error?.message,
346
+ stack: error?.stack,
347
+ traceId: activeSpan?.traceId,
348
+ spanId: activeSpan?.id,
349
+ },
350
+ };
351
+ this.logs.push(entry);
352
+ console[level](message, entry.context);
353
+ }
354
+
355
+ /**
356
+ * Get all logs with optional filtering
357
+ * @param filter - Filter criteria
358
+ * @returns Filtered logs
359
+ */
360
+ public getLogs(filter?: {
361
+ level?: LogLevel;
362
+ traceId?: string;
363
+ spanId?: string;
364
+ startTime?: number;
365
+ endTime?: number;
366
+ }): any[] {
367
+ let filtered = this.logs;
368
+
369
+ if (filter) {
370
+ filtered = filtered.filter(log => {
371
+ if (filter.level && log.level !== filter.level) return false;
372
+ if (filter.traceId && log.context.traceId !== filter.traceId) return false;
373
+ if (filter.spanId && log.context.spanId !== filter.spanId) return false;
374
+ if (filter.startTime && log.timestamp < filter.startTime) return false;
375
+ if (filter.endTime && log.timestamp > filter.endTime) return false;
376
+ return true;
377
+ });
378
+ }
379
+
380
+ return filtered;
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Monitoring system implementation
386
+ *
387
+ * Features:
388
+ * - Metric collection with support for counters, gauges, histograms, and summaries
389
+ * - Prometheus format metric export
390
+ * - Distributed tracing with context propagation
391
+ * - Structured logging with trace correlation
392
+ * - In-memory storage with filtering capabilities
393
+ */
394
+ export class MonitoringSystemImpl implements MonitoringSystem {
395
+ public readonly metrics: MetricCollector;
396
+ public readonly tracer: Tracer;
397
+ public readonly logger: Logger;
398
+
399
+ constructor() {
400
+ const tracer = new TracerImpl();
401
+ this.metrics = new MetricCollectorImpl();
402
+ this.tracer = tracer;
403
+ this.logger = new LoggerImpl(tracer);
404
+ }
405
+
406
+ public async init(): Promise<void> {
407
+ this.logger.info('Monitoring system initialized');
408
+ }
409
+
410
+ public async shutdown(): Promise<void> {
411
+ this.logger.info('Monitoring system shutdown');
412
+ }
413
+ }