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.
Files changed (66) hide show
  1. package/README.ar.md +506 -31
  2. package/README.md +574 -47
  3. package/bin/agent-runner.js +10 -1
  4. package/package.json +12 -4
  5. package/public/agent-workspace.html +347 -0
  6. package/public/browser.html +484 -0
  7. package/public/commander-dashboard.html +243 -0
  8. package/public/css/agent-workspace.css +1713 -0
  9. package/public/css/premium.css +317 -317
  10. package/public/demo.html +259 -259
  11. package/public/index.html +738 -644
  12. package/public/js/agent-workspace.js +1740 -0
  13. package/public/mesh-dashboard.html +309 -382
  14. package/public/premium-dashboard.html +2487 -2487
  15. package/public/premium.html +791 -791
  16. package/public/script/wab.min.js +124 -87
  17. package/script/ai-agent-bridge.js +154 -84
  18. package/sdk/agent-mesh.js +287 -171
  19. package/sdk/commander.js +262 -0
  20. package/sdk/index.d.ts +83 -0
  21. package/sdk/index.js +374 -260
  22. package/sdk/package.json +1 -1
  23. package/server/config/secrets.js +13 -5
  24. package/server/index.js +191 -5
  25. package/server/middleware/adminAuth.js +6 -1
  26. package/server/middleware/auth.js +11 -2
  27. package/server/middleware/rateLimits.js +78 -2
  28. package/server/migrations/002_premium_features.sql +418 -418
  29. package/server/migrations/003_ads_integer_cents.sql +33 -0
  30. package/server/models/db.js +121 -1
  31. package/server/routes/admin-premium.js +671 -671
  32. package/server/routes/admin.js +16 -2
  33. package/server/routes/ads.js +130 -0
  34. package/server/routes/agent-workspace.js +378 -0
  35. package/server/routes/api.js +21 -2
  36. package/server/routes/auth.js +26 -6
  37. package/server/routes/commander.js +316 -0
  38. package/server/routes/mesh.js +370 -201
  39. package/server/routes/premium-v2.js +686 -686
  40. package/server/routes/premium.js +724 -724
  41. package/server/routes/sovereign.js +78 -0
  42. package/server/routes/universal.js +177 -0
  43. package/server/routes/wab-api.js +20 -5
  44. package/server/services/agent-chat.js +506 -0
  45. package/server/services/agent-learning.js +230 -77
  46. package/server/services/agent-memory.js +625 -625
  47. package/server/services/agent-mesh.js +260 -67
  48. package/server/services/agent-symphony.js +553 -517
  49. package/server/services/agent-tasks.js +1807 -0
  50. package/server/services/commander.js +738 -0
  51. package/server/services/edge-compute.js +440 -0
  52. package/server/services/fairness-engine.js +409 -0
  53. package/server/services/local-ai.js +389 -0
  54. package/server/services/plugins.js +771 -747
  55. package/server/services/price-intelligence.js +565 -0
  56. package/server/services/price-shield.js +1137 -0
  57. package/server/services/search-engine.js +357 -0
  58. package/server/services/security.js +513 -0
  59. package/server/services/self-healing.js +843 -843
  60. package/server/services/swarm.js +788 -788
  61. package/server/services/universal-scraper.js +661 -0
  62. package/server/services/vision.js +871 -871
  63. package/server/ws.js +61 -1
  64. package/public/admin/dashboard.html +0 -848
  65. package/public/admin/login.html +0 -84
  66. 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;