confused-ai-core 0.1.0
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/FEATURES.md +169 -0
- package/package.json +119 -0
- package/src/agent.ts +187 -0
- package/src/agentic/index.ts +87 -0
- package/src/agentic/runner.ts +386 -0
- package/src/agentic/types.ts +91 -0
- package/src/artifacts/artifact.ts +417 -0
- package/src/artifacts/index.ts +42 -0
- package/src/artifacts/media.ts +304 -0
- package/src/cli/index.ts +122 -0
- package/src/core/base-agent.ts +151 -0
- package/src/core/context-builder.ts +106 -0
- package/src/core/index.ts +8 -0
- package/src/core/schemas.ts +17 -0
- package/src/core/types.ts +158 -0
- package/src/create-agent.ts +309 -0
- package/src/debug-logger.ts +188 -0
- package/src/dx/agent.ts +88 -0
- package/src/dx/define-agent.ts +183 -0
- package/src/dx/dev-logger.ts +57 -0
- package/src/dx/index.ts +11 -0
- package/src/errors.ts +175 -0
- package/src/execution/engine.ts +522 -0
- package/src/execution/graph-builder.ts +362 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/types.ts +257 -0
- package/src/execution/worker-pool.ts +308 -0
- package/src/extensions/index.ts +123 -0
- package/src/guardrails/allowlist.ts +155 -0
- package/src/guardrails/index.ts +17 -0
- package/src/guardrails/types.ts +159 -0
- package/src/guardrails/validator.ts +265 -0
- package/src/index.ts +74 -0
- package/src/knowledge/index.ts +5 -0
- package/src/knowledge/types.ts +52 -0
- package/src/learning/in-memory-store.ts +72 -0
- package/src/learning/index.ts +6 -0
- package/src/learning/types.ts +42 -0
- package/src/llm/cache.ts +300 -0
- package/src/llm/index.ts +22 -0
- package/src/llm/model-resolver.ts +81 -0
- package/src/llm/openai-provider.ts +313 -0
- package/src/llm/openrouter-provider.ts +29 -0
- package/src/llm/types.ts +131 -0
- package/src/memory/in-memory-store.ts +255 -0
- package/src/memory/index.ts +7 -0
- package/src/memory/types.ts +193 -0
- package/src/memory/vector-store.ts +251 -0
- package/src/observability/console-logger.ts +123 -0
- package/src/observability/index.ts +12 -0
- package/src/observability/metrics.ts +85 -0
- package/src/observability/otlp-exporter.ts +417 -0
- package/src/observability/tracer.ts +105 -0
- package/src/observability/types.ts +341 -0
- package/src/orchestration/agent-adapter.ts +33 -0
- package/src/orchestration/index.ts +34 -0
- package/src/orchestration/load-balancer.ts +151 -0
- package/src/orchestration/mcp-types.ts +59 -0
- package/src/orchestration/message-bus.ts +192 -0
- package/src/orchestration/orchestrator.ts +349 -0
- package/src/orchestration/pipeline.ts +66 -0
- package/src/orchestration/supervisor.ts +107 -0
- package/src/orchestration/swarm.ts +1099 -0
- package/src/orchestration/toolkit.ts +47 -0
- package/src/orchestration/types.ts +339 -0
- package/src/planner/classical-planner.ts +383 -0
- package/src/planner/index.ts +8 -0
- package/src/planner/llm-planner.ts +353 -0
- package/src/planner/types.ts +227 -0
- package/src/planner/validator.ts +297 -0
- package/src/production/circuit-breaker.ts +290 -0
- package/src/production/graceful-shutdown.ts +251 -0
- package/src/production/health.ts +333 -0
- package/src/production/index.ts +57 -0
- package/src/production/latency-eval.ts +62 -0
- package/src/production/rate-limiter.ts +287 -0
- package/src/production/resumable-stream.ts +289 -0
- package/src/production/types.ts +81 -0
- package/src/sdk/index.ts +374 -0
- package/src/session/db-driver.ts +50 -0
- package/src/session/in-memory-store.ts +235 -0
- package/src/session/index.ts +12 -0
- package/src/session/sql-store.ts +315 -0
- package/src/session/sqlite-store.ts +61 -0
- package/src/session/types.ts +153 -0
- package/src/tools/base-tool.ts +223 -0
- package/src/tools/browser-tool.ts +123 -0
- package/src/tools/calculator-tool.ts +265 -0
- package/src/tools/file-tools.ts +394 -0
- package/src/tools/github-tool.ts +432 -0
- package/src/tools/hackernews-tool.ts +187 -0
- package/src/tools/http-tool.ts +118 -0
- package/src/tools/index.ts +99 -0
- package/src/tools/jira-tool.ts +373 -0
- package/src/tools/notion-tool.ts +322 -0
- package/src/tools/openai-tool.ts +236 -0
- package/src/tools/registry.ts +131 -0
- package/src/tools/serpapi-tool.ts +234 -0
- package/src/tools/shell-tool.ts +118 -0
- package/src/tools/slack-tool.ts +327 -0
- package/src/tools/telegram-tool.ts +127 -0
- package/src/tools/types.ts +229 -0
- package/src/tools/websearch-tool.ts +335 -0
- package/src/tools/wikipedia-tool.ts +177 -0
- package/src/tools/yfinance-tool.ts +33 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/voice-provider.ts +228 -0
- package/tests/artifact.test.ts +241 -0
- package/tests/circuit-breaker.test.ts +171 -0
- package/tests/health.test.ts +192 -0
- package/tests/llm-cache.test.ts +186 -0
- package/tests/rate-limiter.test.ts +161 -0
- package/tsconfig.json +29 -0
- package/vitest.config.ts +47 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Tracer Implementation
|
|
3
|
+
*
|
|
4
|
+
* Simple in-memory tracing for development and debugging
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Tracer, TraceSpan, SpanStatus, SpanEvent } from './types.js';
|
|
8
|
+
import type { EntityId } from '../core/types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* In-memory tracer implementation
|
|
12
|
+
*/
|
|
13
|
+
export class InMemoryTracer implements Tracer {
|
|
14
|
+
private spans: Map<EntityId, TraceSpan> = new Map();
|
|
15
|
+
private currentSpanId?: EntityId;
|
|
16
|
+
|
|
17
|
+
startSpan(name: string, parentId?: EntityId): TraceSpan {
|
|
18
|
+
const id = this.generateId();
|
|
19
|
+
const traceId = parentId
|
|
20
|
+
? this.spans.get(parentId)?.traceId ?? this.generateTraceId()
|
|
21
|
+
: this.generateTraceId();
|
|
22
|
+
|
|
23
|
+
const span: TraceSpan = {
|
|
24
|
+
id,
|
|
25
|
+
traceId,
|
|
26
|
+
parentId,
|
|
27
|
+
name,
|
|
28
|
+
startTime: new Date(),
|
|
29
|
+
status: SpanStatus.UNSET,
|
|
30
|
+
attributes: {},
|
|
31
|
+
events: [],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
this.spans.set(id, span);
|
|
35
|
+
this.currentSpanId = id;
|
|
36
|
+
|
|
37
|
+
return span;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
endSpan(spanId: EntityId, status: SpanStatus = SpanStatus.OK): void {
|
|
41
|
+
const span = this.spans.get(spanId);
|
|
42
|
+
if (span) {
|
|
43
|
+
Object.assign(span, {
|
|
44
|
+
endTime: new Date(),
|
|
45
|
+
status,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.currentSpanId === spanId) {
|
|
50
|
+
this.currentSpanId = undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
addEvent(spanId: EntityId, event: Omit<SpanEvent, 'timestamp'>): void {
|
|
55
|
+
const span = this.spans.get(spanId);
|
|
56
|
+
if (span) {
|
|
57
|
+
span.events.push({
|
|
58
|
+
...event,
|
|
59
|
+
timestamp: new Date(),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setAttributes(spanId: EntityId, attributes: Record<string, unknown>): void {
|
|
65
|
+
const span = this.spans.get(spanId);
|
|
66
|
+
if (span) {
|
|
67
|
+
Object.assign(span.attributes, attributes);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getSpan(spanId: EntityId): TraceSpan | undefined {
|
|
72
|
+
return this.spans.get(spanId);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getCurrentSpan(): TraceSpan | undefined {
|
|
76
|
+
return this.currentSpanId ? this.spans.get(this.currentSpanId) : undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getTrace(traceId: string): TraceSpan[] {
|
|
80
|
+
return Array.from(this.spans.values()).filter(span => span.traceId === traceId);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get all spans
|
|
85
|
+
*/
|
|
86
|
+
getAllSpans(): TraceSpan[] {
|
|
87
|
+
return Array.from(this.spans.values());
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Clear all spans
|
|
92
|
+
*/
|
|
93
|
+
clear(): void {
|
|
94
|
+
this.spans.clear();
|
|
95
|
+
this.currentSpanId = undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private generateId(): EntityId {
|
|
99
|
+
return `span-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private generateTraceId(): string {
|
|
103
|
+
return `trace-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability and telemetry types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { EntityId } from '../core/types.js';
|
|
6
|
+
import type { AgentState } from '../core/types.js';
|
|
7
|
+
import type { TaskStatus } from '../planner/types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Log levels
|
|
11
|
+
*/
|
|
12
|
+
export enum LogLevel {
|
|
13
|
+
DEBUG = 'debug',
|
|
14
|
+
INFO = 'info',
|
|
15
|
+
WARN = 'warn',
|
|
16
|
+
ERROR = 'error',
|
|
17
|
+
FATAL = 'fatal',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Log entry
|
|
22
|
+
*/
|
|
23
|
+
export interface LogEntry {
|
|
24
|
+
readonly id: EntityId;
|
|
25
|
+
readonly timestamp: Date;
|
|
26
|
+
readonly level: LogLevel;
|
|
27
|
+
readonly message: string;
|
|
28
|
+
readonly source: string;
|
|
29
|
+
readonly context: LogContext;
|
|
30
|
+
readonly metadata?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Log context
|
|
35
|
+
*/
|
|
36
|
+
export interface LogContext {
|
|
37
|
+
readonly agentId?: EntityId;
|
|
38
|
+
readonly taskId?: EntityId;
|
|
39
|
+
readonly planId?: EntityId;
|
|
40
|
+
readonly executionId?: EntityId;
|
|
41
|
+
readonly sessionId?: string;
|
|
42
|
+
readonly traceId?: string;
|
|
43
|
+
readonly spanId?: string;
|
|
44
|
+
readonly parentSpanId?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Logger interface
|
|
49
|
+
*/
|
|
50
|
+
export interface Logger {
|
|
51
|
+
/**
|
|
52
|
+
* Log a debug message
|
|
53
|
+
*/
|
|
54
|
+
debug(message: string, context?: Partial<LogContext>, metadata?: Record<string, unknown>): void;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Log an info message
|
|
58
|
+
*/
|
|
59
|
+
info(message: string, context?: Partial<LogContext>, metadata?: Record<string, unknown>): void;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Log a warning message
|
|
63
|
+
*/
|
|
64
|
+
warn(message: string, context?: Partial<LogContext>, metadata?: Record<string, unknown>): void;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Log an error message
|
|
68
|
+
*/
|
|
69
|
+
error(message: string, context?: Partial<LogContext>, metadata?: Record<string, unknown>): void;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Log a fatal message
|
|
73
|
+
*/
|
|
74
|
+
fatal(message: string, context?: Partial<LogContext>, metadata?: Record<string, unknown>): void;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a child logger with additional context
|
|
78
|
+
*/
|
|
79
|
+
child(additionalContext: Partial<LogContext>): Logger;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Log transport for outputting logs
|
|
84
|
+
*/
|
|
85
|
+
export interface LogTransport {
|
|
86
|
+
/**
|
|
87
|
+
* Write a log entry
|
|
88
|
+
*/
|
|
89
|
+
write(entry: LogEntry): Promise<void>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Flush any buffered logs
|
|
93
|
+
*/
|
|
94
|
+
flush(): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Trace span representing an operation
|
|
99
|
+
*/
|
|
100
|
+
export interface TraceSpan {
|
|
101
|
+
readonly id: EntityId;
|
|
102
|
+
readonly traceId: string;
|
|
103
|
+
readonly parentId?: EntityId;
|
|
104
|
+
readonly name: string;
|
|
105
|
+
readonly startTime: Date;
|
|
106
|
+
readonly endTime?: Date;
|
|
107
|
+
readonly status: SpanStatus;
|
|
108
|
+
readonly attributes: Record<string, unknown>;
|
|
109
|
+
readonly events: SpanEvent[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Span status
|
|
114
|
+
*/
|
|
115
|
+
export enum SpanStatus {
|
|
116
|
+
OK = 'ok',
|
|
117
|
+
ERROR = 'error',
|
|
118
|
+
UNSET = 'unset',
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Span event
|
|
123
|
+
*/
|
|
124
|
+
export interface SpanEvent {
|
|
125
|
+
readonly timestamp: Date;
|
|
126
|
+
readonly name: string;
|
|
127
|
+
readonly attributes?: Record<string, unknown>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Tracer interface for distributed tracing
|
|
132
|
+
*/
|
|
133
|
+
export interface Tracer {
|
|
134
|
+
/**
|
|
135
|
+
* Start a new span
|
|
136
|
+
*/
|
|
137
|
+
startSpan(name: string, parentId?: EntityId): TraceSpan;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* End a span
|
|
141
|
+
*/
|
|
142
|
+
endSpan(spanId: EntityId, status?: SpanStatus): void;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Add an event to a span
|
|
146
|
+
*/
|
|
147
|
+
addEvent(spanId: EntityId, event: Omit<SpanEvent, 'timestamp'>): void;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Set span attributes
|
|
151
|
+
*/
|
|
152
|
+
setAttributes(spanId: EntityId, attributes: Record<string, unknown>): void;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get a span by ID
|
|
156
|
+
*/
|
|
157
|
+
getSpan(spanId: EntityId): TraceSpan | undefined;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get the current active span
|
|
161
|
+
*/
|
|
162
|
+
getCurrentSpan(): TraceSpan | undefined;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get all spans for a trace
|
|
166
|
+
*/
|
|
167
|
+
getTrace(traceId: string): TraceSpan[];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Metric types
|
|
172
|
+
*/
|
|
173
|
+
export enum MetricType {
|
|
174
|
+
COUNTER = 'counter',
|
|
175
|
+
GAUGE = 'gauge',
|
|
176
|
+
HISTOGRAM = 'histogram',
|
|
177
|
+
SUMMARY = 'summary',
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Metric value
|
|
182
|
+
*/
|
|
183
|
+
export interface MetricValue {
|
|
184
|
+
readonly name: string;
|
|
185
|
+
readonly type: MetricType;
|
|
186
|
+
readonly value: number;
|
|
187
|
+
readonly labels: Record<string, string>;
|
|
188
|
+
readonly timestamp: Date;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Metrics collector
|
|
193
|
+
*/
|
|
194
|
+
export interface MetricsCollector {
|
|
195
|
+
/**
|
|
196
|
+
* Record a counter metric
|
|
197
|
+
*/
|
|
198
|
+
counter(name: string, value?: number, labels?: Record<string, string>): void;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Record a gauge metric
|
|
202
|
+
*/
|
|
203
|
+
gauge(name: string, value: number, labels?: Record<string, string>): void;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Record a histogram metric
|
|
207
|
+
*/
|
|
208
|
+
histogram(name: string, value: number, labels?: Record<string, string>): void;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Get all recorded metrics
|
|
212
|
+
*/
|
|
213
|
+
getMetrics(): MetricValue[];
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Clear all metrics
|
|
217
|
+
*/
|
|
218
|
+
clear(): void;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Agent event for telemetry
|
|
223
|
+
*/
|
|
224
|
+
export interface AgentEvent {
|
|
225
|
+
readonly timestamp: Date;
|
|
226
|
+
readonly agentId: EntityId;
|
|
227
|
+
readonly eventType: AgentEventType;
|
|
228
|
+
readonly previousState?: AgentState;
|
|
229
|
+
readonly currentState?: AgentState;
|
|
230
|
+
readonly metadata?: Record<string, unknown>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Agent event types
|
|
235
|
+
*/
|
|
236
|
+
export enum AgentEventType {
|
|
237
|
+
CREATED = 'created',
|
|
238
|
+
STARTED = 'started',
|
|
239
|
+
STATE_CHANGED = 'state_changed',
|
|
240
|
+
COMPLETED = 'completed',
|
|
241
|
+
FAILED = 'failed',
|
|
242
|
+
DESTROYED = 'destroyed',
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Task event for telemetry
|
|
247
|
+
*/
|
|
248
|
+
export interface TaskEvent {
|
|
249
|
+
readonly timestamp: Date;
|
|
250
|
+
readonly taskId: EntityId;
|
|
251
|
+
readonly agentId: EntityId;
|
|
252
|
+
readonly eventType: TaskEventType;
|
|
253
|
+
readonly previousStatus?: TaskStatus;
|
|
254
|
+
readonly currentStatus?: TaskStatus;
|
|
255
|
+
readonly executionTimeMs?: number;
|
|
256
|
+
readonly metadata?: Record<string, unknown>;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Task event types
|
|
261
|
+
*/
|
|
262
|
+
export enum TaskEventType {
|
|
263
|
+
CREATED = 'created',
|
|
264
|
+
STARTED = 'started',
|
|
265
|
+
STATUS_CHANGED = 'status_changed',
|
|
266
|
+
COMPLETED = 'completed',
|
|
267
|
+
FAILED = 'failed',
|
|
268
|
+
RETRYING = 'retrying',
|
|
269
|
+
CANCELLED = 'cancelled',
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Telemetry collector interface
|
|
274
|
+
*/
|
|
275
|
+
export interface TelemetryCollector {
|
|
276
|
+
/**
|
|
277
|
+
* Record an agent event
|
|
278
|
+
*/
|
|
279
|
+
recordAgentEvent(event: Omit<AgentEvent, 'timestamp'>): void;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Record a task event
|
|
283
|
+
*/
|
|
284
|
+
recordTaskEvent(event: Omit<TaskEvent, 'timestamp'>): void;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get agent events
|
|
288
|
+
*/
|
|
289
|
+
getAgentEvents(agentId?: EntityId): AgentEvent[];
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get task events
|
|
293
|
+
*/
|
|
294
|
+
getTaskEvents(taskId?: EntityId): TaskEvent[];
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Get agent statistics
|
|
298
|
+
*/
|
|
299
|
+
getAgentStats(agentId: EntityId): AgentStats;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Export telemetry data
|
|
303
|
+
*/
|
|
304
|
+
export(format: ExportFormat): string;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Agent statistics
|
|
309
|
+
*/
|
|
310
|
+
export interface AgentStats {
|
|
311
|
+
readonly agentId: EntityId;
|
|
312
|
+
readonly totalExecutions: number;
|
|
313
|
+
readonly successfulExecutions: number;
|
|
314
|
+
readonly failedExecutions: number;
|
|
315
|
+
readonly averageExecutionTimeMs: number;
|
|
316
|
+
readonly totalTokensUsed: number;
|
|
317
|
+
readonly totalCost: number;
|
|
318
|
+
readonly lastExecutionAt?: Date;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Export formats
|
|
323
|
+
*/
|
|
324
|
+
export enum ExportFormat {
|
|
325
|
+
JSON = 'json',
|
|
326
|
+
CSV = 'csv',
|
|
327
|
+
OTLP = 'otlp',
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Observability configuration
|
|
332
|
+
*/
|
|
333
|
+
export interface ObservabilityConfig {
|
|
334
|
+
readonly logLevel: LogLevel;
|
|
335
|
+
readonly enableTracing: boolean;
|
|
336
|
+
readonly enableMetrics: boolean;
|
|
337
|
+
readonly enableTelemetry: boolean;
|
|
338
|
+
readonly samplingRate: number;
|
|
339
|
+
readonly transports: LogTransport[];
|
|
340
|
+
readonly exportIntervalMs?: number;
|
|
341
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent adapter for orchestration
|
|
3
|
+
*
|
|
4
|
+
* Wraps a run function as a core Agent so it can be registered with the Orchestrator.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Agent, AgentInput, AgentOutput, AgentContext } from '../core/types.js';
|
|
8
|
+
|
|
9
|
+
export interface RunnableAgentConfig {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly description?: string;
|
|
12
|
+
readonly run: (input: AgentInput, ctx: AgentContext) => Promise<AgentOutput>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a core Agent from a run function for use with the Orchestrator.
|
|
17
|
+
*/
|
|
18
|
+
export function createRunnableAgent(config: RunnableAgentConfig): Agent {
|
|
19
|
+
return new RunnableAgentAdapter(config);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class RunnableAgentAdapter extends Agent {
|
|
23
|
+
constructor(private readonly runConfig: RunnableAgentConfig) {
|
|
24
|
+
super({
|
|
25
|
+
name: runConfig.name,
|
|
26
|
+
description: runConfig.description,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async run(input: AgentInput, ctx: AgentContext): Promise<AgentOutput> {
|
|
31
|
+
return this.runConfig.run(input, ctx);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestration module exports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
export { OrchestratorImpl } from './orchestrator.js';
|
|
7
|
+
export { MessageBusImpl } from './message-bus.js';
|
|
8
|
+
export { RoundRobinLoadBalancer } from './load-balancer.js';
|
|
9
|
+
export { createRunnableAgent } from './agent-adapter.js';
|
|
10
|
+
export type { RunnableAgentConfig } from './agent-adapter.js';
|
|
11
|
+
export { createSupervisor, createRole } from './supervisor.js';
|
|
12
|
+
export type { SupervisorConfig } from './supervisor.js';
|
|
13
|
+
export { createPipeline } from './pipeline.js';
|
|
14
|
+
export type { PipelineConfig } from './pipeline.js';
|
|
15
|
+
export { createToolkit, toolkitsToRegistry } from './toolkit.js';
|
|
16
|
+
export type { Toolkit } from './toolkit.js';
|
|
17
|
+
export type { MCPClient, MCPServerAdapter, MCPToolDescriptor, A2AMessage, A2AClient } from './mcp-types.js';
|
|
18
|
+
|
|
19
|
+
// Agent Swarm exports (Kimi K2.5 inspired)
|
|
20
|
+
export {
|
|
21
|
+
SwarmOrchestrator,
|
|
22
|
+
createSwarm,
|
|
23
|
+
createSwarmAgent,
|
|
24
|
+
} from './swarm.js';
|
|
25
|
+
export type {
|
|
26
|
+
SwarmConfig,
|
|
27
|
+
SwarmResult,
|
|
28
|
+
SubagentTemplate,
|
|
29
|
+
Subtask,
|
|
30
|
+
SubtaskResult,
|
|
31
|
+
ExecutionStage,
|
|
32
|
+
CriticalPathMetrics,
|
|
33
|
+
SubagentInstance,
|
|
34
|
+
} from './swarm.js';
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load Balancer Implementation
|
|
3
|
+
*
|
|
4
|
+
* Distributes tasks across agents based on various strategies
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { LoadBalancer, AgentRegistration, DelegationTask } from './types.js';
|
|
8
|
+
import type { EntityId } from '../core/types.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Round-robin load balancer
|
|
12
|
+
*/
|
|
13
|
+
export class RoundRobinLoadBalancer implements LoadBalancer {
|
|
14
|
+
private lastIndex = 0;
|
|
15
|
+
private agentMetrics: Map<EntityId, { totalTasks: number; failedTasks: number; totalExecutionTime: number }> = new Map();
|
|
16
|
+
|
|
17
|
+
selectAgent(candidates: AgentRegistration[], _task: DelegationTask): AgentRegistration | undefined {
|
|
18
|
+
if (candidates.length === 0) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Filter to agents under their max load
|
|
23
|
+
const available = candidates.filter(reg =>
|
|
24
|
+
reg.metadata.currentLoad < reg.metadata.maxConcurrentTasks
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (available.length === 0) {
|
|
28
|
+
// All agents at capacity, pick the one with lowest load
|
|
29
|
+
return candidates.sort((a, b) => a.metadata.currentLoad - b.metadata.currentLoad)[0];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Round-robin selection
|
|
33
|
+
const index = this.lastIndex % available.length;
|
|
34
|
+
this.lastIndex = (this.lastIndex + 1) % available.length;
|
|
35
|
+
|
|
36
|
+
return available[index];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
updateMetrics(agentId: EntityId, executionTimeMs: number, success: boolean): void {
|
|
40
|
+
const metrics = this.agentMetrics.get(agentId) ?? {
|
|
41
|
+
totalTasks: 0,
|
|
42
|
+
failedTasks: 0,
|
|
43
|
+
totalExecutionTime: 0,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
metrics.totalTasks++;
|
|
47
|
+
metrics.totalExecutionTime += executionTimeMs;
|
|
48
|
+
if (!success) {
|
|
49
|
+
metrics.failedTasks++;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.agentMetrics.set(agentId, metrics);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get metrics for an agent
|
|
57
|
+
*/
|
|
58
|
+
getMetrics(agentId: EntityId): { totalTasks: number; failedTasks: number; averageExecutionTime: number } | undefined {
|
|
59
|
+
const metrics = this.agentMetrics.get(agentId);
|
|
60
|
+
if (!metrics) return undefined;
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
totalTasks: metrics.totalTasks,
|
|
64
|
+
failedTasks: metrics.failedTasks,
|
|
65
|
+
averageExecutionTime: metrics.totalTasks > 0
|
|
66
|
+
? metrics.totalExecutionTime / metrics.totalTasks
|
|
67
|
+
: 0,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Least connections load balancer
|
|
74
|
+
*/
|
|
75
|
+
export class LeastConnectionsLoadBalancer implements LoadBalancer {
|
|
76
|
+
private agentMetrics: Map<EntityId, { totalTasks: number; failedTasks: number; totalExecutionTime: number }> = new Map();
|
|
77
|
+
|
|
78
|
+
selectAgent(candidates: AgentRegistration[], _task: DelegationTask): AgentRegistration | undefined {
|
|
79
|
+
if (candidates.length === 0) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Sort by current load (ascending)
|
|
84
|
+
return candidates.sort((a, b) => a.metadata.currentLoad - b.metadata.currentLoad)[0];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
updateMetrics(agentId: EntityId, executionTimeMs: number, success: boolean): void {
|
|
88
|
+
const metrics = this.agentMetrics.get(agentId) ?? {
|
|
89
|
+
totalTasks: 0,
|
|
90
|
+
failedTasks: 0,
|
|
91
|
+
totalExecutionTime: 0,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
metrics.totalTasks++;
|
|
95
|
+
metrics.totalExecutionTime += executionTimeMs;
|
|
96
|
+
if (!success) {
|
|
97
|
+
metrics.failedTasks++;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.agentMetrics.set(agentId, metrics);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Weighted response time load balancer
|
|
106
|
+
*/
|
|
107
|
+
export class WeightedResponseTimeLoadBalancer implements LoadBalancer {
|
|
108
|
+
private agentMetrics: Map<EntityId, { totalTasks: number; failedTasks: number; totalExecutionTime: number }> = new Map();
|
|
109
|
+
|
|
110
|
+
selectAgent(candidates: AgentRegistration[], _task: DelegationTask): AgentRegistration | undefined {
|
|
111
|
+
if (candidates.length === 0) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Calculate score based on average response time and current load
|
|
116
|
+
const scored = candidates.map(reg => {
|
|
117
|
+
const metrics = this.agentMetrics.get(reg.agent.id);
|
|
118
|
+
const avgResponseTime = metrics && metrics.totalTasks > 0
|
|
119
|
+
? metrics.totalExecutionTime / metrics.totalTasks
|
|
120
|
+
: 1000; // Default to 1s if no data
|
|
121
|
+
|
|
122
|
+
const loadFactor = reg.metadata.currentLoad / reg.metadata.maxConcurrentTasks;
|
|
123
|
+
|
|
124
|
+
// Lower score is better
|
|
125
|
+
const score = avgResponseTime * (1 + loadFactor);
|
|
126
|
+
|
|
127
|
+
return { reg, score };
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Sort by score (ascending)
|
|
131
|
+
scored.sort((a, b) => a.score - b.score);
|
|
132
|
+
|
|
133
|
+
return scored[0].reg;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
updateMetrics(agentId: EntityId, executionTimeMs: number, success: boolean): void {
|
|
137
|
+
const metrics = this.agentMetrics.get(agentId) ?? {
|
|
138
|
+
totalTasks: 0,
|
|
139
|
+
failedTasks: 0,
|
|
140
|
+
totalExecutionTime: 0,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
metrics.totalTasks++;
|
|
144
|
+
metrics.totalExecutionTime += executionTimeMs;
|
|
145
|
+
if (!success) {
|
|
146
|
+
metrics.failedTasks++;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.agentMetrics.set(agentId, metrics);
|
|
150
|
+
}
|
|
151
|
+
}
|