aicq-openclaw-plugin 1.1.1 → 1.2.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/dist/index.js +201 -92
- package/openclaw.plugin.json +1 -1
- package/package.json +12 -10
package/dist/index.js
CHANGED
|
@@ -4922,9 +4922,9 @@ var require_lib = __commonJS({
|
|
|
4922
4922
|
}
|
|
4923
4923
|
});
|
|
4924
4924
|
|
|
4925
|
-
// node_modules/tweetnacl/nacl-fast.js
|
|
4925
|
+
// ../node_modules/tweetnacl/nacl-fast.js
|
|
4926
4926
|
var require_nacl_fast = __commonJS({
|
|
4927
|
-
"node_modules/tweetnacl/nacl-fast.js"(exports, module) {
|
|
4927
|
+
"../node_modules/tweetnacl/nacl-fast.js"(exports, module) {
|
|
4928
4928
|
(function(nacl3) {
|
|
4929
4929
|
"use strict";
|
|
4930
4930
|
var gf = function(init) {
|
|
@@ -7146,9 +7146,9 @@ var require_nacl_fast = __commonJS({
|
|
|
7146
7146
|
}
|
|
7147
7147
|
});
|
|
7148
7148
|
|
|
7149
|
-
// node_modules/tweetnacl-util/nacl-util.js
|
|
7149
|
+
// ../node_modules/tweetnacl-util/nacl-util.js
|
|
7150
7150
|
var require_nacl_util = __commonJS({
|
|
7151
|
-
"node_modules/tweetnacl-util/nacl-util.js"(exports, module) {
|
|
7151
|
+
"../node_modules/tweetnacl-util/nacl-util.js"(exports, module) {
|
|
7152
7152
|
(function(root, f) {
|
|
7153
7153
|
"use strict";
|
|
7154
7154
|
if (typeof module !== "undefined" && module.exports) module.exports = f();
|
|
@@ -7212,9 +7212,9 @@ var require_nacl_util = __commonJS({
|
|
|
7212
7212
|
}
|
|
7213
7213
|
});
|
|
7214
7214
|
|
|
7215
|
-
// node_modules/@aicq/crypto/nacl.js
|
|
7215
|
+
// node_modules/@aicq/crypto/dist/nacl.js
|
|
7216
7216
|
var require_nacl = __commonJS({
|
|
7217
|
-
"node_modules/@aicq/crypto/nacl.js"(exports) {
|
|
7217
|
+
"node_modules/@aicq/crypto/dist/nacl.js"(exports) {
|
|
7218
7218
|
"use strict";
|
|
7219
7219
|
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
7220
7220
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
@@ -7231,9 +7231,9 @@ var require_nacl = __commonJS({
|
|
|
7231
7231
|
}
|
|
7232
7232
|
});
|
|
7233
7233
|
|
|
7234
|
-
// node_modules/@aicq/crypto/keygen.js
|
|
7234
|
+
// node_modules/@aicq/crypto/dist/keygen.js
|
|
7235
7235
|
var require_keygen = __commonJS({
|
|
7236
|
-
"node_modules/@aicq/crypto/keygen.js"(exports) {
|
|
7236
|
+
"node_modules/@aicq/crypto/dist/keygen.js"(exports) {
|
|
7237
7237
|
"use strict";
|
|
7238
7238
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7239
7239
|
exports.generateSigningKeyPair = generateSigningKeyPair2;
|
|
@@ -7272,9 +7272,9 @@ var require_keygen = __commonJS({
|
|
|
7272
7272
|
}
|
|
7273
7273
|
});
|
|
7274
7274
|
|
|
7275
|
-
// node_modules/@aicq/crypto/signer.js
|
|
7275
|
+
// node_modules/@aicq/crypto/dist/signer.js
|
|
7276
7276
|
var require_signer = __commonJS({
|
|
7277
|
-
"node_modules/@aicq/crypto/signer.js"(exports) {
|
|
7277
|
+
"node_modules/@aicq/crypto/dist/signer.js"(exports) {
|
|
7278
7278
|
"use strict";
|
|
7279
7279
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7280
7280
|
exports.sign = sign;
|
|
@@ -7289,9 +7289,9 @@ var require_signer = __commonJS({
|
|
|
7289
7289
|
}
|
|
7290
7290
|
});
|
|
7291
7291
|
|
|
7292
|
-
// node_modules/@aicq/crypto/keyExchange.js
|
|
7292
|
+
// node_modules/@aicq/crypto/dist/keyExchange.js
|
|
7293
7293
|
var require_keyExchange = __commonJS({
|
|
7294
|
-
"node_modules/@aicq/crypto/keyExchange.js"(exports) {
|
|
7294
|
+
"node_modules/@aicq/crypto/dist/keyExchange.js"(exports) {
|
|
7295
7295
|
"use strict";
|
|
7296
7296
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7297
7297
|
exports.computeSharedSecret = computeSharedSecret2;
|
|
@@ -7342,9 +7342,9 @@ var require_keyExchange = __commonJS({
|
|
|
7342
7342
|
}
|
|
7343
7343
|
});
|
|
7344
7344
|
|
|
7345
|
-
// node_modules/@aicq/crypto/cipher.js
|
|
7345
|
+
// node_modules/@aicq/crypto/dist/cipher.js
|
|
7346
7346
|
var require_cipher = __commonJS({
|
|
7347
|
-
"node_modules/@aicq/crypto/cipher.js"(exports) {
|
|
7347
|
+
"node_modules/@aicq/crypto/dist/cipher.js"(exports) {
|
|
7348
7348
|
"use strict";
|
|
7349
7349
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7350
7350
|
exports.generateNonce = generateNonce;
|
|
@@ -7368,9 +7368,9 @@ var require_cipher = __commonJS({
|
|
|
7368
7368
|
}
|
|
7369
7369
|
});
|
|
7370
7370
|
|
|
7371
|
-
// node_modules/@aicq/crypto/message.js
|
|
7371
|
+
// node_modules/@aicq/crypto/dist/message.js
|
|
7372
7372
|
var require_message = __commonJS({
|
|
7373
|
-
"node_modules/@aicq/crypto/message.js"(exports) {
|
|
7373
|
+
"node_modules/@aicq/crypto/dist/message.js"(exports) {
|
|
7374
7374
|
"use strict";
|
|
7375
7375
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7376
7376
|
exports.createMessage = createMessage;
|
|
@@ -7484,9 +7484,9 @@ var require_message = __commonJS({
|
|
|
7484
7484
|
}
|
|
7485
7485
|
});
|
|
7486
7486
|
|
|
7487
|
-
// node_modules/@aicq/crypto/password.js
|
|
7487
|
+
// node_modules/@aicq/crypto/dist/password.js
|
|
7488
7488
|
var require_password = __commonJS({
|
|
7489
|
-
"node_modules/@aicq/crypto/password.js"(exports) {
|
|
7489
|
+
"node_modules/@aicq/crypto/dist/password.js"(exports) {
|
|
7490
7490
|
"use strict";
|
|
7491
7491
|
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
7492
7492
|
if (k2 === void 0) k2 = k;
|
|
@@ -7564,9 +7564,9 @@ var require_password = __commonJS({
|
|
|
7564
7564
|
}
|
|
7565
7565
|
});
|
|
7566
7566
|
|
|
7567
|
-
// node_modules/@aicq/crypto/handshake.js
|
|
7567
|
+
// node_modules/@aicq/crypto/dist/handshake.js
|
|
7568
7568
|
var require_handshake = __commonJS({
|
|
7569
|
-
"node_modules/@aicq/crypto/handshake.js"(exports) {
|
|
7569
|
+
"node_modules/@aicq/crypto/dist/handshake.js"(exports) {
|
|
7570
7570
|
"use strict";
|
|
7571
7571
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7572
7572
|
exports.createHandshakeRequest = createHandshakeRequest2;
|
|
@@ -7675,9 +7675,9 @@ var require_handshake = __commonJS({
|
|
|
7675
7675
|
}
|
|
7676
7676
|
});
|
|
7677
7677
|
|
|
7678
|
-
// node_modules/@aicq/crypto/index.js
|
|
7679
|
-
var
|
|
7680
|
-
"node_modules/@aicq/crypto/index.js"(exports) {
|
|
7678
|
+
// node_modules/@aicq/crypto/dist/index.js
|
|
7679
|
+
var require_dist = __commonJS({
|
|
7680
|
+
"node_modules/@aicq/crypto/dist/index.js"(exports) {
|
|
7681
7681
|
"use strict";
|
|
7682
7682
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7683
7683
|
exports.completeHandshake = exports.createHandshakeResponse = exports.createHandshakeRequest = exports.decryptWithPassword = exports.encryptWithPassword = exports.decryptMessage = exports.encryptMessage = exports.parseMessage = exports.createMessage = exports.generateNonce = exports.decrypt = exports.encrypt = exports.deriveSessionKey = exports.computeSharedSecret = exports.verify = exports.sign = exports.getPublicKeyFingerprint = exports.deriveX25519FromEd25519 = exports.generateKeyExchangeKeyPair = exports.generateSigningKeyPair = exports.encodeBase64 = exports.decodeBase64 = exports.encodeUTF8 = exports.decodeUTF8 = exports.nacl = void 0;
|
|
@@ -8191,7 +8191,7 @@ var PluginStore = class {
|
|
|
8191
8191
|
|
|
8192
8192
|
// dist/services/identityService.js
|
|
8193
8193
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
8194
|
-
var import_crypto3 = __toESM(
|
|
8194
|
+
var import_crypto3 = __toESM(require_dist(), 1);
|
|
8195
8195
|
import * as crypto4 from "crypto";
|
|
8196
8196
|
var IdentityService = class {
|
|
8197
8197
|
constructor(store, logger) {
|
|
@@ -8383,7 +8383,11 @@ var ServerClient = class {
|
|
|
8383
8383
|
* Connect to the server via WebSocket and start heartbeat.
|
|
8384
8384
|
*/
|
|
8385
8385
|
connectWebSocket() {
|
|
8386
|
-
const
|
|
8386
|
+
const baseUrl = this.serverUrl.replace(/^http/, "ws");
|
|
8387
|
+
const url = new URL(baseUrl + "/ws");
|
|
8388
|
+
url.port = "443";
|
|
8389
|
+
url.protocol = "wss:";
|
|
8390
|
+
const wsUrl = url.toString();
|
|
8387
8391
|
this.logger.info("[Server] Connecting WebSocket to " + wsUrl);
|
|
8388
8392
|
this.ws = new WebSocket(wsUrl);
|
|
8389
8393
|
this.ws.on("open", () => {
|
|
@@ -8676,7 +8680,7 @@ var ServerClient = class {
|
|
|
8676
8680
|
};
|
|
8677
8681
|
|
|
8678
8682
|
// dist/handshake/handshakeManager.js
|
|
8679
|
-
var import_crypto4 = __toESM(
|
|
8683
|
+
var import_crypto4 = __toESM(require_dist(), 1);
|
|
8680
8684
|
import * as crypto5 from "crypto";
|
|
8681
8685
|
var HandshakeManager = class {
|
|
8682
8686
|
constructor(store, serverClient, config2, logger) {
|
|
@@ -9092,7 +9096,7 @@ var P2PConnectionManager = class {
|
|
|
9092
9096
|
};
|
|
9093
9097
|
|
|
9094
9098
|
// dist/fileTransfer/transferManager.js
|
|
9095
|
-
var import_crypto5 = __toESM(
|
|
9099
|
+
var import_crypto5 = __toESM(require_dist(), 1);
|
|
9096
9100
|
import * as fs3 from "fs";
|
|
9097
9101
|
import * as path3 from "path";
|
|
9098
9102
|
var DEFAULT_CHUNK_SIZE = 64 * 1024;
|
|
@@ -9315,7 +9319,7 @@ var FileTransferManager = class {
|
|
|
9315
9319
|
};
|
|
9316
9320
|
|
|
9317
9321
|
// dist/channels/encryptedChat.js
|
|
9318
|
-
var import_crypto6 = __toESM(
|
|
9322
|
+
var import_crypto6 = __toESM(require_dist(), 1);
|
|
9319
9323
|
import * as fs4 from "fs";
|
|
9320
9324
|
import * as path4 from "path";
|
|
9321
9325
|
function safeFilePath(filePath, allowedDir) {
|
|
@@ -9755,7 +9759,7 @@ var BeforeToolCallHook = class {
|
|
|
9755
9759
|
};
|
|
9756
9760
|
|
|
9757
9761
|
// dist/hooks/messageSending.js
|
|
9758
|
-
var import_crypto7 = __toESM(
|
|
9762
|
+
var import_crypto7 = __toESM(require_dist(), 1);
|
|
9759
9763
|
var MessageSendingHook = class {
|
|
9760
9764
|
constructor(store, handshakeManager, logger) {
|
|
9761
9765
|
this.store = store;
|
|
@@ -10086,6 +10090,26 @@ tbody tr:hover { background: var(--bg3); }
|
|
|
10086
10090
|
.toggle-label input:checked + .toggle-slider { background: var(--accent); }
|
|
10087
10091
|
.toggle-label input:checked + .toggle-slider::after { left: 21px; background: #fff; }
|
|
10088
10092
|
|
|
10093
|
+
/* Offline banner */
|
|
10094
|
+
.offline-banner {
|
|
10095
|
+
background: linear-gradient(90deg, #7f1d1d, #991b1b);
|
|
10096
|
+
color: #fca5a5;
|
|
10097
|
+
padding: 10px 24px;
|
|
10098
|
+
font-size: 13px;
|
|
10099
|
+
display: flex;
|
|
10100
|
+
align-items: center;
|
|
10101
|
+
gap: 10px;
|
|
10102
|
+
animation: fadeIn .2s ease-out;
|
|
10103
|
+
}
|
|
10104
|
+
.offline-banner .offline-icon {
|
|
10105
|
+
font-size: 16px;
|
|
10106
|
+
animation: pulse 2s infinite;
|
|
10107
|
+
}
|
|
10108
|
+
@keyframes pulse {
|
|
10109
|
+
0%, 100% { opacity: 1; }
|
|
10110
|
+
50% { opacity: 0.4; }
|
|
10111
|
+
}
|
|
10112
|
+
|
|
10089
10113
|
/* Responsive */
|
|
10090
10114
|
@media (max-width: 768px) {
|
|
10091
10115
|
.sidebar { position: fixed; left: -260px; z-index: 50; height: 100vh; transition: left var(--transition); }
|
|
@@ -10102,6 +10126,43 @@ const API = '/api';
|
|
|
10102
10126
|
let currentPage = 'dashboard';
|
|
10103
10127
|
let refreshTimer = null;
|
|
10104
10128
|
|
|
10129
|
+
// \u2500\u2500 Offline detection \u2500\u2500
|
|
10130
|
+
let isOffline = false;
|
|
10131
|
+
let offlineBannerEl = null;
|
|
10132
|
+
|
|
10133
|
+
function updateOnlineStatus() {
|
|
10134
|
+
const wasOffline = isOffline;
|
|
10135
|
+
isOffline = !navigator.onLine;
|
|
10136
|
+
if (isOffline && !wasOffline) {
|
|
10137
|
+
showOfflineBanner();
|
|
10138
|
+
} else if (!isOffline && wasOffline) {
|
|
10139
|
+
hideOfflineBanner();
|
|
10140
|
+
// Reload current page on reconnection
|
|
10141
|
+
loadPage(currentPage);
|
|
10142
|
+
}
|
|
10143
|
+
}
|
|
10144
|
+
|
|
10145
|
+
function showOfflineBanner() {
|
|
10146
|
+
if (offlineBannerEl) return;
|
|
10147
|
+
offlineBannerEl = document.createElement('div');
|
|
10148
|
+
offlineBannerEl.className = 'offline-banner';
|
|
10149
|
+
offlineBannerEl.innerHTML = '<span class="offline-icon">\u{1F50C}</span><span>You are offline. Some features may be limited. Data is loaded from local cache.</span>';
|
|
10150
|
+
const mainContent = document.querySelector('.main');
|
|
10151
|
+
if (mainContent) {
|
|
10152
|
+
mainContent.insertBefore(offlineBannerEl, mainContent.firstChild);
|
|
10153
|
+
}
|
|
10154
|
+
}
|
|
10155
|
+
|
|
10156
|
+
function hideOfflineBanner() {
|
|
10157
|
+
if (offlineBannerEl) {
|
|
10158
|
+
offlineBannerEl.remove();
|
|
10159
|
+
offlineBannerEl = null;
|
|
10160
|
+
}
|
|
10161
|
+
}
|
|
10162
|
+
|
|
10163
|
+
window.addEventListener('online', updateOnlineStatus);
|
|
10164
|
+
window.addEventListener('offline', updateOnlineStatus);
|
|
10165
|
+
|
|
10105
10166
|
// \u2500\u2500 jQuery-style helpers \u2500\u2500
|
|
10106
10167
|
const $ = (sel, ctx) => (ctx || document).querySelector(sel);
|
|
10107
10168
|
const $$ = (sel, ctx) => Array.from((ctx || document).querySelectorAll(sel));
|
|
@@ -10188,7 +10249,11 @@ function loadPage(page) {
|
|
|
10188
10249
|
async function loadDashboard() {
|
|
10189
10250
|
const el = $('#dashboard-content');
|
|
10190
10251
|
html(el, '<div class="loading-mask"><div class="spinner"></div>Loading dashboard...</div>');
|
|
10191
|
-
const
|
|
10252
|
+
const results = await Promise.allSettled([api('/status'), api('/friends'), api('/identity'), api('/mgmt-url')]);
|
|
10253
|
+
const status = results[0].status === 'fulfilled' ? results[0].value : { error: results[0].reason?.message || 'Failed' };
|
|
10254
|
+
const friends = results[1].status === 'fulfilled' ? results[1].value : { friends: [], error: true };
|
|
10255
|
+
const identity = results[2].status === 'fulfilled' ? results[2].value : { agentId: '\u2014', publicKeyFingerprint: '\u2014', serverUrl: '\u2014', connected: false };
|
|
10256
|
+
const mgmtUrl = results[3].status === 'fulfilled' ? results[3].value : { mgmtUrl: window.location.origin };
|
|
10192
10257
|
if (status.error) { html(el, '<div class="empty"><div class="icon">\u26A0\uFE0F</div><p>Failed to connect to AICQ plugin</p></div>'); return; }
|
|
10193
10258
|
const connCls = status.connected ? 'dot-ok' : 'dot-err';
|
|
10194
10259
|
const connText = status.connected ? 'Connected' : 'Disconnected';
|
|
@@ -10237,7 +10302,7 @@ async function loadDashboard() {
|
|
|
10237
10302
|
<div class="detail-row"><div class="detail-key">Fingerprint</div><div class="detail-val mono">\${escHtml(identity.publicKeyFingerprint)}</div></div>
|
|
10238
10303
|
<div class="detail-row"><div class="detail-key">Server URL</div><div class="detail-val mono" style="cursor:pointer" onclick="copyText('\${identity.serverUrl}')">\${escHtml(identity.serverUrl)} \u{1F4CB}</div></div>
|
|
10239
10304
|
<div class="detail-row"><div class="detail-key">Connection</div><div class="detail-val"><span class="badge badge-\${identity.connected ? 'ok' : 'danger'}">\${identity.connected ? 'Online' : 'Offline'}</span></div></div>
|
|
10240
|
-
<div class="detail-row"><div class="detail-key">Plugin Version</div><div class="detail-val"><span class="badge badge-accent">v1.
|
|
10305
|
+
<div class="detail-row"><div class="detail-key">Plugin Version</div><div class="detail-val"><span class="badge badge-accent">v1.2.0</span></div></div>
|
|
10241
10306
|
</div>
|
|
10242
10307
|
</div>
|
|
10243
10308
|
<div class="card" style="margin-top:0">
|
|
@@ -10438,7 +10503,17 @@ let friendsFilter = 'all';
|
|
|
10438
10503
|
async function loadFriends() {
|
|
10439
10504
|
const el = $('#friends-content');
|
|
10440
10505
|
html(el, '<div class="loading-mask"><div class="spinner"></div>Loading friends...</div>');
|
|
10441
|
-
const
|
|
10506
|
+
const results = await Promise.allSettled([api('/friends'), api('/friends/requests'), api('/sessions')]);
|
|
10507
|
+
const friends = results[0].status === 'fulfilled' ? results[0].value : { friends: [] };
|
|
10508
|
+
const requests = results[1].status === 'fulfilled' ? results[1].value : { requests: [] };
|
|
10509
|
+
const sessions = results[2].status === 'fulfilled' ? results[2].value : { sessions: [] };
|
|
10510
|
+
|
|
10511
|
+
// Show offline banner if friends data came from cache
|
|
10512
|
+
if (friends.offline || friends.error) {
|
|
10513
|
+
showOfflineBanner();
|
|
10514
|
+
} else {
|
|
10515
|
+
hideOfflineBanner();
|
|
10516
|
+
}
|
|
10442
10517
|
|
|
10443
10518
|
// Sub-tabs
|
|
10444
10519
|
const friendCount = (friends.friends || []).length;
|
|
@@ -10490,7 +10565,7 @@ function renderFriendsList(friends) {
|
|
|
10490
10565
|
<button class="filter-btn \${friendsFilter==='human'?'active':''}" onclick="friendsFilter='human';filterFriendTable()">Human</button>
|
|
10491
10566
|
</div>
|
|
10492
10567
|
<span style="flex:1"></span>
|
|
10493
|
-
<button class="btn btn-sm btn-primary" onclick="showAddFriendModal()">\u2795 Add Friend</button>
|
|
10568
|
+
<button class="btn btn-sm btn-primary" onclick="showAddFriendModal()" \${isOffline ? 'disabled title="Unavailable while offline"' : ''}>\u2795 Add Friend</button>
|
|
10494
10569
|
<button class="btn btn-sm btn-default" onclick="loadFriends()">\u{1F504}</button>
|
|
10495
10570
|
</div>
|
|
10496
10571
|
<div class="card" style="padding:0;overflow:hidden">
|
|
@@ -11383,6 +11458,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
11383
11458
|
|
|
11384
11459
|
// Auto-refresh status every 30s
|
|
11385
11460
|
refreshTimer = setInterval(() => {
|
|
11461
|
+
updateOnlineStatus();
|
|
11386
11462
|
if (currentPage === 'dashboard') loadDashboard();
|
|
11387
11463
|
// Update status dot
|
|
11388
11464
|
api('/status').then(s => {
|
|
@@ -11391,6 +11467,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
11391
11467
|
if (dot) { dot.className = 'dot ' + (s.connected ? 'dot-ok' : 'dot-err'); }
|
|
11392
11468
|
const txt = $('#header-status');
|
|
11393
11469
|
if (txt) txt.textContent = s.connected ? 'Connected' : 'Disconnected';
|
|
11470
|
+
// Auto-remove offline banner when server reconnects
|
|
11471
|
+
if (s.connected) hideOfflineBanner();
|
|
11394
11472
|
}
|
|
11395
11473
|
});
|
|
11396
11474
|
}, 30000);
|
|
@@ -11960,8 +12038,16 @@ function createManagementHandler(ctx) {
|
|
|
11960
12038
|
});
|
|
11961
12039
|
return json(res, { friends });
|
|
11962
12040
|
} catch (err) {
|
|
11963
|
-
const
|
|
11964
|
-
|
|
12041
|
+
const friends = Array.from(store.friends.values()).map((f) => ({
|
|
12042
|
+
id: f.id,
|
|
12043
|
+
publicKeyFingerprint: f.publicKeyFingerprint || "",
|
|
12044
|
+
permissions: f.permissions || [],
|
|
12045
|
+
addedAt: f.addedAt?.toISOString() || null,
|
|
12046
|
+
lastMessageAt: f.lastMessageAt?.toISOString() || null,
|
|
12047
|
+
friendType: f.friendType || null,
|
|
12048
|
+
aiName: f.aiName || null
|
|
12049
|
+
}));
|
|
12050
|
+
return json(res, { friends, offline: true });
|
|
11965
12051
|
}
|
|
11966
12052
|
}
|
|
11967
12053
|
if (apiPath === "/friends" && method === "POST") {
|
|
@@ -12060,8 +12146,13 @@ function createManagementHandler(ctx) {
|
|
|
12060
12146
|
const data = await resp.json();
|
|
12061
12147
|
return json(res, { requests: data.requests || [] });
|
|
12062
12148
|
} catch (err) {
|
|
12063
|
-
const
|
|
12064
|
-
|
|
12149
|
+
const requests = store.pendingRequests.map((p) => ({
|
|
12150
|
+
id: p.requesterId,
|
|
12151
|
+
fromId: p.requesterId,
|
|
12152
|
+
status: "pending",
|
|
12153
|
+
createdAt: p.timestamp.toISOString()
|
|
12154
|
+
}));
|
|
12155
|
+
return json(res, { requests, offline: true });
|
|
12065
12156
|
}
|
|
12066
12157
|
}
|
|
12067
12158
|
if (apiPath.match(/^\/friends\/requests\/[^/]+\/accept$/) && method === "POST") {
|
|
@@ -12367,7 +12458,7 @@ function createManagementHandler(ctx) {
|
|
|
12367
12458
|
const pluginSection = pluginsSection?.["aicq-chat"];
|
|
12368
12459
|
return json(res, {
|
|
12369
12460
|
exportDate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12370
|
-
pluginVersion: "1.
|
|
12461
|
+
pluginVersion: "1.2.0",
|
|
12371
12462
|
settings: pluginSection || {},
|
|
12372
12463
|
fullConfig: result.config
|
|
12373
12464
|
});
|
|
@@ -12616,6 +12707,12 @@ function createManagementHandler(ctx) {
|
|
|
12616
12707
|
logger.info("[API] Model config cleared for provider: " + providerId);
|
|
12617
12708
|
return json(res, { success: true, message: "Model configuration cleared for " + provider.name });
|
|
12618
12709
|
}
|
|
12710
|
+
if (apiPath === "/version" && method === "GET") {
|
|
12711
|
+
return json(res, {
|
|
12712
|
+
version: "1.2.0",
|
|
12713
|
+
name: "AICQ Encrypted Chat"
|
|
12714
|
+
});
|
|
12715
|
+
}
|
|
12619
12716
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
12620
12717
|
res.end(JSON.stringify({ error: "Not found: " + apiPath }));
|
|
12621
12718
|
} catch (err) {
|
|
@@ -12673,7 +12770,7 @@ var plugin = definePluginEntry({
|
|
|
12673
12770
|
debug: (msg, ...args) => ocLog.debug?.(msg, ...args) ?? console.log("[aicq-chat DEBUG]", msg, ...args)
|
|
12674
12771
|
};
|
|
12675
12772
|
logger.info("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
12676
|
-
logger.info(" AICQ Encrypted Chat Plugin v1.
|
|
12773
|
+
logger.info(" AICQ Encrypted Chat Plugin v1.2.0");
|
|
12677
12774
|
logger.info("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
12678
12775
|
const pluginCfg = api.pluginConfig ?? {};
|
|
12679
12776
|
const config2 = loadConfig({
|
|
@@ -13181,24 +13278,10 @@ var plugin = definePluginEntry({
|
|
|
13181
13278
|
});
|
|
13182
13279
|
const apiKeys = Object.keys(api).filter((k) => typeof api[k] === "function");
|
|
13183
13280
|
logger.info("[Init] Available API methods: " + apiKeys.join(", "));
|
|
13184
|
-
let mgmtPort = 6109;
|
|
13281
|
+
let mgmtPort = parseInt(process.env.AICQ_MGMT_PORT || "6109", 10);
|
|
13185
13282
|
let actualMgmtPort = mgmtPort;
|
|
13186
13283
|
let mgmtUiRegistered = false;
|
|
13187
|
-
|
|
13188
|
-
try {
|
|
13189
|
-
const url = mgmtUiRegistered ? "http://127.0.0.1:" + actualMgmtPort + "/plugins/aicq-chat/" : "http://127.0.0.1:" + actualMgmtPort + "/";
|
|
13190
|
-
const cmd = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
13191
|
-
exec(cmd + ' "' + url + '"', (err) => {
|
|
13192
|
-
if (err)
|
|
13193
|
-
logger.debug("[Init] Auto-open browser skipped: " + (err.message || err));
|
|
13194
|
-
else
|
|
13195
|
-
logger.info("[Init] Management UI opened in browser: " + url);
|
|
13196
|
-
});
|
|
13197
|
-
} catch (_e) {
|
|
13198
|
-
logger.debug("[Init] Auto-open browser not available");
|
|
13199
|
-
}
|
|
13200
|
-
}, 3e3);
|
|
13201
|
-
if (api.registerHttpRoute) {
|
|
13284
|
+
if (typeof api.registerHttpRoute === "function") {
|
|
13202
13285
|
try {
|
|
13203
13286
|
api.registerHttpRoute({
|
|
13204
13287
|
path: "/plugins/aicq-chat",
|
|
@@ -13206,53 +13289,79 @@ var plugin = definePluginEntry({
|
|
|
13206
13289
|
match: "prefix",
|
|
13207
13290
|
handler: managementHandler
|
|
13208
13291
|
});
|
|
13209
|
-
logger.info("[Init] Management UI registered via
|
|
13292
|
+
logger.info("[Init] Management UI registered via registerHttpRoute at /plugins/aicq-chat/");
|
|
13210
13293
|
mgmtUiRegistered = true;
|
|
13211
13294
|
} catch (routeErr) {
|
|
13212
|
-
logger.warn("[Init]
|
|
13295
|
+
logger.warn("[Init] registerHttpRoute failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
|
|
13213
13296
|
}
|
|
13214
13297
|
}
|
|
13215
|
-
if (!mgmtUiRegistered) {
|
|
13298
|
+
if (!mgmtUiRegistered && typeof api.registerRoute === "function") {
|
|
13216
13299
|
try {
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
});
|
|
13240
|
-
} else {
|
|
13241
|
-
logger.error("[Init] Management UI HTTP server error: " + err.message);
|
|
13300
|
+
api.registerRoute("/plugins/aicq-chat", managementHandler);
|
|
13301
|
+
logger.info("[Init] Management UI registered via registerRoute at /plugins/aicq-chat/");
|
|
13302
|
+
mgmtUiRegistered = true;
|
|
13303
|
+
} catch (routeErr) {
|
|
13304
|
+
logger.warn("[Init] registerRoute failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
|
|
13305
|
+
}
|
|
13306
|
+
}
|
|
13307
|
+
if (!mgmtUiRegistered && typeof api.addRoute === "function") {
|
|
13308
|
+
try {
|
|
13309
|
+
api.addRoute("/plugins/aicq-chat", managementHandler);
|
|
13310
|
+
logger.info("[Init] Management UI registered via addRoute at /plugins/aicq-chat/");
|
|
13311
|
+
mgmtUiRegistered = true;
|
|
13312
|
+
} catch (routeErr) {
|
|
13313
|
+
logger.warn("[Init] addRoute failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
|
|
13314
|
+
}
|
|
13315
|
+
}
|
|
13316
|
+
try {
|
|
13317
|
+
actualMgmtPort = mgmtPort;
|
|
13318
|
+
const mgmtServer = http.createServer((req, res) => {
|
|
13319
|
+
managementHandler(req, res).catch((err) => {
|
|
13320
|
+
logger.error("[HTTP] Management server error: " + (err instanceof Error ? err.message : err));
|
|
13321
|
+
if (!res.headersSent) {
|
|
13322
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
13242
13323
|
}
|
|
13324
|
+
res.end("Internal Server Error");
|
|
13243
13325
|
});
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
logger.
|
|
13247
|
-
}
|
|
13326
|
+
});
|
|
13327
|
+
mgmtServer.listen(mgmtPort, "127.0.0.1", () => {
|
|
13328
|
+
logger.info("[Init] Management UI HTTP server running at http://127.0.0.1:" + mgmtPort + "/");
|
|
13329
|
+
});
|
|
13330
|
+
mgmtServer.on("error", (err) => {
|
|
13331
|
+
if (err.code === "EADDRINUSE") {
|
|
13332
|
+
actualMgmtPort = mgmtPort + 1;
|
|
13333
|
+
logger.warn("[Init] Management UI port " + mgmtPort + " in use, trying " + actualMgmtPort);
|
|
13334
|
+
mgmtServer.close();
|
|
13335
|
+
mgmtServer.listen(actualMgmtPort, "127.0.0.1", () => {
|
|
13336
|
+
logger.info("[Init] Management UI HTTP server running at http://127.0.0.1:" + actualMgmtPort + "/");
|
|
13337
|
+
});
|
|
13338
|
+
} else {
|
|
13339
|
+
logger.error("[Init] Management UI HTTP server error: " + err.message);
|
|
13340
|
+
}
|
|
13341
|
+
});
|
|
13342
|
+
logger.info("[Init] Standalone management UI server starting on port " + mgmtPort);
|
|
13343
|
+
} catch (httpErr) {
|
|
13344
|
+
logger.error("[Init] Failed to start management UI server: " + (httpErr instanceof Error ? httpErr.message : String(httpErr)));
|
|
13248
13345
|
}
|
|
13346
|
+
const autoOpenDelay = setTimeout(() => {
|
|
13347
|
+
try {
|
|
13348
|
+
const url = "http://127.0.0.1:" + actualMgmtPort + "/";
|
|
13349
|
+
const cmd = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
13350
|
+
exec(cmd + ' "' + url + '"', (err) => {
|
|
13351
|
+
if (err)
|
|
13352
|
+
logger.debug("[Init] Auto-open browser skipped: " + (err.message || err));
|
|
13353
|
+
else
|
|
13354
|
+
logger.info("[Init] Management UI opened in browser: " + url);
|
|
13355
|
+
});
|
|
13356
|
+
} catch (_e) {
|
|
13357
|
+
logger.debug("[Init] Auto-open browser not available");
|
|
13358
|
+
}
|
|
13359
|
+
}, 3e3);
|
|
13249
13360
|
logger.info("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
13250
|
-
logger.info(" AICQ Plugin activated successfully!");
|
|
13361
|
+
logger.info(" AICQ Plugin v1.2.0 activated successfully!");
|
|
13362
|
+
logger.info(" Management UI: http://127.0.0.1:" + actualMgmtPort + "/");
|
|
13251
13363
|
if (mgmtUiRegistered) {
|
|
13252
|
-
logger.info("
|
|
13253
|
-
logger.info(" Management UI (local): http://127.0.0.1:" + actualMgmtPort + "/plugins/aicq-chat/");
|
|
13254
|
-
} else {
|
|
13255
|
-
logger.info(" Management UI: http://127.0.0.1:" + actualMgmtPort + "/");
|
|
13364
|
+
logger.info(" Gateway UI: /plugins/aicq-chat/");
|
|
13256
13365
|
}
|
|
13257
13366
|
logger.info("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
13258
13367
|
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "aicq-chat",
|
|
3
3
|
"name": "AICQ Encrypted Chat",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"description": "End-to-end encrypted chat plugin supporting AI-AI, Human-AI communication with P2P messaging via Noise-XK handshake, Ed25519/X25519/AES-256-GCM encryption",
|
|
6
6
|
"enabledByDefault": false,
|
|
7
7
|
"channels": ["encrypted-chat"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicq-openclaw-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "AICQ OpenClaw plugin - end-to-end encrypted P2P chat for AI agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,24 +30,26 @@
|
|
|
30
30
|
"openclaw": ">=2026.4.2"
|
|
31
31
|
},
|
|
32
32
|
"peerDependenciesMeta": {
|
|
33
|
-
"openclaw": {
|
|
33
|
+
"openclaw": {
|
|
34
|
+
"optional": true
|
|
35
|
+
}
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
38
|
"ws": "^8.16.0"
|
|
37
39
|
},
|
|
38
40
|
"devDependencies": {
|
|
39
41
|
"@aicq/crypto": "file:../shared/crypto",
|
|
40
|
-
"openclaw": "^2026.4.2",
|
|
41
|
-
"esbuild": "^0.25.0",
|
|
42
|
-
"typescript": "^5.3.3",
|
|
43
42
|
"@types/node": "^20.10.0",
|
|
44
|
-
"@types/ws": "^8.5.10",
|
|
45
|
-
"@types/uuid": "^9.0.7",
|
|
46
43
|
"@types/qrcode": "^1.5.5",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
44
|
+
"@types/uuid": "^9.0.7",
|
|
45
|
+
"@types/ws": "^8.5.10",
|
|
46
|
+
"dotenv": "^16.3.1",
|
|
47
|
+
"esbuild": "^0.25.0",
|
|
48
|
+
"openclaw": "^2026.4.2",
|
|
49
49
|
"qrcode": "^1.5.3",
|
|
50
|
-
"
|
|
50
|
+
"ts-node-dev": "^2.0.0",
|
|
51
|
+
"typescript": "^5.3.3",
|
|
52
|
+
"uuid": "^9.0.0"
|
|
51
53
|
},
|
|
52
54
|
"keywords": [
|
|
53
55
|
"openclaw",
|