@starlink-awaken/agentmesh 1.0.2 → 1.0.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.
@@ -0,0 +1,101 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { parse } from 'yaml';
3
+ import { join } from 'path';
4
+ const DEFAULT_CONFIG = {
5
+ port: 3000,
6
+ wsPort: 3001,
7
+ host: '0.0.0.0',
8
+ dataDir: './data',
9
+ logDir: './logs',
10
+ logLevel: 'info',
11
+ routing: {
12
+ defaultAgent: 'claude-code',
13
+ rules: []
14
+ },
15
+ agents: []
16
+ };
17
+ let cachedConfig = null;
18
+ /**
19
+ * 加载配置文件
20
+ */
21
+ export function loadConfig(configPath) {
22
+ if (cachedConfig) {
23
+ return cachedConfig;
24
+ }
25
+ const paths = configPath
26
+ ? [configPath]
27
+ : [
28
+ './config/gateway.yaml',
29
+ './config/gateway.yml',
30
+ join(process.cwd(), 'config/gateway.yaml'),
31
+ join(process.cwd(), 'config/gateway.yml')
32
+ ];
33
+ for (const path of paths) {
34
+ try {
35
+ if (existsSync(path)) {
36
+ console.log(`[Config] Loading from: ${path}`);
37
+ const content = readFileSync(path, 'utf-8');
38
+ const parsed = parse(content);
39
+ // 合并配置
40
+ cachedConfig = {
41
+ ...DEFAULT_CONFIG,
42
+ ...parsed,
43
+ routing: {
44
+ ...DEFAULT_CONFIG.routing,
45
+ ...parsed.routing,
46
+ rules: parsed.routing?.rules || DEFAULT_CONFIG.routing.rules
47
+ }
48
+ };
49
+ console.log(`[Config] Loaded successfully`);
50
+ return cachedConfig;
51
+ }
52
+ }
53
+ catch (error) {
54
+ console.warn(`[Config] Failed to load ${path}:`, error);
55
+ }
56
+ }
57
+ console.log('[Config] Using default configuration');
58
+ cachedConfig = { ...DEFAULT_CONFIG };
59
+ return cachedConfig;
60
+ }
61
+ /**
62
+ * 重新加载配置
63
+ */
64
+ export function reloadConfig(configPath) {
65
+ cachedConfig = null;
66
+ return loadConfig(configPath);
67
+ }
68
+ /**
69
+ * 获取配置
70
+ */
71
+ export function getConfig() {
72
+ if (!cachedConfig) {
73
+ return loadConfig();
74
+ }
75
+ return cachedConfig;
76
+ }
77
+ /**
78
+ * 获取 Agent 配置
79
+ */
80
+ export function getAgentConfig(agentId) {
81
+ const config = getConfig();
82
+ return config.agents.find(a => a.id === agentId);
83
+ }
84
+ /**
85
+ * 获取所有 Agent 配置
86
+ */
87
+ export function getAllAgentConfigs() {
88
+ return getConfig().agents;
89
+ }
90
+ /**
91
+ * 获取路由规则
92
+ */
93
+ export function getRoutingRules() {
94
+ return getConfig().routing.rules;
95
+ }
96
+ /**
97
+ * 获取默认 Agent
98
+ */
99
+ export function getDefaultAgent() {
100
+ return getConfig().routing.defaultAgent;
101
+ }
@@ -0,0 +1,52 @@
1
+ import type { AgentMessage, ContextRef } from '../types/index.js';
2
+ interface ContextData {
3
+ shared_space_id: string;
4
+ messages: AgentMessage[];
5
+ artifacts: Map<string, string>;
6
+ metadata: Record<string, unknown>;
7
+ createdAt: number;
8
+ updatedAt: number;
9
+ }
10
+ export declare class ContextManager {
11
+ private memoryCache;
12
+ private baseDir;
13
+ constructor(baseDir?: string);
14
+ /**
15
+ * 创建共享空间
16
+ */
17
+ createSharedSpace(metadata?: Record<string, unknown>): Promise<string>;
18
+ /**
19
+ * 获取共享空间
20
+ */
21
+ getSharedSpace(spaceId: string): Promise<ContextData | null>;
22
+ /**
23
+ * 添加消息到共享空间
24
+ */
25
+ addMessage(spaceId: string, message: AgentMessage): Promise<void>;
26
+ /**
27
+ * 获取消息历史
28
+ */
29
+ getMessages(spaceId: string, limit?: number): Promise<AgentMessage[]>;
30
+ /**
31
+ * 添加产物文件
32
+ */
33
+ addArtifact(spaceId: string, filename: string, content: string): Promise<string>;
34
+ /**
35
+ * 获取产物文件
36
+ */
37
+ getArtifact(spaceId: string, filename: string): Promise<string | null>;
38
+ /**
39
+ * 持久化到文件系统
40
+ */
41
+ private persistToFile;
42
+ /**
43
+ * 从文件系统加载
44
+ */
45
+ private loadFromFile;
46
+ /**
47
+ * 创建 ContextRef
48
+ */
49
+ createContextRef(spaceId: string): Promise<ContextRef>;
50
+ }
51
+ export declare const contextManager: ContextManager;
52
+ export {};
@@ -0,0 +1,165 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join } from 'path';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ import { vectorStore } from './vector-store.js';
5
+ export class ContextManager {
6
+ memoryCache = new Map();
7
+ baseDir;
8
+ constructor(baseDir = './data/tasks') {
9
+ this.baseDir = baseDir;
10
+ }
11
+ /**
12
+ * 创建共享空间
13
+ */
14
+ async createSharedSpace(metadata = {}) {
15
+ const spaceId = uuidv4();
16
+ const context = {
17
+ shared_space_id: spaceId,
18
+ messages: [],
19
+ artifacts: new Map(),
20
+ metadata,
21
+ createdAt: Date.now(),
22
+ updatedAt: Date.now()
23
+ };
24
+ // L1: 内存缓存
25
+ this.memoryCache.set(spaceId, context);
26
+ // L2: 文件系统持久化
27
+ await this.persistToFile(spaceId, context);
28
+ return spaceId;
29
+ }
30
+ /**
31
+ * 获取共享空间
32
+ */
33
+ async getSharedSpace(spaceId) {
34
+ // L1: 先从内存获取
35
+ if (this.memoryCache.has(spaceId)) {
36
+ return this.memoryCache.get(spaceId);
37
+ }
38
+ // L2: 从文件系统加载
39
+ try {
40
+ const context = await this.loadFromFile(spaceId);
41
+ if (context) {
42
+ this.memoryCache.set(spaceId, context);
43
+ return context;
44
+ }
45
+ }
46
+ catch (error) {
47
+ console.error(`[ContextManager] Failed to load context: ${spaceId}`, error);
48
+ }
49
+ return null;
50
+ }
51
+ /**
52
+ * 添加消息到共享空间
53
+ */
54
+ async addMessage(spaceId, message) {
55
+ const context = await this.getSharedSpace(spaceId);
56
+ if (!context) {
57
+ throw new Error(`Shared space not found: ${spaceId}`);
58
+ }
59
+ context.messages.push(message);
60
+ context.updatedAt = Date.now();
61
+ // 更新内存缓存
62
+ this.memoryCache.set(spaceId, context);
63
+ // 持久化到文件系统
64
+ await this.persistToFile(spaceId, context);
65
+ // L3: 添加到向量数据库(异步,不阻塞)
66
+ if (vectorStore.isAvailable()) {
67
+ vectorStore.addMessage(spaceId, message).catch(err => {
68
+ console.error('[ContextManager] Vector store add failed:', err);
69
+ });
70
+ }
71
+ }
72
+ /**
73
+ * 获取消息历史
74
+ */
75
+ async getMessages(spaceId, limit) {
76
+ const context = await this.getSharedSpace(spaceId);
77
+ if (!context) {
78
+ return [];
79
+ }
80
+ const messages = context.messages;
81
+ return limit ? messages.slice(-limit) : messages;
82
+ }
83
+ /**
84
+ * 添加产物文件
85
+ */
86
+ async addArtifact(spaceId, filename, content) {
87
+ const context = await this.getSharedSpace(spaceId);
88
+ if (!context) {
89
+ throw new Error(`Shared space not found: ${spaceId}`);
90
+ }
91
+ const artifactsDir = join(this.baseDir, spaceId, 'artifacts');
92
+ await fs.mkdir(artifactsDir, { recursive: true });
93
+ const filePath = join(artifactsDir, filename);
94
+ await fs.writeFile(filePath, content, 'utf-8');
95
+ context.artifacts.set(filename, filePath);
96
+ context.updatedAt = Date.now();
97
+ // 更新内存缓存
98
+ this.memoryCache.set(spaceId, context);
99
+ // 持久化
100
+ await this.persistToFile(spaceId, context);
101
+ return filePath;
102
+ }
103
+ /**
104
+ * 获取产物文件
105
+ */
106
+ async getArtifact(spaceId, filename) {
107
+ const context = await this.getSharedSpace(spaceId);
108
+ if (!context) {
109
+ return null;
110
+ }
111
+ const filePath = context.artifacts.get(filename);
112
+ if (!filePath) {
113
+ return null;
114
+ }
115
+ try {
116
+ return await fs.readFile(filePath, 'utf-8');
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ /**
123
+ * 持久化到文件系统
124
+ */
125
+ async persistToFile(spaceId, context) {
126
+ const dir = join(this.baseDir, spaceId);
127
+ await fs.mkdir(dir, { recursive: true });
128
+ // 序列化 context(Map 需要转换)
129
+ const serialized = {
130
+ shared_space_id: context.shared_space_id,
131
+ messages: context.messages,
132
+ artifacts: Object.fromEntries(context.artifacts),
133
+ metadata: context.metadata,
134
+ createdAt: context.createdAt,
135
+ updatedAt: context.updatedAt
136
+ };
137
+ await fs.writeFile(join(dir, 'context.json'), JSON.stringify(serialized, null, 2), 'utf-8');
138
+ }
139
+ /**
140
+ * 从文件系统加载
141
+ */
142
+ async loadFromFile(spaceId) {
143
+ const filePath = join(this.baseDir, spaceId, 'context.json');
144
+ try {
145
+ const content = await fs.readFile(filePath, 'utf-8');
146
+ const parsed = JSON.parse(content);
147
+ return {
148
+ ...parsed,
149
+ artifacts: new Map(Object.entries(parsed.artifacts || {}))
150
+ };
151
+ }
152
+ catch {
153
+ return null;
154
+ }
155
+ }
156
+ /**
157
+ * 创建 ContextRef
158
+ */
159
+ async createContextRef(spaceId) {
160
+ return {
161
+ shared_space_id: spaceId
162
+ };
163
+ }
164
+ }
165
+ export const contextManager = new ContextManager();
@@ -0,0 +1,35 @@
1
+ import { EventEmitter } from 'events';
2
+ import type { AgentMessage, EventType } from '../types/index.js';
3
+ interface EventBusOptions {
4
+ logger?: Console;
5
+ }
6
+ export declare class EventBus extends EventEmitter {
7
+ private logger;
8
+ constructor(options?: EventBusOptions);
9
+ /**
10
+ * 发布事件
11
+ */
12
+ publish(eventType: EventType, data: AgentMessage): void;
13
+ /**
14
+ * 订阅事件
15
+ */
16
+ subscribe(eventType: EventType, handler: (event: {
17
+ type: EventType;
18
+ data: AgentMessage;
19
+ timestamp: number;
20
+ }) => void): () => void;
21
+ /**
22
+ * 发布任务事件
23
+ */
24
+ publishTaskEvent(eventType: Exclude<EventType, 'agent.registered' | 'agent.unregistered'>, message: AgentMessage): void;
25
+ /**
26
+ * 发布 Agent 事件
27
+ */
28
+ publishAgentEvent(eventType: 'agent.registered' | 'agent.unregistered', message: AgentMessage): void;
29
+ /**
30
+ * 获取所有事件类型
31
+ */
32
+ getEventTypes(): EventType[];
33
+ }
34
+ export declare const eventBus: EventBus;
35
+ export {};
@@ -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,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
+ };