@yahaha-studio/kichi-forwarder 0.0.1-alpha.41 → 0.0.1-alpha.43

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/index.ts CHANGED
@@ -68,6 +68,8 @@ const LEGACY_SKILLS_CONFIG_PATH = path.join(KICHI_WORLD_DIR, "skills-config.json
68
68
  const IDENTITY_PATH = path.join(KICHI_WORLD_DIR, "identity.json");
69
69
  const RUNTIME_ALBUM_CONFIG_PATH = path.join(KICHI_WORLD_DIR, "album-config.json");
70
70
  const MAX_NOTEBOARD_TEXT_LENGTH = 200;
71
+ const MAX_MESSAGE_RECEIVED_PREVIEW_WIDTH = 20;
72
+ const MESSAGE_RECEIVED_ELLIPSIS = "...";
71
73
  const BUNDLED_ALBUM_CONFIG_PATH = new URL("./config/album-config.json", import.meta.url);
72
74
  let cachedConfig: KichiRuntimeConfig | null = null;
73
75
  let cachedConfigMtime = 0;
@@ -241,11 +243,59 @@ function syncFixedStatus(status: ActionResult): void {
241
243
  });
242
244
  }
243
245
 
246
+ function splitGraphemes(text: string): string[] {
247
+ if (typeof Intl !== "undefined" && "Segmenter" in Intl) {
248
+ const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
249
+ return Array.from(segmenter.segment(text), (item) => item.segment);
250
+ }
251
+ return Array.from(text);
252
+ }
253
+
254
+ function getDisplayWidth(segment: string): number {
255
+ if (/[\u1100-\u115F\u2329\u232A\u2E80-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE6F\uFF01-\uFF60\uFFE0-\uFFE6]/u.test(segment)) {
256
+ return 2;
257
+ }
258
+ if (/\p{Extended_Pictographic}/u.test(segment)) {
259
+ return 2;
260
+ }
261
+ return 1;
262
+ }
263
+
264
+ function getTextDisplayWidth(text: string): number {
265
+ return splitGraphemes(text).reduce((total, segment) => total + getDisplayWidth(segment), 0);
266
+ }
267
+
268
+ function truncateByDisplayWidth(text: string, maxWidth: number): string {
269
+ const trimmed = text.trim();
270
+ if (!trimmed) {
271
+ return "";
272
+ }
273
+
274
+ const segments = splitGraphemes(trimmed);
275
+ const ellipsisWidth = getTextDisplayWidth(MESSAGE_RECEIVED_ELLIPSIS);
276
+ let currentWidth = 0;
277
+ let result = "";
278
+
279
+ for (const segment of segments) {
280
+ const nextWidth = getDisplayWidth(segment);
281
+ if (currentWidth + nextWidth > maxWidth) {
282
+ return result.trimEnd() + MESSAGE_RECEIVED_ELLIPSIS;
283
+ }
284
+ if (currentWidth + nextWidth + ellipsisWidth > maxWidth && result) {
285
+ return result.trimEnd() + MESSAGE_RECEIVED_ELLIPSIS;
286
+ }
287
+ result += segment;
288
+ currentWidth += nextWidth;
289
+ }
290
+
291
+ return result;
292
+ }
293
+
244
294
  async function handleMessageReceivedHook(content: string): Promise<void> {
245
295
  if (!service?.hasValidIdentity() || !service?.isConnected()) {
246
296
  return;
247
297
  }
248
- const trimmed = content.length > 7 ? content.slice(0, 7) + "..." : content;
298
+ const trimmed = truncateByDisplayWidth(content, MAX_MESSAGE_RECEIVED_PREVIEW_WIDTH);
249
299
  service.sendHookNotify("message_received", `"${trimmed}"`);
250
300
  }
251
301
 
@@ -8,18 +8,7 @@
8
8
  "configSchema": {
9
9
  "type": "object",
10
10
  "additionalProperties": false,
11
- "properties": {
12
- "wsUrl": {
13
- "type": "string"
14
- },
15
- "enabled": {
16
- "type": "boolean",
17
- "default": true
18
- }
19
- }
11
+ "properties": {}
20
12
  },
21
- "uiHints": {
22
- "wsUrl": { "label": "WebSocket URL", "placeholder": "ws://host:port/ws/openclaw" },
23
- "enabled": { "label": "Enable Plugin" }
24
- }
13
+ "uiHints": {}
25
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yahaha-studio/kichi-forwarder",
3
- "version": "0.0.1-alpha.41",
3
+ "version": "0.0.1-alpha.43",
4
4
  "description": "Forward OpenClaw agent events to external WebSocket server for visualization",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/src/config.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { KichiForwarderConfig } from "./types.js";
2
2
 
3
- export function parse(value: unknown): KichiForwarderConfig {
4
- const config = (value ?? {}) as Partial<KichiForwarderConfig>;
3
+ const FIXED_WS_URL = "ws://43.106.148.251:48870/ws/openclaw";
4
+
5
+ export function parse(_value: unknown): KichiForwarderConfig {
5
6
  return {
6
- wsUrl: config.wsUrl ?? "ws://43.106.148.251:48870/ws/openclaw",
7
- enabled: config.enabled ?? true,
7
+ wsUrl: FIXED_WS_URL,
8
8
  };
9
9
  }
package/src/service.ts CHANGED
@@ -67,7 +67,6 @@ export class KichiForwarderService {
67
67
  constructor(private config: KichiForwarderConfig, private logger: Logger) {}
68
68
 
69
69
  async start(): Promise<void> {
70
- if (!this.config.enabled) return;
71
70
  this.identity = this.loadIdentity();
72
71
  this.stopped = false;
73
72
  this.connect();
@@ -460,7 +459,7 @@ export class KichiForwarderService {
460
459
  };
461
460
  }
462
461
 
463
- if (this.stopped || !this.config.enabled) {
462
+ if (this.stopped) {
464
463
  return {
465
464
  accepted: false,
466
465
  mode: "unavailable",
@@ -483,7 +482,6 @@ export class KichiForwarderService {
483
482
 
484
483
  getConnectionStatus(): KichiConnectionStatus {
485
484
  return {
486
- enabled: this.config.enabled,
487
485
  wsUrl: this.config.wsUrl,
488
486
  connected: this.isConnected(),
489
487
  websocketState: this.getWebsocketState(),
package/src/types.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export type KichiForwarderConfig = {
2
2
  wsUrl: string;
3
- enabled: boolean;
4
3
  };
5
4
 
6
5
  export type PoseType = "stand" | "sit" | "lay" | "floor";
@@ -38,7 +37,6 @@ export type KichiIdentity = {
38
37
  };
39
38
 
40
39
  export type KichiConnectionStatus = {
41
- enabled: boolean;
42
40
  wsUrl: string;
43
41
  connected: boolean;
44
42
  websocketState: "idle" | "connecting" | "open" | "closing" | "closed";