@starlink-awaken/agentmesh 1.4.0 → 1.5.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 +31 -1
- package/dist/src/cli/release.d.ts +2 -0
- package/dist/src/cli/release.js +94 -0
- package/dist/src/cli.js +117 -31
- package/dist/src/core/agent-registry.d.ts +2 -0
- package/dist/src/core/agent-registry.js +12 -154
- package/dist/src/core/agents.default.d.ts +7 -0
- package/dist/src/core/agents.default.js +154 -0
- package/dist/src/core/config.d.ts +21 -0
- package/dist/src/core/context-manager.d.ts +2 -0
- package/dist/src/core/context-manager.js +4 -0
- package/dist/src/core/gateway.d.ts +79 -0
- package/dist/src/core/gateway.js +223 -0
- package/dist/src/core/pipeline.d.ts +21 -0
- package/dist/src/core/pipeline.js +48 -0
- package/dist/src/core/router.d.ts +2 -1
- package/dist/src/core/scheduler.d.ts +28 -0
- package/dist/src/core/scheduler.js +68 -0
- package/dist/src/core/store.d.ts +18 -0
- package/dist/src/core/store.js +77 -0
- package/dist/src/core/task-manager.d.ts +19 -27
- package/dist/src/core/task-manager.js +89 -80
- package/dist/src/core/vector-store.d.ts +2 -0
- package/dist/src/core/vector-store.js +4 -0
- package/dist/src/hermes/routes.d.ts +13 -0
- package/dist/src/hermes/routes.js +115 -0
- package/dist/src/index.js +76 -50
- package/dist/src/model-gateway/rate-limit.js +9 -0
- package/dist/src/model-gateway/routes.js +5 -5
- package/dist/src/routes/api.js +71 -7
- package/dist/src/routes/dashboard.d.ts +2 -0
- package/dist/src/routes/dashboard.js +113 -0
- package/dist/src/routes/sse.d.ts +2 -0
- package/dist/src/routes/sse.js +64 -0
- package/dist/src/types/index.d.ts +0 -19
- package/dist/src/types/index.js +2 -0
- package/dist/tests/model-gateway/routes.test.js +4 -4
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## [1.5.0] — 2026-05-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **GatewayContainer**: Unified DI lifecycle manager wrapping all core singletons (`init → reload → dispose`)
|
|
7
|
+
- **Task Persistence**: bun:sqlite backend, WAL mode, tasks survive restarts
|
|
8
|
+
- **Task Cancellation**: `POST /v1/tasks/:id/cancel` + `agentmesh cancel <id>`
|
|
9
|
+
- **Agent Hot Reload**: edit `config/gateway.yaml`, agents auto-reload within 3s
|
|
10
|
+
- **Web Dashboard**: `GET /dashboard` — real-time status with Dark theme, auto-refresh
|
|
11
|
+
- **Scheduled Tasks**: cron-based scheduler via `POST /v1/scheduler` + cron-parser
|
|
12
|
+
- **Agent Pipeline**: multi-agent sequential execution via `POST /v1/pipeline`
|
|
13
|
+
- **Graceful Shutdown**: SIGTERM/SIGINT → dispose + fastify.close
|
|
14
|
+
- **Detailed Health**: `GET /v1/health/detailed` with circuit breakers, config, uptime
|
|
15
|
+
- **CLI Table Output**: Unicode box-drawing + ANSI colors for agents/tasks/models/health
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- **API Versioning**: All routes unified under `/v1/` prefix (model-gateway management included)
|
|
19
|
+
- **Routes renamed**: `websocket.ts` → `sse.ts` (was always SSE, never WebSocket)
|
|
20
|
+
- **Type cleanup**: Duplicate `GatewayConfig`/`RoutingRule` removed from types/index.ts
|
|
21
|
+
- **Agent configs**: 25+ hardcoded defaults extracted to `src/core/agents.default.ts`
|
|
22
|
+
- **Config injection**: `(config as any).models` replaced with typed `ModelsSection` + YAML→TS mapping
|
|
23
|
+
- **Logger unified**: Pino bridge via `initLogger({ pino: fastify.log })`
|
|
24
|
+
- **Error handling**: Global `setErrorHandler` + consistent `{error: {code, message}}` format
|
|
25
|
+
- **Rate limiter**: Now configurable from YAML `models.defaults.rate_limit`
|
|
26
|
+
- **Storage paths**: Derived from `config.dataDir` instead of hardcoded `./data/`
|
|
27
|
+
- **cron-parser**: Replaces hand-rolled 40-line cron implementation
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- `purgeCompleted` count overwrite bug when store is present
|
|
31
|
+
- `startConfigWatcher` file watcher leak on dispose
|
|
32
|
+
- `reloadAgents` unconditional re-registration of unchanged agents
|
|
33
|
+
- `TaskManager` removes stale JSDoc cruft, uses single `_save()` path
|
|
4
34
|
|
|
5
35
|
## [1.2.0] — 2026-05-16
|
|
6
36
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// agentmesh release — 一键发版:check → test → build → bump → commit → push → publish
|
|
3
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { join, dirname } from 'node:path';
|
|
5
|
+
// logger 由 cli 入口统一初始化,此模块不需要
|
|
6
|
+
const PROJECT_ROOT = dirname(dirname(import.meta.dir || import.meta.dirname || '.'));
|
|
7
|
+
class ReleaseError extends Error {
|
|
8
|
+
}
|
|
9
|
+
async function sh(cmd, cwd) {
|
|
10
|
+
const proc = Bun.spawn(cmd, { cwd: cwd || PROJECT_ROOT, stdout: 'pipe', stderr: 'pipe' });
|
|
11
|
+
const out = await new Response(proc.stdout).text();
|
|
12
|
+
await proc.exited;
|
|
13
|
+
if (proc.exitCode !== 0) {
|
|
14
|
+
const err = await new Response(proc.stderr).text();
|
|
15
|
+
throw new ReleaseError(`${cmd.join(' ')} failed (exit ${proc.exitCode}): ${err || out}`);
|
|
16
|
+
}
|
|
17
|
+
return out.trim();
|
|
18
|
+
}
|
|
19
|
+
function bumpVersion(current, level) {
|
|
20
|
+
const parts = current.split('.').map(Number);
|
|
21
|
+
if (parts.length !== 3)
|
|
22
|
+
throw new ReleaseError(`Invalid version: ${current}`);
|
|
23
|
+
switch (level) {
|
|
24
|
+
case 'major':
|
|
25
|
+
parts[0]++;
|
|
26
|
+
parts[1] = 0;
|
|
27
|
+
parts[2] = 0;
|
|
28
|
+
break;
|
|
29
|
+
case 'minor':
|
|
30
|
+
parts[1]++;
|
|
31
|
+
parts[2] = 0;
|
|
32
|
+
break;
|
|
33
|
+
case 'patch':
|
|
34
|
+
parts[2]++;
|
|
35
|
+
break;
|
|
36
|
+
default: throw new ReleaseError(`Unknown bump level: ${level}`);
|
|
37
|
+
}
|
|
38
|
+
return parts.join('.');
|
|
39
|
+
}
|
|
40
|
+
function updateVersionFiles(newVer) {
|
|
41
|
+
const pkgPath = join(PROJECT_ROOT, 'package.json');
|
|
42
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
43
|
+
pkg.version = newVer;
|
|
44
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
45
|
+
const cliPath = join(PROJECT_ROOT, 'src', 'cli.ts');
|
|
46
|
+
let cli = readFileSync(cliPath, 'utf-8');
|
|
47
|
+
cli = cli.replace(/const VERSION = '[^']+'/, `const VERSION = '${newVer}'`);
|
|
48
|
+
writeFileSync(cliPath, cli);
|
|
49
|
+
}
|
|
50
|
+
export async function runRelease(level = 'patch') {
|
|
51
|
+
const pkg = JSON.parse(readFileSync(join(PROJECT_ROOT, 'package.json'), 'utf-8'));
|
|
52
|
+
const oldVer = pkg.version;
|
|
53
|
+
const newVer = bumpVersion(oldVer, level);
|
|
54
|
+
console.log(`\n 🚀 Release: ${oldVer} → ${newVer} (${level})\n`);
|
|
55
|
+
// 1. Typecheck
|
|
56
|
+
console.log(' [1/6] Typecheck...');
|
|
57
|
+
await sh(['bun', 'run', 'typecheck']);
|
|
58
|
+
console.log(' ✅ Typecheck passed');
|
|
59
|
+
// 2. Test
|
|
60
|
+
console.log(' [2/6] Test...');
|
|
61
|
+
await sh(['bun', 'test']);
|
|
62
|
+
console.log(' ✅ Tests passed');
|
|
63
|
+
// 3. Build
|
|
64
|
+
console.log(' [3/6] Build...');
|
|
65
|
+
await sh(['bun', 'run', 'build']);
|
|
66
|
+
console.log(' ✅ Build done');
|
|
67
|
+
// 4. Bump version
|
|
68
|
+
console.log(` [4/6] Bump version: ${oldVer} → ${newVer}`);
|
|
69
|
+
updateVersionFiles(newVer);
|
|
70
|
+
console.log(' ✅ Version updated');
|
|
71
|
+
// 5. Commit + Push
|
|
72
|
+
console.log(' [5/6] Commit + Push...');
|
|
73
|
+
await sh(['git', 'add', '-A']);
|
|
74
|
+
await sh(['git', 'commit', '-m', `Release v${newVer}`]);
|
|
75
|
+
await sh(['git', 'push', 'origin', 'main']);
|
|
76
|
+
console.log(' ✅ Pushed to GitHub');
|
|
77
|
+
// 6. Publish to npm
|
|
78
|
+
console.log(' [6/7] Publish to npm...');
|
|
79
|
+
const pubOut = await sh(['npm', 'publish']);
|
|
80
|
+
console.log(` ✅ Published: ${pubOut}`);
|
|
81
|
+
// 7. Install latest globally
|
|
82
|
+
console.log(' [7/7] Install latest...');
|
|
83
|
+
await sh(['npm', 'install', '-g', `@starlink-awaken/agentmesh@${newVer}`]);
|
|
84
|
+
console.log(' ✅ Installed globally');
|
|
85
|
+
console.log(`\n 🎉 v${newVer} released & installed!\n`);
|
|
86
|
+
return newVer;
|
|
87
|
+
}
|
|
88
|
+
if (import.meta.main) {
|
|
89
|
+
const level = Bun.argv[2] || 'patch';
|
|
90
|
+
runRelease(level).catch(err => {
|
|
91
|
+
console.error(`\n ❌ Release failed: ${err.message}\n`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
|
94
|
+
}
|
package/dist/src/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
7
7
|
import { resolve, dirname, join } from 'node:path';
|
|
8
8
|
import { initLogger } from './core/logger.js';
|
|
9
9
|
const PROJECT_ROOT = resolve(dirname(import.meta.dir), '..');
|
|
10
|
-
const VERSION = '1.
|
|
10
|
+
const VERSION = '1.5.0';
|
|
11
11
|
const BANNER = `
|
|
12
12
|
█████╗ ██████╗ ███████╗███╗ ██╗████████╗
|
|
13
13
|
██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝
|
|
@@ -17,6 +17,19 @@ const BANNER = `
|
|
|
17
17
|
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝
|
|
18
18
|
𝙼 𝙴 𝚂 𝙷 𝙶 𝙰 𝚃 𝙴 𝚆 𝙰 𝚈 v${VERSION}
|
|
19
19
|
`;
|
|
20
|
+
const C = { reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m' };
|
|
21
|
+
const ICON = { ok: '✅', fail: '❌', warn: '⚠️', dot: '⚫' };
|
|
22
|
+
const STATUS_ICON = { completed: '🎯', failed: '❌', running: '🔄', pending: '🕐', assigned: '⚫' };
|
|
23
|
+
function table(headers, rows) {
|
|
24
|
+
const widths = headers.map((h, i) => Math.max(h.length, ...rows.map(r => (r[i] || '').length)));
|
|
25
|
+
const sep = '─'.repeat(widths.reduce((a, b) => a + b, 0) + widths.length * 3 + 1);
|
|
26
|
+
let out = `╭${sep}╮\n│ ${headers.map((h, i) => C.bold + h.padEnd(widths[i]) + C.reset).join(' │ ')} │\n├${sep}┤\n`;
|
|
27
|
+
for (const row of rows) {
|
|
28
|
+
out += `│ ${row.map((cell, i) => cell.padEnd(widths[i])).join(' │ ')} │\n`;
|
|
29
|
+
}
|
|
30
|
+
out += `╰${sep}╯`;
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
20
33
|
const BASE_URL = () => {
|
|
21
34
|
const host = Bun.env.AGENT_GATEWAY_HOST || '127.0.0.1';
|
|
22
35
|
const port = Bun.env.AGENT_GATEWAY_PORT || '3000';
|
|
@@ -98,6 +111,7 @@ ${BANNER}
|
|
|
98
111
|
接入命令:
|
|
99
112
|
connect [tool] 一键接入 AI 工具 (--dry-run 预览)
|
|
100
113
|
disconnect [tool] 恢复工具配置到接入前状态
|
|
114
|
+
hermes setup 配置 Hermes 双向通路 (手机↔网关)
|
|
101
115
|
|
|
102
116
|
查询命令:
|
|
103
117
|
health, status 健康检查
|
|
@@ -105,6 +119,7 @@ ${BANNER}
|
|
|
105
119
|
quota 查看配额状态
|
|
106
120
|
agents 列出已注册 Agent
|
|
107
121
|
tasks 列出任务列表
|
|
122
|
+
cancel <id> 取消指定任务
|
|
108
123
|
|
|
109
124
|
配置命令:
|
|
110
125
|
config show 显示当前配置
|
|
@@ -140,10 +155,10 @@ async function cmdStart(args) {
|
|
|
140
155
|
console.log(`${BANNER}
|
|
141
156
|
🚀 Starting Agent Mesh Gateway...
|
|
142
157
|
═══════════════════════════════════════
|
|
143
|
-
|
|
144
|
-
Health: http://${host}:${port}/health
|
|
158
|
+
API v1: http://${host}:${port}/v1
|
|
159
|
+
Health: http://${host}:${port}/v1/health
|
|
145
160
|
Models: http://${host}:${port}/v1/models
|
|
146
|
-
Quota: http://${host}:${port}/model-gateway/quota
|
|
161
|
+
Quota: http://${host}:${port}/v1/model-gateway/quota
|
|
147
162
|
Docs: http://${host}:${port}/docs
|
|
148
163
|
═══════════════════════════════════════
|
|
149
164
|
`);
|
|
@@ -153,40 +168,41 @@ async function cmdStart(args) {
|
|
|
153
168
|
}
|
|
154
169
|
async function cmdHealth() {
|
|
155
170
|
try {
|
|
156
|
-
const data = await apiRequest('/health');
|
|
157
|
-
console.log(`\n
|
|
158
|
-
console.log(` Status:
|
|
159
|
-
|
|
160
|
-
|
|
171
|
+
const data = await apiRequest('/v1/health');
|
|
172
|
+
console.log(`\n ${C.green}${ICON.ok} Gateway Running${C.reset}`);
|
|
173
|
+
console.log(` Status: ${C.bold}${data.status}${C.reset} Uptime: ${C.cyan}${data.uptime_seconds}s${C.reset} Agents: ${C.green}${data.agents?.online || data.agents?.length || 0} online${C.reset} / ${data.agents?.total || data.agents?.length || 0} total`);
|
|
174
|
+
if (data.tasks) {
|
|
175
|
+
console.log(` Tasks: ${C.yellow}${data.tasks.pending}pending${C.reset} ${C.cyan}${data.tasks.running}running${C.reset} ${C.green}${data.tasks.completed}done${C.reset} ${C.red}${data.tasks.failed}failed${C.reset}`);
|
|
176
|
+
}
|
|
177
|
+
console.log('');
|
|
161
178
|
}
|
|
162
179
|
catch (err) {
|
|
163
|
-
console.error(`\n
|
|
164
|
-
console.error(` Error: ${err.message}`);
|
|
165
|
-
console.log(`\n Start it with: agentmesh start\n`);
|
|
180
|
+
console.error(`\n ${C.red}${ICON.fail} Gateway not reachable at ${BASE_URL()}${C.reset}`);
|
|
181
|
+
console.error(` ${C.dim}Error: ${err.message}${C.reset}`);
|
|
182
|
+
console.log(`\n Start it with: ${C.cyan}agentmesh start${C.reset}\n`);
|
|
166
183
|
}
|
|
167
184
|
}
|
|
168
185
|
async function cmdModels() {
|
|
169
186
|
try {
|
|
170
187
|
const data = await apiRequest('/v1/models');
|
|
171
|
-
console.log('\n 📋 Available Models:\n');
|
|
172
188
|
const byProvider = {};
|
|
173
189
|
for (const m of data.data || []) {
|
|
174
190
|
(byProvider[m.owned_by] ??= []).push(m.id);
|
|
175
191
|
}
|
|
192
|
+
const rows = [];
|
|
176
193
|
for (const [provider, models] of Object.entries(byProvider)) {
|
|
177
|
-
|
|
178
|
-
models.forEach(m => console.log(` - ${m}`));
|
|
179
|
-
console.log('');
|
|
194
|
+
rows.push([`${C.cyan}${provider}${C.reset}`, models.join(', ')]);
|
|
180
195
|
}
|
|
196
|
+
console.log('\n ' + table(['Provider', 'Models'], rows) + '\n');
|
|
181
197
|
}
|
|
182
198
|
catch (err) {
|
|
183
|
-
console.error(`\n
|
|
199
|
+
console.error(`\n ${C.red}${ICON.fail} ${err.message}${C.reset}\n`);
|
|
184
200
|
}
|
|
185
201
|
}
|
|
186
202
|
async function cmdQuota() {
|
|
187
203
|
try {
|
|
188
204
|
console.log('\n ⏳ Fetching quota data (may take ~15s)...');
|
|
189
|
-
const data = await apiRequest('/model-gateway/quota', { signal: AbortSignal.timeout(60_000) });
|
|
205
|
+
const data = await apiRequest('/v1/model-gateway/quota', { signal: AbortSignal.timeout(60_000) });
|
|
190
206
|
console.log('\n 📊 Provider Quota Status:\n');
|
|
191
207
|
if (!data || Object.keys(data).length === 0) {
|
|
192
208
|
console.log(' No quota data available. Is codexbar installed?\n');
|
|
@@ -204,27 +220,46 @@ async function cmdQuota() {
|
|
|
204
220
|
}
|
|
205
221
|
async function cmdAgents() {
|
|
206
222
|
try {
|
|
207
|
-
const data = await apiRequest('/agents');
|
|
208
|
-
|
|
209
|
-
|
|
223
|
+
const data = await apiRequest('/v1/agents');
|
|
224
|
+
const rows = data.map(a => [
|
|
225
|
+
a.status === 'online' ? `${C.green}●${C.reset}` : `${C.dim}○${C.reset}`,
|
|
226
|
+
a.id,
|
|
227
|
+
a.name,
|
|
228
|
+
a.status,
|
|
229
|
+
(a.capabilities || []).slice(0, 3).join(', '),
|
|
230
|
+
]);
|
|
231
|
+
console.log('\n ' + table(['', 'ID', 'Name', 'Status', 'Capabilities (top 3)'], rows) + '\n');
|
|
210
232
|
}
|
|
211
233
|
catch (err) {
|
|
212
|
-
console.error(`\n
|
|
234
|
+
console.error(`\n ${C.red}${ICON.fail} ${err.message}${C.reset}\n`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async function cmdCancel(taskId) {
|
|
238
|
+
try {
|
|
239
|
+
const data = await apiRequest(`/v1/tasks/${taskId}/cancel`, { method: 'POST' });
|
|
240
|
+
console.log(`\n ${C.green}${ICON.ok} Task ${data.task_id} cancelled${C.reset}\n`);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
console.error(`\n ${C.red}${ICON.fail} ${err.message}${C.reset}\n`);
|
|
213
244
|
}
|
|
214
245
|
}
|
|
215
246
|
async function cmdTasks() {
|
|
216
247
|
try {
|
|
217
|
-
const tasks = await apiRequest('/tasks');
|
|
218
|
-
console.log('\n 📋 Tasks:\n');
|
|
248
|
+
const tasks = await apiRequest('/v1/tasks');
|
|
219
249
|
if (!tasks.length) {
|
|
220
|
-
console.log(
|
|
250
|
+
console.log(`\n ${C.dim}(no tasks)${C.reset}\n`);
|
|
221
251
|
return;
|
|
222
252
|
}
|
|
223
|
-
tasks.
|
|
224
|
-
|
|
253
|
+
const rows = tasks.map(t => [
|
|
254
|
+
(STATUS_ICON[t.status] || ICON.dot) + ' ' + t.status,
|
|
255
|
+
t.id?.slice(0, 8) || '-',
|
|
256
|
+
String(t.assigned_agents?.length || 0),
|
|
257
|
+
new Date(t.created_at).toLocaleString(),
|
|
258
|
+
]);
|
|
259
|
+
console.log('\n ' + table(['Status', 'ID', 'Agents', 'Created'], rows) + '\n');
|
|
225
260
|
}
|
|
226
261
|
catch (err) {
|
|
227
|
-
console.error(`\n
|
|
262
|
+
console.error(`\n ${C.red}${ICON.fail} ${err.message}${C.reset}\n`);
|
|
228
263
|
}
|
|
229
264
|
}
|
|
230
265
|
async function cmdConfig(args) {
|
|
@@ -253,9 +288,9 @@ async function cmdConfig(args) {
|
|
|
253
288
|
async function cmdStatus() {
|
|
254
289
|
try {
|
|
255
290
|
const [health, models, stats] = await Promise.all([
|
|
256
|
-
apiRequest('/health'),
|
|
291
|
+
apiRequest('/v1/health'),
|
|
257
292
|
apiRequest('/v1/models').catch(() => ({ data: [] })),
|
|
258
|
-
apiRequest('/model-gateway/stats').catch(() => null),
|
|
293
|
+
apiRequest('/v1/model-gateway/stats').catch(() => null),
|
|
259
294
|
]);
|
|
260
295
|
console.log(`
|
|
261
296
|
╔═══════════════════════════════════════════════════╗
|
|
@@ -330,7 +365,7 @@ async function cmdDoctor() {
|
|
|
330
365
|
}
|
|
331
366
|
// Gateway status
|
|
332
367
|
try {
|
|
333
|
-
await apiRequest('/health');
|
|
368
|
+
await apiRequest('/v1/health');
|
|
334
369
|
console.log(` ✅ Gateway Running at ${BASE_URL()}`);
|
|
335
370
|
}
|
|
336
371
|
catch {
|
|
@@ -382,6 +417,13 @@ async function main() {
|
|
|
382
417
|
case 'tasks':
|
|
383
418
|
await cmdTasks();
|
|
384
419
|
break;
|
|
420
|
+
case 'cancel':
|
|
421
|
+
if (!rest[0]) {
|
|
422
|
+
console.error(`\n ${C.red}Usage: agentmesh cancel <task-id>${C.reset}\n`);
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
await cmdCancel(rest[0]);
|
|
426
|
+
break;
|
|
385
427
|
case 'config':
|
|
386
428
|
await cmdConfig(rest);
|
|
387
429
|
break;
|
|
@@ -434,6 +476,50 @@ async function main() {
|
|
|
434
476
|
}
|
|
435
477
|
break;
|
|
436
478
|
}
|
|
479
|
+
case 'release':
|
|
480
|
+
const { runRelease } = await import('./cli/release.js');
|
|
481
|
+
await runRelease(rest[0] || 'patch');
|
|
482
|
+
break;
|
|
483
|
+
case 'hermes':
|
|
484
|
+
if (rest[0] === 'setup') {
|
|
485
|
+
console.log(`
|
|
486
|
+
╔═══════════════════════════════════════════════════╗
|
|
487
|
+
║ Hermes ↔ Agent Mesh 双向通路设置 ║
|
|
488
|
+
╚═══════════════════════════════════════════════════╝
|
|
489
|
+
|
|
490
|
+
Hermes 网关已在运行(Discord + Weixin 已连接)。
|
|
491
|
+
现在只需添加一个 webhook 订阅,让 Hermes 能调用本网关。
|
|
492
|
+
|
|
493
|
+
方式 1: 手动订阅 (推荐)
|
|
494
|
+
hermes webhook subscribe \\
|
|
495
|
+
--name agentmesh \\
|
|
496
|
+
--url http://127.0.0.1:3000/hermes/task \\
|
|
497
|
+
--event message.received \\
|
|
498
|
+
--format '{"prompt":"{{message}}","model":"deepseek-chat"}'
|
|
499
|
+
|
|
500
|
+
方式 2: 从 Discord/Weixin 用 !task 命令触发
|
|
501
|
+
在 Hermes 的 skills 目录创建 agentmesh skill:
|
|
502
|
+
~/.hermes/skills/agentmesh.md
|
|
503
|
+
内容: "当用户发送 !task <描述> 时,POST 到 http://127.0.0.1:3000/hermes/task"
|
|
504
|
+
|
|
505
|
+
当前网关端点:
|
|
506
|
+
POST /hermes/task 提交任务 (手机 → 网关)
|
|
507
|
+
GET /hermes/task/:id 查询结果 (网关 → 手机)
|
|
508
|
+
GET /hermes/health Hermes 健康检查
|
|
509
|
+
|
|
510
|
+
使用流程:
|
|
511
|
+
📱 手机 Discord/Weixin 发消息
|
|
512
|
+
→ Hermes Gateway 接收
|
|
513
|
+
→ Webhook → POST :3000/hermes/task
|
|
514
|
+
→ Agent Mesh 执行
|
|
515
|
+
→ 结果返回 Hermes
|
|
516
|
+
→ 📱 手机收到回复
|
|
517
|
+
`);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
console.log('\n agentmesh hermes setup Hermes 双向通路设置指南\n');
|
|
521
|
+
}
|
|
522
|
+
break;
|
|
437
523
|
case 'doctor':
|
|
438
524
|
case 'check':
|
|
439
525
|
await cmdDoctor();
|
|
@@ -2,160 +2,7 @@ import { ProcessAdapter } from '../adapters/process.js';
|
|
|
2
2
|
import { ClaudeCodeAdapter } from '../adapters/claude-code.js';
|
|
3
3
|
import { OpenClawAdapter } from '../adapters/openclaw.js';
|
|
4
4
|
import { getAllAgentConfigs } from './config.js';
|
|
5
|
-
|
|
6
|
-
const DEFAULT_AGENT_CONFIGS = {
|
|
7
|
-
'claude-code': {
|
|
8
|
-
name: 'Claude Code',
|
|
9
|
-
capabilities: ['code-generation', 'code-review', 'debugging', 'refactoring', 'documentation', 'file-operations'],
|
|
10
|
-
command: 'claude',
|
|
11
|
-
args: ['-p']
|
|
12
|
-
},
|
|
13
|
-
'openclaw': {
|
|
14
|
-
name: 'OpenClaw',
|
|
15
|
-
capabilities: ['browser-automation', 'web-scraping', 'form-filling', 'ui-testing'],
|
|
16
|
-
command: 'openclaw',
|
|
17
|
-
args: ['--task']
|
|
18
|
-
},
|
|
19
|
-
'opencode': {
|
|
20
|
-
name: 'OpenCode',
|
|
21
|
-
capabilities: ['code-completion', 'code-generation', 'refactoring', 'debugging'],
|
|
22
|
-
command: 'opencode',
|
|
23
|
-
args: ['--task']
|
|
24
|
-
},
|
|
25
|
-
'gemini': {
|
|
26
|
-
name: 'Google Gemini CLI',
|
|
27
|
-
capabilities: ['code-generation', 'multimodal', 'reasoning', 'analysis'],
|
|
28
|
-
command: 'gemini',
|
|
29
|
-
args: ['--prompt']
|
|
30
|
-
},
|
|
31
|
-
'codex': {
|
|
32
|
-
name: 'OpenAI Codex',
|
|
33
|
-
capabilities: ['code-generation', 'code-explanation', 'refactoring'],
|
|
34
|
-
command: 'codex',
|
|
35
|
-
args: ['complete']
|
|
36
|
-
},
|
|
37
|
-
'github-copilot': {
|
|
38
|
-
name: 'GitHub Copilot',
|
|
39
|
-
capabilities: ['code-completion', 'code-suggestions', 'refactoring'],
|
|
40
|
-
command: 'copilot',
|
|
41
|
-
args: ['--ask']
|
|
42
|
-
},
|
|
43
|
-
'qwen-code': {
|
|
44
|
-
name: 'Qwen Code',
|
|
45
|
-
capabilities: ['code-generation', 'code-review', 'multilingual'],
|
|
46
|
-
command: 'qwen-code',
|
|
47
|
-
args: ['--task']
|
|
48
|
-
},
|
|
49
|
-
'crush': {
|
|
50
|
-
name: 'CRUSH AI',
|
|
51
|
-
capabilities: ['code-generation', 'debugging', 'security-analysis'],
|
|
52
|
-
command: 'crush',
|
|
53
|
-
args: ['run']
|
|
54
|
-
},
|
|
55
|
-
'droid': {
|
|
56
|
-
name: 'Droid Agent',
|
|
57
|
-
capabilities: ['android-development', 'mobile-debugging', 'device-control'],
|
|
58
|
-
command: 'droid',
|
|
59
|
-
args: ['--task']
|
|
60
|
-
},
|
|
61
|
-
'factory': {
|
|
62
|
-
name: 'Factory AI',
|
|
63
|
-
capabilities: ['code-generation', 'testing', 'documentation', 'refactoring'],
|
|
64
|
-
command: 'factory',
|
|
65
|
-
args: ['--task']
|
|
66
|
-
},
|
|
67
|
-
'cursor': {
|
|
68
|
-
name: 'Cursor',
|
|
69
|
-
capabilities: ['code-completion', 'code-generation', 'refactoring', 'chat'],
|
|
70
|
-
command: 'cursor',
|
|
71
|
-
args: ['--task']
|
|
72
|
-
},
|
|
73
|
-
'windsurf': {
|
|
74
|
-
name: 'Windsurf',
|
|
75
|
-
capabilities: ['code-generation', 'agentic-coding', 'flow-state'],
|
|
76
|
-
command: 'windsurf',
|
|
77
|
-
args: ['--task']
|
|
78
|
-
},
|
|
79
|
-
'zed': {
|
|
80
|
-
name: 'Zed AI',
|
|
81
|
-
capabilities: ['code-generation', 'collaboration', 'high-performance'],
|
|
82
|
-
command: 'zed',
|
|
83
|
-
args: ['--ai-task']
|
|
84
|
-
},
|
|
85
|
-
'aider': {
|
|
86
|
-
name: 'Aider',
|
|
87
|
-
capabilities: ['git-based-editing', 'code-refactoring', 'multi-file-changes'],
|
|
88
|
-
command: 'aider',
|
|
89
|
-
args: ['--message']
|
|
90
|
-
},
|
|
91
|
-
'cline': {
|
|
92
|
-
name: 'Cline',
|
|
93
|
-
capabilities: ['autonomous-coding', 'file-operations', 'command-execution'],
|
|
94
|
-
command: 'cline',
|
|
95
|
-
args: ['--task']
|
|
96
|
-
},
|
|
97
|
-
'roo-code': {
|
|
98
|
-
name: 'Roo Code',
|
|
99
|
-
capabilities: ['code-generation', 'agentic-mode', 'workspace-awareness'],
|
|
100
|
-
command: 'roo-code',
|
|
101
|
-
args: ['--task']
|
|
102
|
-
},
|
|
103
|
-
// 2026 新增 Agent
|
|
104
|
-
'perplexity': {
|
|
105
|
-
name: 'Perplexity',
|
|
106
|
-
capabilities: ['research', 'web-search', 'fact-checking', 'analysis'],
|
|
107
|
-
command: 'perplexity',
|
|
108
|
-
args: ['--query']
|
|
109
|
-
},
|
|
110
|
-
'grok': {
|
|
111
|
-
name: 'xAI Grok',
|
|
112
|
-
capabilities: ['reasoning', 'humor', 'code-generation', 'analysis'],
|
|
113
|
-
command: 'grok',
|
|
114
|
-
args: ['--prompt']
|
|
115
|
-
},
|
|
116
|
-
'phind': {
|
|
117
|
-
name: 'Phind',
|
|
118
|
-
capabilities: ['developer-search', 'code-search', 'documentation-search'],
|
|
119
|
-
command: 'phind',
|
|
120
|
-
args: ['--search']
|
|
121
|
-
},
|
|
122
|
-
'you': {
|
|
123
|
-
name: 'You.com AI',
|
|
124
|
-
capabilities: ['web-search', 'code-search', 'general-assistant'],
|
|
125
|
-
command: 'you',
|
|
126
|
-
args: ['--query']
|
|
127
|
-
},
|
|
128
|
-
'lepton': {
|
|
129
|
-
name: 'Lepton AI',
|
|
130
|
-
capabilities: ['code-generation', 'conversation', 'analysis'],
|
|
131
|
-
command: 'lepton',
|
|
132
|
-
args: ['--prompt']
|
|
133
|
-
},
|
|
134
|
-
'ollama': {
|
|
135
|
-
name: 'Ollama',
|
|
136
|
-
capabilities: ['local-llm', 'code-generation', 'privacy-focused'],
|
|
137
|
-
command: 'ollama',
|
|
138
|
-
args: ['run']
|
|
139
|
-
},
|
|
140
|
-
'llama': {
|
|
141
|
-
name: 'Meta Llama',
|
|
142
|
-
capabilities: ['code-generation', 'reasoning', 'open-source'],
|
|
143
|
-
command: 'llama',
|
|
144
|
-
args: ['--prompt']
|
|
145
|
-
},
|
|
146
|
-
'mistral': {
|
|
147
|
-
name: 'Mistral AI',
|
|
148
|
-
capabilities: ['code-generation', 'reasoning', 'multilingual'],
|
|
149
|
-
command: 'mistral',
|
|
150
|
-
args: ['--task']
|
|
151
|
-
},
|
|
152
|
-
'anthropic': {
|
|
153
|
-
name: 'Anthropic CLI',
|
|
154
|
-
capabilities: ['conversation', 'reasoning', 'code-generation'],
|
|
155
|
-
command: 'anthropic',
|
|
156
|
-
args: ['--prompt']
|
|
157
|
-
}
|
|
158
|
-
};
|
|
5
|
+
import { DEFAULT_AGENT_CONFIGS } from './agents.default.js';
|
|
159
6
|
export class AgentRegistry {
|
|
160
7
|
adapters = new Map();
|
|
161
8
|
initialized = false;
|
|
@@ -211,6 +58,17 @@ export class AgentRegistry {
|
|
|
211
58
|
console.log(`[AgentRegistry] Registered default: ${id}`);
|
|
212
59
|
}
|
|
213
60
|
}
|
|
61
|
+
/** 热重载:清空后重新从配置加载所有适配器 */
|
|
62
|
+
reload() {
|
|
63
|
+
// 保留内置适配器(ClaudeCode, OpenClaw),清除其余
|
|
64
|
+
const preserved = new Set(['claude-code', 'openclaw']);
|
|
65
|
+
for (const key of this.adapters.keys()) {
|
|
66
|
+
if (!preserved.has(key))
|
|
67
|
+
this.adapters.delete(key);
|
|
68
|
+
}
|
|
69
|
+
this.initialized = false;
|
|
70
|
+
this.initialize();
|
|
71
|
+
}
|
|
214
72
|
/**
|
|
215
73
|
* 注册自定义适配器
|
|
216
74
|
*/
|