aicq-openclaw-plugin 1.1.0 → 1.2.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/dist/index.js CHANGED
@@ -7771,6 +7771,7 @@ var require_crypto = __commonJS({
7771
7771
  var dotenv = __toESM(require_main(), 1);
7772
7772
  import * as path6 from "path";
7773
7773
  import * as http from "http";
7774
+ import { exec } from "child_process";
7774
7775
  import { definePluginEntry } from "openclaw/plugin-sdk/core";
7775
7776
 
7776
7777
  // dist/config.js
@@ -7826,7 +7827,7 @@ var v4_default = v4;
7826
7827
 
7827
7828
  // dist/config.js
7828
7829
  var _dirname = typeof __dirname !== "undefined" ? __dirname : process.cwd();
7829
- var SERVER_URL = process.env.AICQ_SERVER_URL || "https://aicq.online:61018";
7830
+ var SERVER_URL = process.env.AICQ_SERVER_URL || "https://aicq.online";
7830
7831
  function loadConfig(overrides) {
7831
7832
  let schemaDefaults = {};
7832
7833
  try {
@@ -8382,7 +8383,11 @@ var ServerClient = class {
8382
8383
  * Connect to the server via WebSocket and start heartbeat.
8383
8384
  */
8384
8385
  connectWebSocket() {
8385
- const wsUrl = this.serverUrl.replace(/^http/, "ws") + "/ws";
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();
8386
8391
  this.logger.info("[Server] Connecting WebSocket to " + wsUrl);
8387
8392
  this.ws = new WebSocket(wsUrl);
8388
8393
  this.ws.on("open", () => {
@@ -10187,13 +10192,14 @@ function loadPage(page) {
10187
10192
  async function loadDashboard() {
10188
10193
  const el = $('#dashboard-content');
10189
10194
  html(el, '<div class="loading-mask"><div class="spinner"></div>Loading dashboard...</div>');
10190
- const [status, friends, identity] = await Promise.all([api('/status'), api('/friends'), api('/identity')]);
10195
+ const [status, friends, identity, mgmtUrl] = await Promise.all([api('/status'), api('/friends'), api('/identity'), api('/mgmt-url')]);
10191
10196
  if (status.error) { html(el, '<div class="empty"><div class="icon">\u26A0\uFE0F</div><p>Failed to connect to AICQ plugin</p></div>'); return; }
10192
10197
  const connCls = status.connected ? 'dot-ok' : 'dot-err';
10193
10198
  const connText = status.connected ? 'Connected' : 'Disconnected';
10194
10199
  const friendList = friends.friends || [];
10195
10200
  const aiFriends = friendList.filter(f => f.friendType === 'ai').length;
10196
10201
  const humanFriends = friendList.filter(f => f.friendType !== 'ai').length;
10202
+ const mgmtLink = mgmtUrl?.mgmtUrl || window.location.origin;
10197
10203
 
10198
10204
  html(el, \\\`
10199
10205
  <div class="stats-grid">
@@ -10235,9 +10241,20 @@ async function loadDashboard() {
10235
10241
  <div class="detail-row"><div class="detail-key">Fingerprint</div><div class="detail-val mono">\${escHtml(identity.publicKeyFingerprint)}</div></div>
10236
10242
  <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>
10237
10243
  <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>
10244
+ <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>
10238
10245
  </div>
10239
10246
  </div>
10247
+ <div class="card" style="margin-top:0">
10248
+ <div class="card-header"><div class="card-title">\u{1F5A5}\uFE0F Management UI Access</div></div>
10249
+ <div class="detail-row"><div class="detail-key">Current URL</div><div class="detail-val"><a href="\${escHtml(mgmtLink)}" target="_blank" style="color:var(--info);text-decoration:underline">\${escHtml(mgmtLink)}</a></div></div>
10250
+ <div class="detail-row"><div class="detail-key">Local Access</div><div class="detail-val"><a href="http://127.0.0.1:6109" target="_blank" style="color:var(--info);text-decoration:underline">http://127.0.0.1:6109</a> <button class="btn btn-sm btn-primary" onclick="window.open('http://127.0.0.1:6109','_blank')" style="margin-left:8px">\u{1F517} Open</button></div></div>
10251
+ <div class="detail-row"><div class="detail-key">Gateway Path</div><div class="detail-val mono">/plugins/aicq-chat/</div></div>
10252
+ </div>
10240
10253
  \\\`);
10254
+
10255
+ // Also set the mgmt-url-display in settings
10256
+ const mgmtUrlEl = document.getElementById('mgmt-url-display');
10257
+ if (mgmtUrlEl) mgmtUrlEl.textContent = window.location.href;
10241
10258
  }
10242
10259
 
10243
10260
  function renderMiniFriendList(friends) {
@@ -10801,7 +10818,7 @@ function renderSettingsConnection() {
10801
10818
  <div style="flex:1">
10802
10819
  <div class="input-prefix">
10803
10820
  <span class="prefix">\u{1F310}</span>
10804
- <input type="url" id="set-server-url" value="\${escHtml(s.serverUrl || '')}" placeholder="https://aicq.online:61018">
10821
+ <input type="url" id="set-server-url" value="\${escHtml(s.serverUrl || '')}" placeholder="https://aicq.online">
10805
10822
  </div>
10806
10823
  <div class="hint">The HTTPS URL of the AICQ relay server. WebSocket path /ws is auto-appended.</div>
10807
10824
  </div>
@@ -10843,7 +10860,8 @@ function renderSettingsConnection() {
10843
10860
  <div class="card">
10844
10861
  <div class="card-header"><div class="card-title">\u{1F4C1} Config File</div></div>
10845
10862
  <div class="detail-row"><div class="detail-key">Source</div><div class="detail-val mono" style="cursor:pointer" onclick="copyText('\${escHtml(s.configPath || '')}')">\${escHtml(s.configPath || 'Not found')} \u{1F4CB}</div></div>
10846
- <div class="detail-row"><div class="detail-key">Plugin Version</div><div class="detail-val">1.0.4</div></div>
10863
+ <div class="detail-row"><div class="detail-key">Plugin Version</div><div class="detail-val">1.1.1</div></div>
10864
+ <div class="detail-row"><div class="detail-key">Management UI</div><div class="detail-val" id="mgmt-url-display" style="cursor:pointer" onclick="copyText(document.getElementById('mgmt-url-display')?.textContent || '')"></div></div>
10847
10865
  <div class="detail-row"><div class="detail-key">Uptime</div><div class="detail-val">\${formatUptime(s.uptimeSeconds)}</div></div>
10848
10866
  </div>
10849
10867
  \\\`);
@@ -12353,7 +12371,7 @@ function createManagementHandler(ctx) {
12353
12371
  const pluginSection = pluginsSection?.["aicq-chat"];
12354
12372
  return json(res, {
12355
12373
  exportDate: (/* @__PURE__ */ new Date()).toISOString(),
12356
- pluginVersion: "1.0.4",
12374
+ pluginVersion: "1.2.0",
12357
12375
  settings: pluginSection || {},
12358
12376
  fullConfig: result.config
12359
12377
  });
@@ -12451,6 +12469,16 @@ function createManagementHandler(ctx) {
12451
12469
  return json(res, { success: false, message: "Write failed: " + msg }, 500);
12452
12470
  }
12453
12471
  }
12472
+ if (apiPath === "/mgmt-url" && method === "GET") {
12473
+ const host = req.headers?.host || "127.0.0.1:6109";
12474
+ const protocol = req.headers?.["x-forwarded-proto"] || "http";
12475
+ const mgmtUrl = protocol + "://" + host;
12476
+ return json(res, {
12477
+ mgmtUrl,
12478
+ standaloneUrl: "http://127.0.0.1:6109",
12479
+ gatewayPath: "/plugins/aicq-chat/"
12480
+ });
12481
+ }
12454
12482
  if (apiPath === "/agents" && method === "POST") {
12455
12483
  const body = await readBody(req);
12456
12484
  const agent = body.agent;
@@ -12592,6 +12620,12 @@ function createManagementHandler(ctx) {
12592
12620
  logger.info("[API] Model config cleared for provider: " + providerId);
12593
12621
  return json(res, { success: true, message: "Model configuration cleared for " + provider.name });
12594
12622
  }
12623
+ if (apiPath === "/version" && method === "GET") {
12624
+ return json(res, {
12625
+ version: "1.2.0",
12626
+ name: "AICQ Encrypted Chat"
12627
+ });
12628
+ }
12595
12629
  res.writeHead(404, { "Content-Type": "application/json" });
12596
12630
  res.end(JSON.stringify({ error: "Not found: " + apiPath }));
12597
12631
  } catch (err) {
@@ -12649,7 +12683,7 @@ var plugin = definePluginEntry({
12649
12683
  debug: (msg, ...args) => ocLog.debug?.(msg, ...args) ?? console.log("[aicq-chat DEBUG]", msg, ...args)
12650
12684
  };
12651
12685
  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");
12652
- logger.info(" AICQ Encrypted Chat Plugin v1.0.0");
12686
+ logger.info(" AICQ Encrypted Chat Plugin v1.2.0");
12653
12687
  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");
12654
12688
  const pluginCfg = api.pluginConfig ?? {};
12655
12689
  const config2 = loadConfig({
@@ -13157,9 +13191,10 @@ var plugin = definePluginEntry({
13157
13191
  });
13158
13192
  const apiKeys = Object.keys(api).filter((k) => typeof api[k] === "function");
13159
13193
  logger.info("[Init] Available API methods: " + apiKeys.join(", "));
13160
- let mgmtPort = 6109;
13194
+ let mgmtPort = parseInt(process.env.AICQ_MGMT_PORT || "6109", 10);
13195
+ let actualMgmtPort = mgmtPort;
13161
13196
  let mgmtUiRegistered = false;
13162
- if (api.registerHttpRoute) {
13197
+ if (typeof api.registerHttpRoute === "function") {
13163
13198
  try {
13164
13199
  api.registerHttpRoute({
13165
13200
  path: "/plugins/aicq-chat",
@@ -13167,49 +13202,79 @@ var plugin = definePluginEntry({
13167
13202
  match: "prefix",
13168
13203
  handler: managementHandler
13169
13204
  });
13170
- logger.info("[Init] Management UI registered via gateway at /plugins/aicq-chat/");
13205
+ logger.info("[Init] Management UI registered via registerHttpRoute at /plugins/aicq-chat/");
13171
13206
  mgmtUiRegistered = true;
13172
13207
  } catch (routeErr) {
13173
- logger.warn("[Init] Gateway route registration failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
13208
+ logger.warn("[Init] registerHttpRoute failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
13174
13209
  }
13175
13210
  }
13176
- if (!mgmtUiRegistered) {
13211
+ if (!mgmtUiRegistered && typeof api.registerRoute === "function") {
13177
13212
  try {
13178
- mgmtPort = parseInt(process.env.AICQ_MGMT_PORT || "6109", 10);
13179
- const mgmtServer = http.createServer((req, res) => {
13180
- managementHandler(req, res).catch((err) => {
13181
- logger.error("[HTTP] Management server error: " + (err instanceof Error ? err.message : err));
13182
- if (!res.headersSent) {
13183
- res.writeHead(500, { "Content-Type": "text/plain" });
13184
- }
13185
- res.end("Internal Server Error");
13186
- });
13187
- });
13188
- mgmtServer.listen(mgmtPort, "127.0.0.1", () => {
13189
- logger.info("[Init] Management UI HTTP server running at http://127.0.0.1:" + mgmtPort + "/");
13190
- });
13191
- mgmtServer.on("error", (err) => {
13192
- if (err.code === "EADDRINUSE") {
13193
- logger.warn("[Init] Management UI port " + mgmtPort + " already in use, trying " + (mgmtPort + 1));
13194
- mgmtServer.close();
13195
- mgmtServer.listen(mgmtPort + 1, "127.0.0.1", () => {
13196
- logger.info("[Init] Management UI HTTP server running at http://127.0.0.1:" + (mgmtPort + 1) + "/");
13197
- });
13198
- } else {
13199
- logger.error("[Init] Management UI HTTP server error: " + err.message);
13213
+ api.registerRoute("/plugins/aicq-chat", managementHandler);
13214
+ logger.info("[Init] Management UI registered via registerRoute at /plugins/aicq-chat/");
13215
+ mgmtUiRegistered = true;
13216
+ } catch (routeErr) {
13217
+ logger.warn("[Init] registerRoute failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
13218
+ }
13219
+ }
13220
+ if (!mgmtUiRegistered && typeof api.addRoute === "function") {
13221
+ try {
13222
+ api.addRoute("/plugins/aicq-chat", managementHandler);
13223
+ logger.info("[Init] Management UI registered via addRoute at /plugins/aicq-chat/");
13224
+ mgmtUiRegistered = true;
13225
+ } catch (routeErr) {
13226
+ logger.warn("[Init] addRoute failed: " + (routeErr instanceof Error ? routeErr.message : String(routeErr)));
13227
+ }
13228
+ }
13229
+ try {
13230
+ actualMgmtPort = mgmtPort;
13231
+ const mgmtServer = http.createServer((req, res) => {
13232
+ managementHandler(req, res).catch((err) => {
13233
+ logger.error("[HTTP] Management server error: " + (err instanceof Error ? err.message : err));
13234
+ if (!res.headersSent) {
13235
+ res.writeHead(500, { "Content-Type": "text/plain" });
13200
13236
  }
13237
+ res.end("Internal Server Error");
13201
13238
  });
13202
- logger.info("[Init] Standalone management UI server starting on port " + mgmtPort);
13203
- } catch (httpErr) {
13204
- logger.error("[Init] Failed to start management UI server: " + (httpErr instanceof Error ? httpErr.message : String(httpErr)));
13205
- }
13239
+ });
13240
+ mgmtServer.listen(mgmtPort, "127.0.0.1", () => {
13241
+ logger.info("[Init] Management UI HTTP server running at http://127.0.0.1:" + mgmtPort + "/");
13242
+ });
13243
+ mgmtServer.on("error", (err) => {
13244
+ if (err.code === "EADDRINUSE") {
13245
+ actualMgmtPort = mgmtPort + 1;
13246
+ logger.warn("[Init] Management UI port " + mgmtPort + " in use, trying " + actualMgmtPort);
13247
+ mgmtServer.close();
13248
+ mgmtServer.listen(actualMgmtPort, "127.0.0.1", () => {
13249
+ logger.info("[Init] Management UI HTTP server running at http://127.0.0.1:" + actualMgmtPort + "/");
13250
+ });
13251
+ } else {
13252
+ logger.error("[Init] Management UI HTTP server error: " + err.message);
13253
+ }
13254
+ });
13255
+ logger.info("[Init] Standalone management UI server starting on port " + mgmtPort);
13256
+ } catch (httpErr) {
13257
+ logger.error("[Init] Failed to start management UI server: " + (httpErr instanceof Error ? httpErr.message : String(httpErr)));
13206
13258
  }
13259
+ const autoOpenDelay = setTimeout(() => {
13260
+ try {
13261
+ const url = "http://127.0.0.1:" + actualMgmtPort + "/";
13262
+ const cmd = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
13263
+ exec(cmd + ' "' + url + '"', (err) => {
13264
+ if (err)
13265
+ logger.debug("[Init] Auto-open browser skipped: " + (err.message || err));
13266
+ else
13267
+ logger.info("[Init] Management UI opened in browser: " + url);
13268
+ });
13269
+ } catch (_e) {
13270
+ logger.debug("[Init] Auto-open browser not available");
13271
+ }
13272
+ }, 3e3);
13207
13273
  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");
13208
- logger.info(" AICQ Plugin activated successfully!");
13274
+ logger.info(" AICQ Plugin v1.2.0 activated successfully!");
13275
+ logger.info(" Management UI: http://127.0.0.1:" + actualMgmtPort + "/");
13209
13276
  if (mgmtUiRegistered) {
13210
- logger.info(" Management UI: via gateway /plugins/aicq-chat/");
13211
- } else {
13212
- logger.info(" Management UI: http://127.0.0.1:" + mgmtPort + "/");
13277
+ logger.info(" Gateway UI: /plugins/aicq-chat/");
13213
13278
  }
13214
13279
  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");
13215
13280
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "aicq-chat",
3
3
  "name": "AICQ Encrypted Chat",
4
- "version": "1.1.0",
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"],
@@ -15,14 +15,14 @@
15
15
  "properties": {
16
16
  "serverUrl": {
17
17
  "type": "string",
18
- "default": "https://aicq.online:61018",
19
- "description": "AICQ relay server URL (HTTPS, WebSocket path /ws is auto-appended)",
18
+ "default": "https://aicq.online",
19
+ "description": "AICQ relay server URL (HTTPS, WebSocket path /ws is auto-appended, default port 443)",
20
20
  "uiHints": {
21
21
  "label": "Server URL",
22
- "placeholder": "https://aicq.online:61018",
22
+ "placeholder": "https://aicq.online",
23
23
  "order": 1,
24
24
  "group": "Connection",
25
- "helpText": "The HTTPS URL of the AICQ relay server. WebSocket path /ws is auto-appended."
25
+ "helpText": "The HTTPS URL of the AICQ relay server (port 443). WebSocket path /ws is auto-appended."
26
26
  }
27
27
  },
28
28
  "agentId": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicq-openclaw-plugin",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
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",