web-agent-bridge 2.3.0 → 2.4.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/README.ar.md +506 -31
- package/README.md +574 -47
- package/bin/agent-runner.js +10 -1
- package/package.json +12 -4
- package/public/agent-workspace.html +347 -0
- package/public/browser.html +484 -0
- package/public/commander-dashboard.html +243 -0
- package/public/css/agent-workspace.css +1713 -0
- package/public/css/premium.css +317 -317
- package/public/demo.html +259 -259
- package/public/index.html +738 -644
- package/public/js/agent-workspace.js +1740 -0
- package/public/mesh-dashboard.html +309 -382
- package/public/premium-dashboard.html +2487 -2487
- package/public/premium.html +791 -791
- package/public/script/wab.min.js +124 -87
- package/script/ai-agent-bridge.js +154 -84
- package/sdk/agent-mesh.js +287 -171
- package/sdk/commander.js +262 -0
- package/sdk/index.d.ts +83 -0
- package/sdk/index.js +374 -260
- package/sdk/package.json +1 -1
- package/server/config/secrets.js +13 -5
- package/server/index.js +191 -5
- package/server/middleware/adminAuth.js +6 -1
- package/server/middleware/auth.js +11 -2
- package/server/middleware/rateLimits.js +78 -2
- package/server/migrations/002_premium_features.sql +418 -418
- package/server/migrations/003_ads_integer_cents.sql +33 -0
- package/server/models/db.js +121 -1
- package/server/routes/admin-premium.js +671 -671
- package/server/routes/admin.js +16 -2
- package/server/routes/ads.js +130 -0
- package/server/routes/agent-workspace.js +378 -0
- package/server/routes/api.js +21 -2
- package/server/routes/auth.js +26 -6
- package/server/routes/commander.js +316 -0
- package/server/routes/mesh.js +370 -201
- package/server/routes/premium-v2.js +686 -686
- package/server/routes/premium.js +724 -724
- package/server/routes/sovereign.js +78 -0
- package/server/routes/universal.js +177 -0
- package/server/routes/wab-api.js +20 -5
- package/server/services/agent-chat.js +506 -0
- package/server/services/agent-learning.js +230 -77
- package/server/services/agent-memory.js +625 -625
- package/server/services/agent-mesh.js +260 -67
- package/server/services/agent-symphony.js +553 -517
- package/server/services/agent-tasks.js +1807 -0
- package/server/services/commander.js +738 -0
- package/server/services/edge-compute.js +440 -0
- package/server/services/fairness-engine.js +409 -0
- package/server/services/local-ai.js +389 -0
- package/server/services/plugins.js +771 -747
- package/server/services/price-intelligence.js +565 -0
- package/server/services/price-shield.js +1137 -0
- package/server/services/search-engine.js +357 -0
- package/server/services/security.js +513 -0
- package/server/services/self-healing.js +843 -843
- package/server/services/swarm.js +788 -788
- package/server/services/universal-scraper.js +661 -0
- package/server/services/vision.js +871 -871
- package/server/ws.js +61 -1
- package/public/admin/dashboard.html +0 -848
- package/public/admin/login.html +0 -84
- package/public/video/tutorial.mp4 +0 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Commander Routes — REST API for the Commander Agent System
|
|
3
|
+
*
|
|
4
|
+
* Exposes commander, edge computing, and local AI services through
|
|
5
|
+
* RESTful endpoints. All routes are site-scoped.
|
|
6
|
+
*
|
|
7
|
+
* Sections:
|
|
8
|
+
* /missions — Mission lifecycle (create, launch, list, get)
|
|
9
|
+
* /agents — Commander agent registry
|
|
10
|
+
* /edge — Edge computing node management
|
|
11
|
+
* /local-ai — Local model discovery and inference
|
|
12
|
+
* /stats — Unified statistics
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const express = require('express');
|
|
16
|
+
const router = express.Router();
|
|
17
|
+
|
|
18
|
+
const commander = require('../services/commander');
|
|
19
|
+
const edge = require('../services/edge-compute');
|
|
20
|
+
const localAI = require('../services/local-ai');
|
|
21
|
+
|
|
22
|
+
// ─── Helpers ─────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
function ok(res, data) { res.json({ ok: true, ...data }); }
|
|
25
|
+
function fail(res, status, message) { res.status(status).json({ ok: false, error: message }); }
|
|
26
|
+
|
|
27
|
+
function requireBody(req, res, ...fields) {
|
|
28
|
+
for (const f of fields) {
|
|
29
|
+
if (req.body[f] === undefined || req.body[f] === null) {
|
|
30
|
+
fail(res, 400, `Missing required field: ${f}`);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
38
|
+
// MISSIONS — Task Decomposition & Orchestration
|
|
39
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
40
|
+
|
|
41
|
+
// Launch a full mission (create + execute)
|
|
42
|
+
router.post('/missions/launch', async (req, res) => {
|
|
43
|
+
try {
|
|
44
|
+
if (!requireBody(req, res, 'goal')) return;
|
|
45
|
+
const { siteId, goal, title, strategy, priority, context } = req.body;
|
|
46
|
+
const result = await commander.launchMission(siteId || 'default', title || goal.substring(0, 80), goal, {
|
|
47
|
+
strategy, priority, context,
|
|
48
|
+
});
|
|
49
|
+
ok(res, { mission: result });
|
|
50
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Create a mission (plan only, no execution)
|
|
54
|
+
router.post('/missions', (req, res) => {
|
|
55
|
+
try {
|
|
56
|
+
if (!requireBody(req, res, 'goal')) return;
|
|
57
|
+
const { siteId, goal, title, strategy, priority, context } = req.body;
|
|
58
|
+
const mission = commander.createMission(siteId || 'default', title || goal.substring(0, 80), goal, {
|
|
59
|
+
strategy, priority, context,
|
|
60
|
+
});
|
|
61
|
+
ok(res, { mission });
|
|
62
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Execute an existing mission
|
|
66
|
+
router.post('/missions/:id/execute', async (req, res) => {
|
|
67
|
+
try {
|
|
68
|
+
const result = await commander.executeMission(req.params.id);
|
|
69
|
+
ok(res, { mission: result });
|
|
70
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Get a single mission
|
|
74
|
+
router.get('/missions/:id', (req, res) => {
|
|
75
|
+
try {
|
|
76
|
+
const mission = commander.getMission(req.params.id);
|
|
77
|
+
if (!mission) return fail(res, 404, 'Mission not found');
|
|
78
|
+
ok(res, { mission });
|
|
79
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Get mission tasks
|
|
83
|
+
router.get('/missions/:id/tasks', (req, res) => {
|
|
84
|
+
try {
|
|
85
|
+
const tasks = commander.getMissionTasks(req.params.id);
|
|
86
|
+
ok(res, { tasks });
|
|
87
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// List missions
|
|
91
|
+
router.get('/missions', (req, res) => {
|
|
92
|
+
try {
|
|
93
|
+
const siteId = req.query.siteId || 'default';
|
|
94
|
+
const missions = req.query.active === 'true'
|
|
95
|
+
? commander.getActiveMissions(siteId)
|
|
96
|
+
: commander.getMissions(siteId, parseInt(req.query.limit) || 50);
|
|
97
|
+
ok(res, { missions });
|
|
98
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Get decomposition strategies
|
|
102
|
+
router.get('/strategies', (req, res) => {
|
|
103
|
+
try {
|
|
104
|
+
ok(res, { strategies: commander.getStrategies() });
|
|
105
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
109
|
+
// AGENTS — Commander Agent Registry
|
|
110
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
111
|
+
|
|
112
|
+
router.post('/agents', (req, res) => {
|
|
113
|
+
try {
|
|
114
|
+
if (!requireBody(req, res, 'agentType')) return;
|
|
115
|
+
const { siteId, agentType, displayName, capabilities, modelInfo, hardware } = req.body;
|
|
116
|
+
const agent = commander.registerAgent(siteId || 'default', agentType, displayName, capabilities, modelInfo, hardware);
|
|
117
|
+
ok(res, { agent });
|
|
118
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
router.get('/agents', (req, res) => {
|
|
122
|
+
try {
|
|
123
|
+
const siteId = req.query.siteId || 'default';
|
|
124
|
+
const agents = req.query.capability
|
|
125
|
+
? commander.getAgentsByCapability(siteId, req.query.capability)
|
|
126
|
+
: commander.getAgents(siteId);
|
|
127
|
+
ok(res, { agents });
|
|
128
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
router.post('/agents/:id/heartbeat', (req, res) => {
|
|
132
|
+
try {
|
|
133
|
+
commander.agentHeartbeat(req.params.id);
|
|
134
|
+
ok(res, { alive: true });
|
|
135
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
139
|
+
// EDGE — Distributed Computing Nodes
|
|
140
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
141
|
+
|
|
142
|
+
// Register an edge node
|
|
143
|
+
router.post('/edge/nodes', (req, res) => {
|
|
144
|
+
try {
|
|
145
|
+
if (!requireBody(req, res, 'hostname')) return;
|
|
146
|
+
const { siteId, hostname, hardware, capabilities } = req.body;
|
|
147
|
+
const node = edge.registerNode(siteId || 'default', hostname, hardware, capabilities);
|
|
148
|
+
ok(res, { node });
|
|
149
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// List edge nodes
|
|
153
|
+
router.get('/edge/nodes', (req, res) => {
|
|
154
|
+
try {
|
|
155
|
+
const siteId = req.query.siteId || 'default';
|
|
156
|
+
const nodes = req.query.available === 'true'
|
|
157
|
+
? edge.getAvailableNodes(siteId)
|
|
158
|
+
: edge.getNodes(siteId);
|
|
159
|
+
ok(res, { nodes });
|
|
160
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Node heartbeat
|
|
164
|
+
router.post('/edge/nodes/:id/heartbeat', (req, res) => {
|
|
165
|
+
try {
|
|
166
|
+
edge.nodeHeartbeat(req.params.id, req.body.currentLoad || 0);
|
|
167
|
+
ok(res, { alive: true });
|
|
168
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Remove node
|
|
172
|
+
router.delete('/edge/nodes/:id', (req, res) => {
|
|
173
|
+
try {
|
|
174
|
+
edge.removeNode(req.params.id);
|
|
175
|
+
ok(res, { removed: req.params.id });
|
|
176
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Submit a task for edge execution
|
|
180
|
+
router.post('/edge/tasks', (req, res) => {
|
|
181
|
+
try {
|
|
182
|
+
if (!requireBody(req, res, 'taskType', 'payload')) return;
|
|
183
|
+
const { taskType, payload, priority, missionId, encrypt, encryptionKey } = req.body;
|
|
184
|
+
const task = edge.submitTask(taskType, payload, { priority, missionId, encrypt, encryptionKey });
|
|
185
|
+
ok(res, { task });
|
|
186
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Distribute queued tasks to available nodes
|
|
190
|
+
router.post('/edge/distribute', (req, res) => {
|
|
191
|
+
try {
|
|
192
|
+
const siteId = req.body.siteId || 'default';
|
|
193
|
+
const result = edge.distributeTask(siteId);
|
|
194
|
+
ok(res, result);
|
|
195
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Complete a task (called by the executing node)
|
|
199
|
+
router.post('/edge/tasks/:id/complete', (req, res) => {
|
|
200
|
+
try {
|
|
201
|
+
const { result, success } = req.body;
|
|
202
|
+
const outcome = edge.completeTask(req.params.id, result, success !== false);
|
|
203
|
+
ok(res, outcome);
|
|
204
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Get tasks for a specific node
|
|
208
|
+
router.get('/edge/tasks', (req, res) => {
|
|
209
|
+
try {
|
|
210
|
+
if (req.query.nodeId) {
|
|
211
|
+
ok(res, { tasks: edge.getNodeTasks(req.query.nodeId) });
|
|
212
|
+
} else if (req.query.missionId) {
|
|
213
|
+
const task = edge.getTask(req.query.missionId);
|
|
214
|
+
ok(res, { tasks: task ? [task] : [] });
|
|
215
|
+
} else {
|
|
216
|
+
fail(res, 400, 'Provide nodeId or missionId query param');
|
|
217
|
+
}
|
|
218
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Get edge swarms
|
|
222
|
+
router.get('/edge/swarms', (req, res) => {
|
|
223
|
+
try {
|
|
224
|
+
const siteId = req.query.siteId || 'default';
|
|
225
|
+
const swarms = req.query.capability
|
|
226
|
+
? [edge.getSwarmByCapability(siteId, req.query.capability)].filter(Boolean)
|
|
227
|
+
: edge.getSwarms(siteId);
|
|
228
|
+
ok(res, { swarms });
|
|
229
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Edge stats
|
|
233
|
+
router.get('/edge/stats', (req, res) => {
|
|
234
|
+
try {
|
|
235
|
+
ok(res, edge.getStats(req.query.siteId || 'default'));
|
|
236
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
240
|
+
// LOCAL AI — Sovereign Model Management
|
|
241
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
242
|
+
|
|
243
|
+
// Discover local models (probe Ollama, llama.cpp, etc.)
|
|
244
|
+
router.post('/local-ai/discover', async (req, res) => {
|
|
245
|
+
try {
|
|
246
|
+
const siteId = req.body.siteId || 'default';
|
|
247
|
+
const result = await localAI.discoverModels(siteId, req.body.customEndpoints);
|
|
248
|
+
ok(res, result);
|
|
249
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Register a model manually
|
|
253
|
+
router.post('/local-ai/models', (req, res) => {
|
|
254
|
+
try {
|
|
255
|
+
if (!requireBody(req, res, 'provider', 'modelName', 'endpoint')) return;
|
|
256
|
+
const { siteId, provider, modelName, endpoint, capabilities, contextWindow } = req.body;
|
|
257
|
+
const model = localAI.registerModel(siteId || 'default', provider, modelName, endpoint, capabilities, contextWindow);
|
|
258
|
+
ok(res, { model });
|
|
259
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Run inference
|
|
263
|
+
router.post('/local-ai/infer', async (req, res) => {
|
|
264
|
+
try {
|
|
265
|
+
if (!requireBody(req, res, 'prompt')) return;
|
|
266
|
+
const { siteId, prompt, capability, modelId, systemPrompt, temperature, maxTokens } = req.body;
|
|
267
|
+
const result = await localAI.infer(siteId || 'default', prompt, {
|
|
268
|
+
capability, modelId, systemPrompt, temperature, maxTokens,
|
|
269
|
+
});
|
|
270
|
+
ok(res, { result });
|
|
271
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// List models
|
|
275
|
+
router.get('/local-ai/models', (req, res) => {
|
|
276
|
+
try {
|
|
277
|
+
const siteId = req.query.siteId || 'default';
|
|
278
|
+
const models = req.query.available === 'true'
|
|
279
|
+
? localAI.getAvailableModels(siteId)
|
|
280
|
+
: localAI.getModels(siteId);
|
|
281
|
+
ok(res, { models });
|
|
282
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Update model status
|
|
286
|
+
router.patch('/local-ai/models/:id', (req, res) => {
|
|
287
|
+
try {
|
|
288
|
+
if (!requireBody(req, res, 'status')) return;
|
|
289
|
+
localAI.updateModelStatus(req.params.id, req.body.status);
|
|
290
|
+
ok(res, { updated: req.params.id });
|
|
291
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Local AI stats
|
|
295
|
+
router.get('/local-ai/stats', (req, res) => {
|
|
296
|
+
try {
|
|
297
|
+
ok(res, localAI.getStats(req.query.siteId || 'default'));
|
|
298
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
302
|
+
// UNIFIED STATS
|
|
303
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
304
|
+
|
|
305
|
+
router.get('/stats', (req, res) => {
|
|
306
|
+
try {
|
|
307
|
+
const siteId = req.query.siteId || 'default';
|
|
308
|
+
ok(res, {
|
|
309
|
+
commander: commander.getStats(siteId),
|
|
310
|
+
edge: edge.getStats(siteId),
|
|
311
|
+
localAI: localAI.getStats(siteId),
|
|
312
|
+
});
|
|
313
|
+
} catch (e) { fail(res, 500, e.message); }
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
module.exports = router;
|