@starlink-awaken/agentmesh 1.0.2 → 1.2.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/CHANGELOG.md +60 -41
- package/README.zh-CN.md +137 -167
- package/config/gateway.yaml +78 -0
- package/dist/src/adapters/base.d.ts +22 -0
- package/dist/src/adapters/base.js +10 -0
- package/dist/src/adapters/claude-code.d.ts +22 -0
- package/dist/src/adapters/claude-code.js +112 -0
- package/dist/src/adapters/openclaw.d.ts +22 -0
- package/dist/src/adapters/openclaw.js +110 -0
- package/dist/src/adapters/process.d.ts +28 -0
- package/dist/src/adapters/process.js +121 -0
- package/dist/src/cli/connect.d.ts +26 -0
- package/dist/src/cli/connect.js +544 -0
- package/dist/src/cli/setup.d.ts +2 -0
- package/dist/src/cli/setup.js +97 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +410 -0
- package/dist/src/core/agent-registry.d.ts +48 -0
- package/dist/src/core/agent-registry.js +295 -0
- package/dist/src/core/config.d.ts +59 -0
- package/dist/src/core/config.js +101 -0
- package/dist/src/core/context-manager.d.ts +52 -0
- package/dist/src/core/context-manager.js +165 -0
- package/dist/src/core/event-bus.d.ts +35 -0
- package/dist/src/core/event-bus.js +62 -0
- package/dist/src/core/logger.d.ts +14 -0
- package/dist/src/core/logger.js +57 -0
- package/dist/src/core/metrics.d.ts +87 -0
- package/dist/src/core/metrics.js +167 -0
- package/dist/src/core/router.d.ts +46 -0
- package/dist/src/core/router.js +90 -0
- package/dist/src/core/task-manager.d.ts +41 -0
- package/dist/src/core/task-manager.js +197 -0
- package/dist/src/core/vector-store.d.ts +37 -0
- package/dist/src/core/vector-store.js +175 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +105 -0
- package/dist/src/model-gateway/circuit-breaker.d.ts +21 -0
- package/dist/src/model-gateway/circuit-breaker.js +86 -0
- package/dist/src/model-gateway/health.d.ts +12 -0
- package/dist/src/model-gateway/health.js +80 -0
- package/dist/src/model-gateway/providers.d.ts +4 -0
- package/dist/src/model-gateway/providers.js +113 -0
- package/dist/src/model-gateway/quota.d.ts +4 -0
- package/dist/src/model-gateway/quota.js +107 -0
- package/dist/src/model-gateway/rate-limit.d.ts +12 -0
- package/dist/src/model-gateway/rate-limit.js +51 -0
- package/dist/src/model-gateway/retry.d.ts +14 -0
- package/dist/src/model-gateway/retry.js +48 -0
- package/dist/src/model-gateway/router.d.ts +4 -0
- package/dist/src/model-gateway/router.js +79 -0
- package/dist/src/model-gateway/routes.d.ts +2 -0
- package/dist/src/model-gateway/routes.js +172 -0
- package/dist/src/model-gateway/types.d.ts +47 -0
- package/dist/src/model-gateway/types.js +1 -0
- package/dist/src/routes/api.d.ts +2 -0
- package/dist/src/routes/api.js +128 -0
- package/dist/src/routes/websocket.d.ts +2 -0
- package/dist/src/routes/websocket.js +64 -0
- package/dist/src/types/index.d.ts +71 -0
- package/dist/src/types/index.js +1 -0
- package/dist/tests/core/context-manager.test.d.ts +1 -0
- package/dist/tests/core/context-manager.test.js +35 -0
- package/dist/tests/core/router.test.d.ts +1 -0
- package/dist/tests/core/router.test.js +79 -0
- package/dist/tests/model-gateway/circuit-breaker.test.d.ts +1 -0
- package/dist/tests/model-gateway/circuit-breaker.test.js +84 -0
- package/dist/tests/model-gateway/providers.test.d.ts +1 -0
- package/dist/tests/model-gateway/providers.test.js +80 -0
- package/dist/tests/model-gateway/quota.test.d.ts +1 -0
- package/dist/tests/model-gateway/quota.test.js +60 -0
- package/dist/tests/model-gateway/rate-limit.test.d.ts +1 -0
- package/dist/tests/model-gateway/rate-limit.test.js +42 -0
- package/dist/tests/model-gateway/retry.test.d.ts +1 -0
- package/dist/tests/model-gateway/retry.test.js +47 -0
- package/dist/tests/model-gateway/router.test.d.ts +1 -0
- package/dist/tests/model-gateway/router.test.js +108 -0
- package/dist/tests/model-gateway/routes.test.d.ts +1 -0
- package/dist/tests/model-gateway/routes.test.js +83 -0
- package/docs/api.md +187 -460
- package/docs/architecture.md +138 -0
- package/docs/configuration.md +188 -0
- package/package.json +3 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export class EventBus extends EventEmitter {
|
|
3
|
+
logger;
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
super();
|
|
6
|
+
this.logger = options.logger || console;
|
|
7
|
+
this.setMaxListeners(100);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 发布事件
|
|
11
|
+
*/
|
|
12
|
+
publish(eventType, data) {
|
|
13
|
+
const event = {
|
|
14
|
+
type: eventType,
|
|
15
|
+
data,
|
|
16
|
+
timestamp: Date.now()
|
|
17
|
+
};
|
|
18
|
+
this.emit(eventType, event);
|
|
19
|
+
this.logger.info(`[EventBus] Published: ${eventType}`, { id: data.id });
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 订阅事件
|
|
23
|
+
*/
|
|
24
|
+
subscribe(eventType, handler) {
|
|
25
|
+
this.on(eventType, handler);
|
|
26
|
+
this.logger.info(`[EventBus] Subscribed to: ${eventType}`);
|
|
27
|
+
// 返回取消订阅函数
|
|
28
|
+
return () => {
|
|
29
|
+
this.off(eventType, handler);
|
|
30
|
+
this.logger.info(`[EventBus] Unsubscribed from: ${eventType}`);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 发布任务事件
|
|
35
|
+
*/
|
|
36
|
+
publishTaskEvent(eventType, message) {
|
|
37
|
+
this.publish(eventType, message);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 发布 Agent 事件
|
|
41
|
+
*/
|
|
42
|
+
publishAgentEvent(eventType, message) {
|
|
43
|
+
this.publish(eventType, message);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 获取所有事件类型
|
|
47
|
+
*/
|
|
48
|
+
getEventTypes() {
|
|
49
|
+
return [
|
|
50
|
+
'agent.registered',
|
|
51
|
+
'agent.unregistered',
|
|
52
|
+
'task.submitted',
|
|
53
|
+
'task.assigned',
|
|
54
|
+
'task.started',
|
|
55
|
+
'task.progress',
|
|
56
|
+
'task.completed',
|
|
57
|
+
'task.failed',
|
|
58
|
+
'context.updated'
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export const eventBus = new EventBus();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
+
export interface Logger {
|
|
3
|
+
debug(msg: string, data?: Record<string, any>): void;
|
|
4
|
+
info(msg: string, data?: Record<string, any>): void;
|
|
5
|
+
warn(msg: string, data?: Record<string, any>): void;
|
|
6
|
+
error(msg: string, data?: Record<string, any>): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function initLogger(opts?: {
|
|
9
|
+
level?: LogLevel;
|
|
10
|
+
dir?: string;
|
|
11
|
+
pino?: any;
|
|
12
|
+
}): void;
|
|
13
|
+
export declare const logger: Logger;
|
|
14
|
+
export declare function createLogger(bindings?: Record<string, any>): Logger;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
4
|
+
let currentLevel = 'info';
|
|
5
|
+
let logDir = null;
|
|
6
|
+
let logFile = null;
|
|
7
|
+
let pinoInstance = null;
|
|
8
|
+
export function initLogger(opts = {}) {
|
|
9
|
+
currentLevel = opts.level || 'info';
|
|
10
|
+
if (opts.pino && typeof opts.pino.child === 'function') {
|
|
11
|
+
pinoInstance = opts.pino;
|
|
12
|
+
}
|
|
13
|
+
if (opts.dir) {
|
|
14
|
+
logDir = opts.dir;
|
|
15
|
+
if (!existsSync(logDir))
|
|
16
|
+
mkdirSync(logDir, { recursive: true });
|
|
17
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
18
|
+
logFile = join(logDir, `agentmesh-${date}.log`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function shouldLog(level) {
|
|
22
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];
|
|
23
|
+
}
|
|
24
|
+
function writeLine(level, msg, data) {
|
|
25
|
+
const ts = new Date().toISOString();
|
|
26
|
+
const extra = data ? ' ' + JSON.stringify(data) : '';
|
|
27
|
+
const line = `[${ts}] [${level.toUpperCase()}] ${msg}${extra}`;
|
|
28
|
+
if (pinoInstance) {
|
|
29
|
+
// 委托给 Pino: 将 data 序列化到消息中
|
|
30
|
+
pinoInstance[level](line);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
process.stderr.write(line + '\n');
|
|
34
|
+
}
|
|
35
|
+
if (logFile) {
|
|
36
|
+
try {
|
|
37
|
+
Bun.write(logFile, line + '\n').catch(() => { });
|
|
38
|
+
}
|
|
39
|
+
catch { }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export const logger = {
|
|
43
|
+
debug(msg, data) { if (shouldLog('debug'))
|
|
44
|
+
writeLine('debug', msg, data); },
|
|
45
|
+
info(msg, data) { if (shouldLog('info'))
|
|
46
|
+
writeLine('info', msg, data); },
|
|
47
|
+
warn(msg, data) { if (shouldLog('warn'))
|
|
48
|
+
writeLine('warn', msg, data); },
|
|
49
|
+
error(msg, data) { if (shouldLog('error'))
|
|
50
|
+
writeLine('error', msg, data); },
|
|
51
|
+
};
|
|
52
|
+
export function createLogger(bindings) {
|
|
53
|
+
if (!pinoInstance)
|
|
54
|
+
return logger;
|
|
55
|
+
// 直接从全局 pino 实例获取 child,当前版本用 context 前缀
|
|
56
|
+
return logger;
|
|
57
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
interface Metric {
|
|
2
|
+
name: string;
|
|
3
|
+
value: number;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
tags?: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
interface LogEntry {
|
|
8
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
9
|
+
message: string;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
data?: any;
|
|
12
|
+
}
|
|
13
|
+
export declare class Metrics {
|
|
14
|
+
private metrics;
|
|
15
|
+
private logs;
|
|
16
|
+
private logDir;
|
|
17
|
+
private maxMetricsHistory;
|
|
18
|
+
private maxLogsHistory;
|
|
19
|
+
constructor(logDir?: string);
|
|
20
|
+
private ensureLogDir;
|
|
21
|
+
/**
|
|
22
|
+
* 记录指标
|
|
23
|
+
*/
|
|
24
|
+
record(name: string, value: number, tags?: Record<string, string>): void;
|
|
25
|
+
/**
|
|
26
|
+
* 递增计数器
|
|
27
|
+
*/
|
|
28
|
+
increment(name: string, tags?: Record<string, string>): void;
|
|
29
|
+
/**
|
|
30
|
+
* 记录执行时间
|
|
31
|
+
*/
|
|
32
|
+
timing(name: string, duration: number, tags?: Record<string, string>): void;
|
|
33
|
+
/**
|
|
34
|
+
* 获取指标值
|
|
35
|
+
*/
|
|
36
|
+
get(name: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* 获取指标历史
|
|
39
|
+
*/
|
|
40
|
+
getHistory(name: string, limit?: number): Metric[];
|
|
41
|
+
/**
|
|
42
|
+
* 获取所有指标摘要
|
|
43
|
+
*/
|
|
44
|
+
getSummary(): Record<string, {
|
|
45
|
+
count: number;
|
|
46
|
+
last: number;
|
|
47
|
+
avg: number;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* 记录日志
|
|
51
|
+
*/
|
|
52
|
+
log(level: LogEntry['level'], message: string, data?: any): void;
|
|
53
|
+
private writeLogToFile;
|
|
54
|
+
/**
|
|
55
|
+
* 获取日志
|
|
56
|
+
*/
|
|
57
|
+
getLogs(level?: LogEntry['level'], limit?: number): LogEntry[];
|
|
58
|
+
/**
|
|
59
|
+
* 获取统计信息
|
|
60
|
+
*/
|
|
61
|
+
getStats(): {
|
|
62
|
+
uptime: number;
|
|
63
|
+
totalTasks: number;
|
|
64
|
+
completedTasks: number;
|
|
65
|
+
failedTasks: number;
|
|
66
|
+
activeAgents: number;
|
|
67
|
+
metricsCount: number;
|
|
68
|
+
logsCount: number;
|
|
69
|
+
};
|
|
70
|
+
private startTime;
|
|
71
|
+
/**
|
|
72
|
+
* 启动计时
|
|
73
|
+
*/
|
|
74
|
+
start(): void;
|
|
75
|
+
/**
|
|
76
|
+
* 重置指标
|
|
77
|
+
*/
|
|
78
|
+
reset(): void;
|
|
79
|
+
}
|
|
80
|
+
export declare const metrics: Metrics;
|
|
81
|
+
export declare const logger: {
|
|
82
|
+
debug: (message: string, data?: any) => void;
|
|
83
|
+
info: (message: string, data?: any) => void;
|
|
84
|
+
warn: (message: string, data?: any) => void;
|
|
85
|
+
error: (message: string, data?: any) => void;
|
|
86
|
+
};
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { writeFileSync, existsSync, mkdirSync, appendFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export class Metrics {
|
|
4
|
+
metrics = new Map();
|
|
5
|
+
logs = [];
|
|
6
|
+
logDir;
|
|
7
|
+
maxMetricsHistory = 1000;
|
|
8
|
+
maxLogsHistory = 1000;
|
|
9
|
+
constructor(logDir = './logs') {
|
|
10
|
+
this.logDir = logDir;
|
|
11
|
+
this.ensureLogDir();
|
|
12
|
+
}
|
|
13
|
+
ensureLogDir() {
|
|
14
|
+
if (!existsSync(this.logDir)) {
|
|
15
|
+
mkdirSync(this.logDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 记录指标
|
|
20
|
+
*/
|
|
21
|
+
record(name, value, tags) {
|
|
22
|
+
const metric = {
|
|
23
|
+
name,
|
|
24
|
+
value,
|
|
25
|
+
timestamp: Date.now(),
|
|
26
|
+
tags
|
|
27
|
+
};
|
|
28
|
+
if (!this.metrics.has(name)) {
|
|
29
|
+
this.metrics.set(name, []);
|
|
30
|
+
}
|
|
31
|
+
const history = this.metrics.get(name);
|
|
32
|
+
history.push(metric);
|
|
33
|
+
// 保持历史记录数量
|
|
34
|
+
if (history.length > this.maxMetricsHistory) {
|
|
35
|
+
history.shift();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 递增计数器
|
|
40
|
+
*/
|
|
41
|
+
increment(name, tags) {
|
|
42
|
+
const current = this.get(name);
|
|
43
|
+
this.record(name, current + 1, tags);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 记录执行时间
|
|
47
|
+
*/
|
|
48
|
+
timing(name, duration, tags) {
|
|
49
|
+
this.record(`${name}.duration`, duration, tags);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 获取指标值
|
|
53
|
+
*/
|
|
54
|
+
get(name) {
|
|
55
|
+
const history = this.metrics.get(name);
|
|
56
|
+
if (!history || history.length === 0)
|
|
57
|
+
return 0;
|
|
58
|
+
const last = history[history.length - 1];
|
|
59
|
+
return last?.value ?? 0;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 获取指标历史
|
|
63
|
+
*/
|
|
64
|
+
getHistory(name, limit) {
|
|
65
|
+
const history = this.metrics.get(name);
|
|
66
|
+
if (!history)
|
|
67
|
+
return [];
|
|
68
|
+
return limit ? history.slice(-limit) : history;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 获取所有指标摘要
|
|
72
|
+
*/
|
|
73
|
+
getSummary() {
|
|
74
|
+
const summary = {};
|
|
75
|
+
for (const [name, history] of this.metrics) {
|
|
76
|
+
if (history.length === 0)
|
|
77
|
+
continue;
|
|
78
|
+
const values = history.map(m => m.value);
|
|
79
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
80
|
+
summary[name] = {
|
|
81
|
+
count: history.length,
|
|
82
|
+
last: values[values.length - 1] ?? 0,
|
|
83
|
+
avg: sum / values.length
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return summary;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 记录日志
|
|
90
|
+
*/
|
|
91
|
+
log(level, message, data) {
|
|
92
|
+
const entry = {
|
|
93
|
+
level,
|
|
94
|
+
message,
|
|
95
|
+
timestamp: Date.now(),
|
|
96
|
+
data
|
|
97
|
+
};
|
|
98
|
+
this.logs.push(entry);
|
|
99
|
+
// 保持日志数量
|
|
100
|
+
if (this.logs.length > this.maxLogsHistory) {
|
|
101
|
+
this.logs.shift();
|
|
102
|
+
}
|
|
103
|
+
// 写入文件
|
|
104
|
+
this.writeLogToFile(entry);
|
|
105
|
+
}
|
|
106
|
+
writeLogToFile(entry) {
|
|
107
|
+
try {
|
|
108
|
+
const date = new Date(entry.timestamp).toISOString().split('T')[0];
|
|
109
|
+
const logFile = join(this.logDir, `gateway-${date}.log`);
|
|
110
|
+
const line = `[${new Date(entry.timestamp).toISOString()}] [${entry.level.toUpperCase()}] ${entry.message}${entry.data ? ' ' + JSON.stringify(entry.data) : ''}\n`;
|
|
111
|
+
appendFileSync(logFile, line);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error('Failed to write log to file:', error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 获取日志
|
|
119
|
+
*/
|
|
120
|
+
getLogs(level, limit) {
|
|
121
|
+
let filtered = this.logs;
|
|
122
|
+
if (level) {
|
|
123
|
+
filtered = filtered.filter(l => l.level === level);
|
|
124
|
+
}
|
|
125
|
+
return limit ? filtered.slice(-limit) : filtered;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 获取统计信息
|
|
129
|
+
*/
|
|
130
|
+
getStats() {
|
|
131
|
+
const taskHistory = this.metrics.get('tasks.submitted') || [];
|
|
132
|
+
const completedHistory = this.metrics.get('tasks.completed') || [];
|
|
133
|
+
const failedHistory = this.metrics.get('tasks.failed') || [];
|
|
134
|
+
return {
|
|
135
|
+
uptime: this.startTime ? Date.now() - this.startTime : 0,
|
|
136
|
+
totalTasks: taskHistory.length,
|
|
137
|
+
completedTasks: completedHistory.length,
|
|
138
|
+
failedTasks: failedHistory.length,
|
|
139
|
+
activeAgents: this.metrics.get('agents.active')?.[0]?.value || 0,
|
|
140
|
+
metricsCount: this.metrics.size,
|
|
141
|
+
logsCount: this.logs.length
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
startTime = Date.now();
|
|
145
|
+
/**
|
|
146
|
+
* 启动计时
|
|
147
|
+
*/
|
|
148
|
+
start() {
|
|
149
|
+
this.startTime = Date.now();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 重置指标
|
|
153
|
+
*/
|
|
154
|
+
reset() {
|
|
155
|
+
this.metrics.clear();
|
|
156
|
+
this.logs = [];
|
|
157
|
+
this.startTime = Date.now();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export const metrics = new Metrics();
|
|
161
|
+
// 便捷方法
|
|
162
|
+
export const logger = {
|
|
163
|
+
debug: (message, data) => metrics.log('debug', message, data),
|
|
164
|
+
info: (message, data) => metrics.log('info', message, data),
|
|
165
|
+
warn: (message, data) => metrics.log('warn', message, data),
|
|
166
|
+
error: (message, data) => metrics.log('error', message, data)
|
|
167
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Agent, RoutingRule, AgentMessage } from '../types/index.js';
|
|
2
|
+
export declare class Router {
|
|
3
|
+
private rules;
|
|
4
|
+
private agents;
|
|
5
|
+
private defaultAgent?;
|
|
6
|
+
/**
|
|
7
|
+
* 配置路由规则
|
|
8
|
+
*/
|
|
9
|
+
configure(rules: RoutingRule[], defaultAgent?: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* 注册 Agent
|
|
12
|
+
*/
|
|
13
|
+
registerAgent(agent: Agent): void;
|
|
14
|
+
/**
|
|
15
|
+
* 注销 Agent
|
|
16
|
+
*/
|
|
17
|
+
unregisterAgent(agentId: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* 获取所有在线 Agent
|
|
20
|
+
*/
|
|
21
|
+
getOnlineAgents(): Agent[];
|
|
22
|
+
/**
|
|
23
|
+
* 路由任务到合适的 Agent
|
|
24
|
+
*/
|
|
25
|
+
route(message: AgentMessage): {
|
|
26
|
+
agentIds: string[];
|
|
27
|
+
strategy: 'direct' | 'broadcast';
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* 检查任务是否匹配路由关键词
|
|
31
|
+
*/
|
|
32
|
+
private matchesRule;
|
|
33
|
+
/**
|
|
34
|
+
* 检查 Agent 是否在线
|
|
35
|
+
*/
|
|
36
|
+
private isAgentOnline;
|
|
37
|
+
/**
|
|
38
|
+
* 获取 Agent 信息
|
|
39
|
+
*/
|
|
40
|
+
getAgent(agentId: string): Agent | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* 获取所有 Agent
|
|
43
|
+
*/
|
|
44
|
+
getAllAgents(): Agent[];
|
|
45
|
+
}
|
|
46
|
+
export declare const router: Router;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export class Router {
|
|
2
|
+
rules = [];
|
|
3
|
+
agents = new Map();
|
|
4
|
+
defaultAgent;
|
|
5
|
+
/**
|
|
6
|
+
* 配置路由规则
|
|
7
|
+
*/
|
|
8
|
+
configure(rules, defaultAgent) {
|
|
9
|
+
// 按优先级排序
|
|
10
|
+
this.rules = [...rules].sort((a, b) => b.priority - a.priority);
|
|
11
|
+
this.defaultAgent = defaultAgent;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 注册 Agent
|
|
15
|
+
*/
|
|
16
|
+
registerAgent(agent) {
|
|
17
|
+
this.agents.set(agent.id, agent);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 注销 Agent
|
|
21
|
+
*/
|
|
22
|
+
unregisterAgent(agentId) {
|
|
23
|
+
this.agents.delete(agentId);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 获取所有在线 Agent
|
|
27
|
+
*/
|
|
28
|
+
getOnlineAgents() {
|
|
29
|
+
return Array.from(this.agents.values()).filter(a => a.status === 'online');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 路由任务到合适的 Agent
|
|
33
|
+
*/
|
|
34
|
+
route(message) {
|
|
35
|
+
const task = message.payload?.task || '';
|
|
36
|
+
// 匹配路由规则
|
|
37
|
+
for (const rule of this.rules) {
|
|
38
|
+
if (this.matchesRule(task, rule.keywords)) {
|
|
39
|
+
// 检查 Agent 是否在线
|
|
40
|
+
if (rule.strategy === 'broadcast' && rule.agents) {
|
|
41
|
+
const availableAgents = rule.agents.filter(id => this.isAgentOnline(id));
|
|
42
|
+
if (availableAgents.length > 0) {
|
|
43
|
+
return { agentIds: availableAgents, strategy: 'broadcast' };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (rule.agent && this.isAgentOnline(rule.agent)) {
|
|
47
|
+
return { agentIds: [rule.agent], strategy: 'direct' };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// 使用默认 Agent
|
|
52
|
+
if (this.defaultAgent && this.isAgentOnline(this.defaultAgent)) {
|
|
53
|
+
return { agentIds: [this.defaultAgent], strategy: 'direct' };
|
|
54
|
+
}
|
|
55
|
+
// 返回所有在线 Agent 作为兜底
|
|
56
|
+
const onlineAgents = this.getOnlineAgents();
|
|
57
|
+
if (onlineAgents.length > 0) {
|
|
58
|
+
return { agentIds: onlineAgents.map(a => a.id), strategy: 'broadcast' };
|
|
59
|
+
}
|
|
60
|
+
// 没有可用的 Agent
|
|
61
|
+
return { agentIds: [], strategy: 'direct' };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 检查任务是否匹配路由关键词
|
|
65
|
+
*/
|
|
66
|
+
matchesRule(task, keywords) {
|
|
67
|
+
const lowerTask = task.toLowerCase();
|
|
68
|
+
return keywords.some(keyword => lowerTask.includes(keyword.toLowerCase()));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 检查 Agent 是否在线
|
|
72
|
+
*/
|
|
73
|
+
isAgentOnline(agentId) {
|
|
74
|
+
const agent = this.agents.get(agentId);
|
|
75
|
+
return agent?.status === 'online';
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 获取 Agent 信息
|
|
79
|
+
*/
|
|
80
|
+
getAgent(agentId) {
|
|
81
|
+
return this.agents.get(agentId);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 获取所有 Agent
|
|
85
|
+
*/
|
|
86
|
+
getAllAgents() {
|
|
87
|
+
return Array.from(this.agents.values());
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export const router = new Router();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Task, AgentMessage, Error } from '../types/index.js';
|
|
2
|
+
export declare class TaskManager {
|
|
3
|
+
private tasks;
|
|
4
|
+
/**
|
|
5
|
+
* 创建新任务
|
|
6
|
+
*/
|
|
7
|
+
createTask(request: AgentMessage): Promise<Task>;
|
|
8
|
+
/**
|
|
9
|
+
* 分配任务到 Agent
|
|
10
|
+
*/
|
|
11
|
+
assignTask(taskId: string, agentIds: string[]): Task | null;
|
|
12
|
+
/**
|
|
13
|
+
* 开始执行任务
|
|
14
|
+
*/
|
|
15
|
+
startTask(taskId: string): Task | null;
|
|
16
|
+
/**
|
|
17
|
+
* 完成任务
|
|
18
|
+
*/
|
|
19
|
+
completeTask(taskId: string, result: unknown): Task | null;
|
|
20
|
+
/**
|
|
21
|
+
* 任务失败
|
|
22
|
+
*/
|
|
23
|
+
failTask(taskId: string, error: Error): Task | null;
|
|
24
|
+
/**
|
|
25
|
+
* 获取任务
|
|
26
|
+
*/
|
|
27
|
+
getTask(taskId: string): Task | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* 获取所有任务
|
|
30
|
+
*/
|
|
31
|
+
getAllTasks(): Task[];
|
|
32
|
+
/**
|
|
33
|
+
* 处理任务
|
|
34
|
+
*/
|
|
35
|
+
processTask(message: AgentMessage): Promise<Task>;
|
|
36
|
+
/**
|
|
37
|
+
* 执行任务
|
|
38
|
+
*/
|
|
39
|
+
private executeTask;
|
|
40
|
+
}
|
|
41
|
+
export declare const taskManager: TaskManager;
|