openclaw-clawtown-plugin 1.1.30 → 1.1.31

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/local-identity.js CHANGED
@@ -4,6 +4,11 @@ import path from "path";
4
4
 
5
5
  const DEFAULT_OPENCLAW_STATE_DIR = path.join(os.homedir(), ".openclaw");
6
6
  const FORUM_OPENCLAW_HOME_DIR = path.join(os.homedir(), ".openclaw-forum");
7
+ const CANONICAL_FORUM_SERVER_URL = "https://clawtown.uk";
8
+ const LEGACY_FORUM_SERVER_HOSTS = new Map([
9
+ ["clawtown.online", "clawtown.uk"],
10
+ ]);
11
+ const LOCAL_FORUM_SERVER_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
7
12
  const SKILL_FILE_RE = /\.(json|ya?ml)$/i;
8
13
  const SKILL_NAME_ALIASES = new Map([
9
14
  ["agent-browser", "网页自动化"],
@@ -22,20 +27,37 @@ export function readLocalReporterConfig() {
22
27
  for (const filePath of reporterConfigCandidates()) {
23
28
  try {
24
29
  if (!fs.existsSync(filePath)) continue;
25
- const parsed = JSON.parse(readTextAuto(filePath));
26
- if (!parsed?.userId || !parsed?.apiKey || !parsed?.serverUrl) continue;
27
- return {
28
- userId: String(parsed.userId),
29
- apiKey: String(parsed.apiKey),
30
- serverUrl: String(parsed.serverUrl),
31
- openclawAgentId: parsed.openclawAgentId ? String(parsed.openclawAgentId) : undefined,
32
- openclawSessionId: parsed.openclawSessionId ? String(parsed.openclawSessionId) : undefined,
33
- };
30
+ const normalized = normalizeReporterLocalConfig(JSON.parse(readTextAuto(filePath)));
31
+ if (!normalized) continue;
32
+ persistReporterLocalConfigIfChanged(filePath, normalized);
33
+ return normalized;
34
34
  } catch {}
35
35
  }
36
36
  return null;
37
37
  }
38
38
 
39
+ export function normalizeForumServerUrl(raw, fallback = CANONICAL_FORUM_SERVER_URL) {
40
+ const input = String(raw ?? "").trim() || String(fallback ?? "").trim();
41
+ if (!input) return "";
42
+ try {
43
+ const url = new URL(input);
44
+ const host = url.hostname.toLowerCase();
45
+ const migratedHost = LEGACY_FORUM_SERVER_HOSTS.get(host);
46
+ if (migratedHost) {
47
+ url.protocol = "https:";
48
+ url.hostname = migratedHost;
49
+ if (url.port === "80" || url.port === "443") {
50
+ url.port = "";
51
+ }
52
+ } else if (!LOCAL_FORUM_SERVER_HOSTS.has(host) && url.protocol === "http:") {
53
+ url.protocol = "https:";
54
+ }
55
+ return `${url.protocol}//${url.host}`;
56
+ } catch {
57
+ return input;
58
+ }
59
+ }
60
+
39
61
  export function readOpenClawIdentity(baseDir = process.env.OCT_OPENCLAW_PATH ?? process.env.OPENCLAW_HOME ?? DEFAULT_OPENCLAW_STATE_DIR) {
40
62
  try {
41
63
  const configBaseDir = normalizeOpenClawConfigBaseDir(baseDir);
@@ -74,6 +96,28 @@ function readOpenClawConfig(baseDir) {
74
96
  return parseJsonWithComments(readTextAuto(target));
75
97
  }
76
98
 
99
+ function normalizeReporterLocalConfig(parsed) {
100
+ if (!parsed?.userId || !parsed?.apiKey || !parsed?.serverUrl) return null;
101
+ return {
102
+ userId: String(parsed.userId),
103
+ apiKey: String(parsed.apiKey),
104
+ serverUrl: normalizeForumServerUrl(parsed.serverUrl),
105
+ openclawAgentId: parsed.openclawAgentId ? String(parsed.openclawAgentId) : undefined,
106
+ openclawSessionId: parsed.openclawSessionId ? String(parsed.openclawSessionId) : undefined,
107
+ };
108
+ }
109
+
110
+ function persistReporterLocalConfigIfChanged(filePath, payload) {
111
+ const nextRaw = `${JSON.stringify(payload, null, 2)}\n`;
112
+ try {
113
+ const currentRaw = fs.existsSync(filePath) ? readTextAuto(filePath) : "";
114
+ if (currentRaw === nextRaw) return;
115
+ } catch {}
116
+ try {
117
+ fs.writeFileSync(filePath, nextRaw, "utf-8");
118
+ } catch {}
119
+ }
120
+
77
121
  function reporterConfigCandidates() {
78
122
  const out = [];
79
123
  const explicitHome = String(process.env.OPENCLAW_HOME ?? "").trim();
@@ -2,7 +2,7 @@
2
2
  "id": "openclaw-clawtown-plugin",
3
3
  "name": "OpenClaw Clawtown Plugin",
4
4
  "description": "Connects an OpenClaw agent to OpenClaw Forum and reports forum actions",
5
- "version": "1.1.30",
5
+ "version": "1.1.31",
6
6
  "main": "./index.ts",
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-clawtown-plugin",
3
- "version": "1.1.30",
3
+ "version": "1.1.31",
4
4
  "description": "Forum reporter plugin for OpenClaw Forum (Clawtown)",
5
5
  "license": "MIT",
6
6
  "main": "index.ts",
package/reporter.ts CHANGED
@@ -6,7 +6,7 @@ import path from "node:path";
6
6
  import os from "node:os";
7
7
  import crypto from "node:crypto";
8
8
  import { fileURLToPath } from "node:url";
9
- import { readLocalReporterConfig, readOpenClawIdentity } from "./local-identity.js";
9
+ import { normalizeForumServerUrl, readLocalReporterConfig, readOpenClawIdentity } from "./local-identity.js";
10
10
 
11
11
  const execFileAsync = promisify(execFile);
12
12
 
@@ -41,11 +41,11 @@ const PLUGIN_ID = "openclaw-clawtown-plugin";
41
41
  const LEGACY_PLUGIN_ID = "forum-reporter";
42
42
  const REPORTER_CONFIG_BASENAME = "forum-reporter.json";
43
43
  const REPORTER_INSTALLATION_BASENAME = "forum-reporter-installation.json";
44
- const DEFAULT_FORUM_SERVER_URL = String(
44
+ const DEFAULT_FORUM_SERVER_URL = normalizeForumServerUrl(String(
45
45
  process.env.OPENCLAW_FORUM_SERVER_URL
46
46
  ?? process.env.OCT_SERVER_URL
47
47
  ?? "https://clawtown.uk",
48
- ).trim() || "https://clawtown.uk";
48
+ ).trim(), "https://clawtown.uk") || "https://clawtown.uk";
49
49
 
50
50
  const V2_MANIFESTO = [
51
51
  "你现在是「机器人共答社区 V2」的一位居民。",
@@ -71,18 +71,7 @@ function isCurrentPluginUninstallInvocation(argv = process.argv.slice(2)) {
71
71
  }
72
72
 
73
73
  function normalizeServerUrl(raw: string) {
74
- const input = String(raw ?? "").trim() || "http://127.0.0.1:3679";
75
- try {
76
- const url = new URL(input);
77
- const host = url.hostname.toLowerCase();
78
- const isLocal = host === "localhost" || host === "127.0.0.1" || host === "::1";
79
- if (!isLocal && url.protocol === "http:") {
80
- url.protocol = "https:";
81
- }
82
- return `${url.protocol}//${url.host}`;
83
- } catch {
84
- return input;
85
- }
74
+ return normalizeForumServerUrl(raw, "http://127.0.0.1:3679") || "http://127.0.0.1:3679";
86
75
  }
87
76
 
88
77
  type AgentActionKind = "answer_question" | "vote_question" | "mine_task";
@@ -1018,6 +1007,17 @@ class Reporter {
1018
1007
  }
1019
1008
  this.lastProfileSyncAt = Date.now();
1020
1009
  const payload = await res.json().catch(() => ({} as any));
1010
+ const nextServerUrl = normalizeServerUrl(String(payload?.serverUrl ?? this.serverUrl).trim() || this.serverUrl);
1011
+ if (nextServerUrl !== this.serverUrl) {
1012
+ this.serverUrl = nextServerUrl;
1013
+ writeReporterLocalConfig(resolveStateDirForConfiguredHome(this.forcedOpenClawHome), {
1014
+ userId: this.userId,
1015
+ apiKey: this.apiKey,
1016
+ serverUrl: this.serverUrl,
1017
+ openclawAgentId: this.openclawAgentId,
1018
+ openclawSessionId: this.openclawSessionId,
1019
+ });
1020
+ }
1021
1021
  const displayName = String(payload?.displayName ?? "").trim() || this.userId;
1022
1022
  const isBound = Boolean(payload?.isBound);
1023
1023
  let pairCode = String(payload?.pairCode ?? "").trim();
@@ -1521,7 +1521,11 @@ function writeReporterLocalConfig(
1521
1521
  },
1522
1522
  ) {
1523
1523
  const filePath = path.join(stateDir, REPORTER_CONFIG_BASENAME);
1524
- const nextRaw = `${JSON.stringify(input, null, 2)}\n`;
1524
+ const normalizedInput = {
1525
+ ...input,
1526
+ serverUrl: normalizeServerUrl(input.serverUrl),
1527
+ };
1528
+ const nextRaw = `${JSON.stringify(normalizedInput, null, 2)}\n`;
1525
1529
  try {
1526
1530
  const current = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf-8") : "";
1527
1531
  if (current === nextRaw) return filePath;