web-agent-bridge 2.2.0 → 2.3.1
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 +7 -0
- package/README.md +7 -0
- package/package.json +12 -4
- package/public/commander-dashboard.html +243 -0
- package/public/css/premium.css +317 -317
- package/public/demo.html +259 -259
- package/public/index.html +644 -592
- package/public/llms.txt +1 -0
- package/public/mesh-dashboard.html +328 -0
- package/public/premium-dashboard.html +2487 -2487
- package/public/premium.html +791 -791
- package/public/script/wab.min.js +181 -6
- package/script/ai-agent-bridge.js +196 -0
- package/sdk/agent-mesh.js +449 -0
- package/sdk/commander.js +262 -0
- package/sdk/index.js +260 -259
- package/sdk/package.json +1 -1
- package/server/index.js +13 -1
- package/server/migrations/002_premium_features.sql +418 -418
- package/server/models/db.js +24 -5
- package/server/routes/admin-premium.js +671 -671
- package/server/routes/commander.js +316 -0
- package/server/routes/mesh.js +469 -0
- package/server/routes/premium-v2.js +686 -686
- package/server/routes/premium.js +724 -724
- package/server/services/agent-learning.js +575 -0
- package/server/services/agent-memory.js +625 -625
- package/server/services/agent-mesh.js +539 -0
- package/server/services/agent-symphony.js +711 -0
- package/server/services/commander.js +738 -0
- package/server/services/edge-compute.js +440 -0
- package/server/services/local-ai.js +389 -0
- package/server/services/plugins.js +747 -747
- package/server/services/self-healing.js +843 -843
- package/server/services/swarm.js +788 -788
- package/server/services/vision.js +871 -871
- package/public/admin/dashboard.html +0 -848
- package/public/admin/login.html +0 -84
- package/public/video/tutorial.mp4 +0 -0
package/public/script/wab.min.js
CHANGED
|
@@ -356,6 +356,164 @@
|
|
|
356
356
|
}).then(function(r) { return r.json(); });
|
|
357
357
|
};
|
|
358
358
|
|
|
359
|
+
// ── Agent Mesh Protocol ───────────────────────────────────────────
|
|
360
|
+
|
|
361
|
+
function _meshReq(url, opts) {
|
|
362
|
+
return fetch(url, opts).then(function(r) {
|
|
363
|
+
if (!r.ok) return r.json().catch(function() { return {}; }).then(function(e) { return Promise.reject(new Error(e.error || r.statusText)); });
|
|
364
|
+
return r.json();
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
WABInstance.prototype.meshJoin = function(role, displayName, capabilities) {
|
|
369
|
+
if (!this.serverUrl) return Promise.reject(new Error('Mesh requires a server URL'));
|
|
370
|
+
var self = this;
|
|
371
|
+
return _meshReq(this.serverUrl + '/api/mesh/agents', {
|
|
372
|
+
method: 'POST',
|
|
373
|
+
headers: { 'Content-Type': 'application/json' },
|
|
374
|
+
body: JSON.stringify({ siteId: this.name, role: role, displayName: displayName, capabilities: capabilities })
|
|
375
|
+
}).then(function(data) {
|
|
376
|
+
self._meshAgentId = data.agent.id;
|
|
377
|
+
self._meshHeartbeat = setInterval(function() {
|
|
378
|
+
_meshReq(self.serverUrl + '/api/mesh/agents/' + self._meshAgentId + '/heartbeat', { method: 'POST' }).catch(function() {});
|
|
379
|
+
}, 30000);
|
|
380
|
+
self._emit('mesh:joined', data.agent);
|
|
381
|
+
return data.agent;
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
WABInstance.prototype.meshLeave = function() {
|
|
386
|
+
if (this._meshHeartbeat) { clearInterval(this._meshHeartbeat); this._meshHeartbeat = null; }
|
|
387
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.resolve();
|
|
388
|
+
var self = this;
|
|
389
|
+
return _meshReq(this.serverUrl + '/api/mesh/agents/' + this._meshAgentId, { method: 'DELETE' })
|
|
390
|
+
.catch(function() {}).then(function() { self._meshAgentId = null; });
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
WABInstance.prototype.meshPublish = function(channel, messageType, subject, payload, opts) {
|
|
394
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
395
|
+
return _meshReq(this.serverUrl + '/api/mesh/messages', {
|
|
396
|
+
method: 'POST',
|
|
397
|
+
headers: { 'Content-Type': 'application/json' },
|
|
398
|
+
body: JSON.stringify({ channelName: channel || 'general', senderId: this._meshAgentId, targetId: (opts || {}).targetId, type: messageType, subject: subject, payload: payload, priority: (opts || {}).priority, ttl: (opts || {}).ttl })
|
|
399
|
+
}).then(function(d) { return d.message; });
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
WABInstance.prototype.meshReceive = function(limit) {
|
|
403
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
404
|
+
return _meshReq(this.serverUrl + '/api/mesh/messages?agentId=' + this._meshAgentId + '&limit=' + (limit || 50))
|
|
405
|
+
.then(function(d) { return d.messages; });
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
WABInstance.prototype.meshAcknowledge = function(messageId) {
|
|
409
|
+
if (!this.serverUrl) return Promise.reject(new Error('Requires server URL'));
|
|
410
|
+
return _meshReq(this.serverUrl + '/api/mesh/messages/' + encodeURIComponent(messageId) + '/acknowledge', { method: 'POST' });
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
WABInstance.prototype.meshUnread = function() {
|
|
414
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
415
|
+
return _meshReq(this.serverUrl + '/api/mesh/agents/' + this._meshAgentId + '/unread');
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
WABInstance.prototype.meshShareKnowledge = function(type, key, value, opts) {
|
|
419
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
420
|
+
opts = opts || {};
|
|
421
|
+
return _meshReq(this.serverUrl + '/api/mesh/knowledge', {
|
|
422
|
+
method: 'POST',
|
|
423
|
+
headers: { 'Content-Type': 'application/json' },
|
|
424
|
+
body: JSON.stringify({ agentId: this._meshAgentId, type: type, domain: opts.domain, key: key, value: value, confidence: opts.confidence, source: opts.source })
|
|
425
|
+
}).then(function(d) { return d.knowledge; });
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
WABInstance.prototype.meshQueryKnowledge = function(params) {
|
|
429
|
+
if (!this.serverUrl) return Promise.reject(new Error('Requires server URL'));
|
|
430
|
+
var qs = Object.keys(params || {}).map(function(k) { return k + '=' + encodeURIComponent(params[k]); }).join('&');
|
|
431
|
+
return _meshReq(this.serverUrl + '/api/mesh/knowledge?' + qs).then(function(d) { return d.knowledge; });
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
WABInstance.prototype.meshSearchKnowledge = function(query, limit) {
|
|
435
|
+
if (!this.serverUrl) return Promise.reject(new Error('Requires server URL'));
|
|
436
|
+
return _meshReq(this.serverUrl + '/api/mesh/knowledge/search/' + encodeURIComponent(query) + '?limit=' + (limit || 20))
|
|
437
|
+
.then(function(d) { return d.knowledge; });
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
WABInstance.prototype.meshAlert = function(subject, details, priority) {
|
|
441
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
442
|
+
return _meshReq(this.serverUrl + '/api/mesh/alert', {
|
|
443
|
+
method: 'POST',
|
|
444
|
+
headers: { 'Content-Type': 'application/json' },
|
|
445
|
+
body: JSON.stringify({ senderId: this._meshAgentId, subject: subject, details: details, priority: priority })
|
|
446
|
+
}).then(function(d) { return d.message; });
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
WABInstance.prototype.meshCreateVote = function(subject, options, deadlineSeconds) {
|
|
450
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
451
|
+
return _meshReq(this.serverUrl + '/api/mesh/votes', {
|
|
452
|
+
method: 'POST',
|
|
453
|
+
headers: { 'Content-Type': 'application/json' },
|
|
454
|
+
body: JSON.stringify({ senderId: this._meshAgentId, subject: subject, options: options, deadlineSeconds: deadlineSeconds })
|
|
455
|
+
}).then(function(d) { return d.vote; });
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
WABInstance.prototype.meshCastVote = function(voteMessageId, choice, weight, reason) {
|
|
459
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
460
|
+
return _meshReq(this.serverUrl + '/api/mesh/votes/' + encodeURIComponent(voteMessageId) + '/cast', {
|
|
461
|
+
method: 'POST',
|
|
462
|
+
headers: { 'Content-Type': 'application/json' },
|
|
463
|
+
body: JSON.stringify({ voterId: this._meshAgentId, choice: choice, weight: weight, reason: reason })
|
|
464
|
+
}).then(function(d) { return d.result; });
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
WABInstance.prototype.meshTallyVote = function(voteMessageId) {
|
|
468
|
+
if (!this.serverUrl) return Promise.reject(new Error('Requires server URL'));
|
|
469
|
+
return _meshReq(this.serverUrl + '/api/mesh/votes/' + encodeURIComponent(voteMessageId) + '/tally')
|
|
470
|
+
.then(function(d) { return d.tally; });
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// ── Agent Symphony Orchestrator ───────────────────────────────────
|
|
474
|
+
|
|
475
|
+
WABInstance.prototype.symphonyPerform = function(template, inputData, schema) {
|
|
476
|
+
if (!this.serverUrl) return Promise.reject(new Error('Symphony requires a server URL'));
|
|
477
|
+
var self = this;
|
|
478
|
+
return _meshReq(this.serverUrl + '/api/mesh/symphony/compose', {
|
|
479
|
+
method: 'POST',
|
|
480
|
+
headers: { 'Content-Type': 'application/json' },
|
|
481
|
+
body: JSON.stringify({ siteId: this.name, template: template, inputData: inputData, schema: schema })
|
|
482
|
+
}).then(function(data) {
|
|
483
|
+
self._emit('symphony:completed', data);
|
|
484
|
+
return data;
|
|
485
|
+
});
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// ── Agent Learning Engine ─────────────────────────────────────────
|
|
489
|
+
|
|
490
|
+
WABInstance.prototype.learnRecord = function(domain, action, context, features) {
|
|
491
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
492
|
+
return _meshReq(this.serverUrl + '/api/mesh/learning/decisions', {
|
|
493
|
+
method: 'POST',
|
|
494
|
+
headers: { 'Content-Type': 'application/json' },
|
|
495
|
+
body: JSON.stringify({ siteId: this.name, agentId: this._meshAgentId, domain: domain, action: action, context: context, features: features })
|
|
496
|
+
});
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
WABInstance.prototype.learnFeedback = function(decisionId, outcome, reward) {
|
|
500
|
+
if (!this.serverUrl) return Promise.reject(new Error('Learning requires a server URL'));
|
|
501
|
+
return _meshReq(this.serverUrl + '/api/mesh/learning/feedback', {
|
|
502
|
+
method: 'POST',
|
|
503
|
+
headers: { 'Content-Type': 'application/json' },
|
|
504
|
+
body: JSON.stringify({ decisionId: decisionId, outcome: outcome, reward: reward })
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
WABInstance.prototype.learnRecommend = function(domain, actions, context) {
|
|
509
|
+
if (!this.serverUrl || !this._meshAgentId) return Promise.reject(new Error('Must join mesh first'));
|
|
510
|
+
return _meshReq(this.serverUrl + '/api/mesh/learning/recommend', {
|
|
511
|
+
method: 'POST',
|
|
512
|
+
headers: { 'Content-Type': 'application/json' },
|
|
513
|
+
body: JSON.stringify({ siteId: this.name, agentId: this._meshAgentId, domain: domain, actions: actions, context: context })
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
|
|
359
517
|
// ── Static API ────────────────────────────────────────────────────
|
|
360
518
|
|
|
361
519
|
var WAB = {
|
|
@@ -367,36 +525,53 @@
|
|
|
367
525
|
return instance;
|
|
368
526
|
},
|
|
369
527
|
|
|
370
|
-
// Connect to a remote WAB server (for client pages that don't define actions)
|
|
371
528
|
connect: function(serverUrl) {
|
|
372
529
|
return new WABInstance({ name: 'WAB Client', serverUrl: serverUrl });
|
|
373
530
|
},
|
|
374
531
|
|
|
375
532
|
discover: function() {
|
|
376
533
|
if (WAB._instance) return WAB._instance.discover();
|
|
377
|
-
return Promise.
|
|
534
|
+
return Promise.reject(new Error('WAB not initialized. Call WAB.init() first.'));
|
|
378
535
|
},
|
|
379
536
|
|
|
380
537
|
execute: function(actionName, params) {
|
|
381
538
|
if (WAB._instance) return WAB._instance.execute(actionName, params);
|
|
382
|
-
return Promise.
|
|
539
|
+
return Promise.reject(new Error('WAB not initialized. Call WAB.init() first.'));
|
|
383
540
|
},
|
|
384
541
|
|
|
385
542
|
negotiate: function(agentId, proposal) {
|
|
386
543
|
if (WAB._instance) return WAB._instance.negotiate(agentId, proposal);
|
|
387
|
-
return Promise.
|
|
544
|
+
return Promise.reject(new Error('WAB not initialized'));
|
|
388
545
|
},
|
|
389
546
|
|
|
390
547
|
getReputation: function(siteId) {
|
|
391
548
|
if (WAB._instance) return WAB._instance.getReputation(siteId);
|
|
392
|
-
return Promise.
|
|
549
|
+
return Promise.reject(new Error('WAB not initialized'));
|
|
393
550
|
},
|
|
394
551
|
|
|
395
552
|
verifyPrice: function(opts) {
|
|
396
553
|
if (WAB._instance) return WAB._instance.verifyPrice(opts);
|
|
397
|
-
return Promise.
|
|
554
|
+
return Promise.reject(new Error('WAB not initialized'));
|
|
398
555
|
},
|
|
399
556
|
|
|
557
|
+
meshJoin: function(r, d, c) { return WAB._instance ? WAB._instance.meshJoin(r, d, c) : Promise.reject(new Error('WAB not initialized')); },
|
|
558
|
+
meshLeave: function() { return WAB._instance ? WAB._instance.meshLeave() : Promise.reject(new Error('WAB not initialized')); },
|
|
559
|
+
meshPublish: function(ch, mt, s, p, o) { return WAB._instance ? WAB._instance.meshPublish(ch, mt, s, p, o) : Promise.reject(new Error('WAB not initialized')); },
|
|
560
|
+
meshReceive: function(l) { return WAB._instance ? WAB._instance.meshReceive(l) : Promise.reject(new Error('WAB not initialized')); },
|
|
561
|
+
meshAcknowledge: function(id) { return WAB._instance ? WAB._instance.meshAcknowledge(id) : Promise.reject(new Error('WAB not initialized')); },
|
|
562
|
+
meshUnread: function() { return WAB._instance ? WAB._instance.meshUnread() : Promise.reject(new Error('WAB not initialized')); },
|
|
563
|
+
meshShareKnowledge: function(t, k, v, o) { return WAB._instance ? WAB._instance.meshShareKnowledge(t, k, v, o) : Promise.reject(new Error('WAB not initialized')); },
|
|
564
|
+
meshQueryKnowledge: function(p) { return WAB._instance ? WAB._instance.meshQueryKnowledge(p) : Promise.reject(new Error('WAB not initialized')); },
|
|
565
|
+
meshSearchKnowledge: function(q, l) { return WAB._instance ? WAB._instance.meshSearchKnowledge(q, l) : Promise.reject(new Error('WAB not initialized')); },
|
|
566
|
+
meshAlert: function(s, d, p) { return WAB._instance ? WAB._instance.meshAlert(s, d, p) : Promise.reject(new Error('WAB not initialized')); },
|
|
567
|
+
meshCreateVote: function(s, o, d) { return WAB._instance ? WAB._instance.meshCreateVote(s, o, d) : Promise.reject(new Error('WAB not initialized')); },
|
|
568
|
+
meshCastVote: function(id, c, w, r) { return WAB._instance ? WAB._instance.meshCastVote(id, c, w, r) : Promise.reject(new Error('WAB not initialized')); },
|
|
569
|
+
meshTallyVote: function(id) { return WAB._instance ? WAB._instance.meshTallyVote(id) : Promise.reject(new Error('WAB not initialized')); },
|
|
570
|
+
symphonyPerform: function(t, i, s) { return WAB._instance ? WAB._instance.symphonyPerform(t, i, s) : Promise.reject(new Error('WAB not initialized')); },
|
|
571
|
+
learnRecord: function(d, a, c, f) { return WAB._instance ? WAB._instance.learnRecord(d, a, c, f) : Promise.reject(new Error('WAB not initialized')); },
|
|
572
|
+
learnFeedback: function(id, o, r) { return WAB._instance ? WAB._instance.learnFeedback(id, o, r) : Promise.reject(new Error('WAB not initialized')); },
|
|
573
|
+
learnRecommend: function(d, a, c) { return WAB._instance ? WAB._instance.learnRecommend(d, a, c) : Promise.reject(new Error('WAB not initialized')); },
|
|
574
|
+
|
|
400
575
|
_instance: null
|
|
401
576
|
};
|
|
402
577
|
|
|
@@ -1426,8 +1426,204 @@
|
|
|
1426
1426
|
this.logger.log('refresh', {});
|
|
1427
1427
|
}
|
|
1428
1428
|
|
|
1429
|
+
// ── Agent Mesh Protocol (Client-Side) ───────────────────────────────
|
|
1430
|
+
|
|
1431
|
+
async _meshPost(path, body) {
|
|
1432
|
+
const base = this._resolveApiBase();
|
|
1433
|
+
const res = await fetch(`${base}/api/mesh${path}`, {
|
|
1434
|
+
method: 'POST',
|
|
1435
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1436
|
+
body: body ? JSON.stringify(body) : undefined
|
|
1437
|
+
});
|
|
1438
|
+
if (!res.ok) { const e = await res.json().catch(() => ({})); throw new Error(e.error || res.statusText); }
|
|
1439
|
+
return res.json();
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
async _meshGet(path) {
|
|
1443
|
+
const base = this._resolveApiBase();
|
|
1444
|
+
const res = await fetch(`${base}/api/mesh${path}`);
|
|
1445
|
+
if (!res.ok) { const e = await res.json().catch(() => ({})); throw new Error(e.error || res.statusText); }
|
|
1446
|
+
return res.json();
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
async _meshDelete(path) {
|
|
1450
|
+
const base = this._resolveApiBase();
|
|
1451
|
+
const res = await fetch(`${base}/api/mesh${path}`, { method: 'DELETE' });
|
|
1452
|
+
if (!res.ok) { const e = await res.json().catch(() => ({})); throw new Error(e.error || res.statusText); }
|
|
1453
|
+
return res.json();
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
async meshJoin(role, displayName, capabilities) {
|
|
1457
|
+
const data = await this._meshPost('/agents', { siteId: this.config.siteId, role, displayName, capabilities });
|
|
1458
|
+
this._meshAgentId = data.agent.id;
|
|
1459
|
+
this._meshHeartbeat = setInterval(() => {
|
|
1460
|
+
this._meshPost(`/agents/${this._meshAgentId}/heartbeat`).catch(() => {});
|
|
1461
|
+
}, 30000);
|
|
1462
|
+
this.events.emit('mesh:joined', data.agent);
|
|
1463
|
+
return data.agent;
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
async meshLeave() {
|
|
1467
|
+
if (this._meshHeartbeat) { clearInterval(this._meshHeartbeat); this._meshHeartbeat = null; }
|
|
1468
|
+
if (this._meshAgentId) {
|
|
1469
|
+
await this._meshDelete(`/agents/${this._meshAgentId}`).catch(() => {});
|
|
1470
|
+
this._meshAgentId = null;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
async meshPublish(channel, messageType, subject, payload, opts) {
|
|
1475
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1476
|
+
return (await this._meshPost('/messages', {
|
|
1477
|
+
channelName: channel || 'general', senderId: this._meshAgentId,
|
|
1478
|
+
targetId: opts?.targetId, type: messageType, subject, payload,
|
|
1479
|
+
priority: opts?.priority, ttl: opts?.ttl
|
|
1480
|
+
})).message;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
async meshReceive(limit) {
|
|
1484
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1485
|
+
return (await this._meshGet(`/messages?agentId=${this._meshAgentId}&limit=${limit || 50}`)).messages;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
async meshAcknowledge(messageId) {
|
|
1489
|
+
return this._meshPost(`/messages/${encodeURIComponent(messageId)}/acknowledge`);
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
async meshUnread() {
|
|
1493
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1494
|
+
return this._meshGet(`/agents/${this._meshAgentId}/unread`);
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
async meshShareKnowledge(type, key, value, opts) {
|
|
1498
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1499
|
+
return (await this._meshPost('/knowledge', {
|
|
1500
|
+
agentId: this._meshAgentId, type, domain: opts?.domain,
|
|
1501
|
+
key, value, confidence: opts?.confidence, source: opts?.source
|
|
1502
|
+
})).knowledge;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
async meshQueryKnowledge(params) {
|
|
1506
|
+
const qs = new URLSearchParams(params || {}).toString();
|
|
1507
|
+
return (await this._meshGet(`/knowledge?${qs}`)).knowledge;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
async meshSearchKnowledge(query, limit) {
|
|
1511
|
+
return (await this._meshGet(`/knowledge/search/${encodeURIComponent(query)}?limit=${limit || 20}`)).knowledge;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
async meshAlert(subject, details, priority) {
|
|
1515
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1516
|
+
return (await this._meshPost('/alert', { senderId: this._meshAgentId, subject, details, priority })).message;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
async meshCreateVote(subject, options, deadlineSeconds) {
|
|
1520
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1521
|
+
return (await this._meshPost('/votes', { senderId: this._meshAgentId, subject, options, deadlineSeconds })).vote;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
async meshCastVote(voteMessageId, choice, weight, reason) {
|
|
1525
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1526
|
+
return (await this._meshPost(`/votes/${encodeURIComponent(voteMessageId)}/cast`, {
|
|
1527
|
+
voterId: this._meshAgentId, choice, weight, reason
|
|
1528
|
+
})).result;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
async meshTallyVote(voteMessageId) {
|
|
1532
|
+
return (await this._meshGet(`/votes/${encodeURIComponent(voteMessageId)}/tally`)).tally;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
async symphonyPerform(template, inputData, schema) {
|
|
1536
|
+
const data = await this._meshPost('/symphony/compose', {
|
|
1537
|
+
siteId: this.config.siteId, template, inputData, schema
|
|
1538
|
+
});
|
|
1539
|
+
this.events.emit('symphony:completed', data);
|
|
1540
|
+
return data;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
async learnRecord(domain, action, context, features) {
|
|
1544
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1545
|
+
return this._meshPost('/learning/decisions', {
|
|
1546
|
+
siteId: this.config.siteId, agentId: this._meshAgentId, domain, action, context, features
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
async learnFeedback(decisionId, outcome, reward) {
|
|
1551
|
+
return this._meshPost('/learning/feedback', { decisionId, outcome, reward });
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
async learnRecommend(domain, actions, context) {
|
|
1555
|
+
if (!this._meshAgentId) throw new Error('Must call meshJoin() first');
|
|
1556
|
+
return this._meshPost('/learning/recommend', {
|
|
1557
|
+
siteId: this.config.siteId, agentId: this._meshAgentId, domain, actions, context
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
// ── Commander Agent Protocol ────────────────────────────────────────
|
|
1562
|
+
|
|
1563
|
+
async _cmdPost(path, body) {
|
|
1564
|
+
const base = this.config.serverUrl || '';
|
|
1565
|
+
const res = await fetch(`${base}/api/commander${path}`, {
|
|
1566
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
1567
|
+
body: JSON.stringify(body)
|
|
1568
|
+
});
|
|
1569
|
+
if (!res.ok) throw new Error(`Commander POST ${path} failed: ${res.status}`);
|
|
1570
|
+
return res.json();
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
async _cmdGet(path) {
|
|
1574
|
+
const base = this.config.serverUrl || '';
|
|
1575
|
+
const res = await fetch(`${base}/api/commander${path}`);
|
|
1576
|
+
if (!res.ok) throw new Error(`Commander GET ${path} failed: ${res.status}`);
|
|
1577
|
+
return res.json();
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/** Launch a mission — decompose a goal and execute it. */
|
|
1581
|
+
async commanderLaunch(goal, options) {
|
|
1582
|
+
const data = await this._cmdPost('/missions/launch', {
|
|
1583
|
+
siteId: this.config.siteId, goal,
|
|
1584
|
+
title: options?.title || goal.substring(0, 80),
|
|
1585
|
+
strategy: options?.strategy,
|
|
1586
|
+
priority: options?.priority, context: options?.context
|
|
1587
|
+
});
|
|
1588
|
+
this.events.emit('commander:mission', data.mission);
|
|
1589
|
+
return data.mission;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/** Get commander + edge + local AI stats. */
|
|
1593
|
+
async commanderStats() {
|
|
1594
|
+
return this._cmdGet(`/stats?siteId=${encodeURIComponent(this.config.siteId || 'default')}`);
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/** Register an edge computing node. */
|
|
1598
|
+
async edgeRegisterNode(hostname, hardware, capabilities) {
|
|
1599
|
+
return this._cmdPost('/edge/nodes', {
|
|
1600
|
+
siteId: this.config.siteId, hostname, hardware, capabilities
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
/** Submit a task to the edge computing queue. */
|
|
1605
|
+
async edgeSubmitTask(taskType, payload, options) {
|
|
1606
|
+
return this._cmdPost('/edge/tasks', { taskType, payload, ...options });
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
/** Discover local AI models (Ollama, llama.cpp, etc.). */
|
|
1610
|
+
async localAIDiscover(customEndpoints) {
|
|
1611
|
+
return this._cmdPost('/local-ai/discover', {
|
|
1612
|
+
siteId: this.config.siteId, customEndpoints
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
/** Run inference on a local AI model. */
|
|
1617
|
+
async localAIInfer(prompt, options) {
|
|
1618
|
+
return this._cmdPost('/local-ai/infer', {
|
|
1619
|
+
siteId: this.config.siteId, prompt, ...options
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1429
1623
|
destroy() {
|
|
1430
1624
|
this.events.emit('destroy');
|
|
1625
|
+
if (this._meshHeartbeat) { clearInterval(this._meshHeartbeat); this._meshHeartbeat = null; }
|
|
1626
|
+
this._meshAgentId = null;
|
|
1431
1627
|
if (this._mutationObserver) {
|
|
1432
1628
|
this._mutationObserver.disconnect();
|
|
1433
1629
|
this._mutationObserver = null;
|