openclaw-extension-typex 1.0.13 → 1.0.14

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.md CHANGED
@@ -2,48 +2,19 @@
2
2
 
3
3
  TypeX channel plugin for OpenClaw.
4
4
 
5
- This plugin is modeled after the Feishu channel plugin in `extensions/feishu/`, so you can
6
- use that implementation as a reference when wiring up the real TypeX provider.
7
-
8
- ## Install (local checkout)
5
+ ## Install (local checkout if you've downloaded the source)
9
6
 
10
7
  ```bash
11
- openclaw plugins install ./extensions/typex
8
+ openclaw plugins install path/to/openclaw-extension-typex
12
9
  ```
13
10
 
14
11
  ## Install (npm)
15
12
 
16
13
  ```bash
17
- openclaw plugins install @openclaw/typex
14
+ openclaw plugins install openclaw-extension-typex
18
15
  ```
19
16
 
20
17
  Onboarding: select TypeX and confirm the install prompt to fetch the plugin automatically.
21
18
 
22
- ## Config
23
-
24
- ```json5
25
- {
26
- channels: {
27
- typex: {
28
- accounts: {
29
- default: {
30
- appId: "app_xxx",
31
- appSecret: "xxx",
32
- enabled: true,
33
- },
34
- },
35
- dmPolicy: "pairing",
36
- groupPolicy: "open",
37
- blockStreaming: true,
38
- },
39
- },
40
- }
41
- ```
42
-
43
19
  Once the actual TypeX provider is implemented in the core `openclaw` repo, you can extend
44
- this plugin to wire outbound messaging and gateway/runtime logic, mirroring the Feishu
45
- implementation.
46
-
47
- ## Docs
48
-
49
- https://docs.openclaw.ai/channels/typex
20
+ this plugin to wire outbound messaging and gateway/runtime logic.
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TypeXClient = void 0;
4
4
  exports.getTypeXClient = getTypeXClient;
5
- const TYPEX_DOMAIN = "https://api-coco.typex.im";
6
- // const TYPEX_DOMAIN = "https://api-tx.bossjob.net.cn";
5
+ // const TYPEX_DOMAIN = "https://api-coco.typex.im";
6
+ const TYPEX_DOMAIN = "https://api-tx.bossjob.net.cn";
7
7
  let prompter;
8
8
  class TypeXClient {
9
9
  options;
@@ -83,6 +83,7 @@ class TypeXClient {
83
83
  }
84
84
  }
85
85
  async sendMessage(content, msgType = 0) {
86
+ console.info("msgType: ", msgType);
86
87
  const token = this.accessToken;
87
88
  if (!token) {
88
89
  throw new Error("TypeXClient: Not authenticated.");
@@ -196,7 +197,7 @@ function getTypeXClient(accountId, manualOptions) {
196
197
  token = typexCfg.accounts[accountId].token;
197
198
  }
198
199
  if (!manualOptions?.skipConfigCheck) {
199
- throw new Error("TypeX email not configured yet.");
200
+ throw new Error("TypeX not configured yet.");
200
201
  }
201
202
  return new TypeXClient({
202
203
  token: token,
@@ -1,5 +1,5 @@
1
1
  import type { TypeXClient } from "./client.js";
2
- import type { TypeXMessageEntry } from "./types.js";
2
+ import { type TypeXMessageEntry } from "./types.js";
3
3
  import type { OpenClawConfig } from "openclaw/plugin-sdk";
4
4
  export type ProcessTypeXMessageOptions = {
5
5
  /** Full OpenClaw gateway config (needed for bindings/routing). */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.processTypeXMessage = processTypeXMessage;
4
+ const types_js_1 = require("./types.js");
4
5
  const send_js_1 = require("./send.js");
5
6
  const runtime_js_1 = require("./runtime.js");
6
7
  async function processTypeXMessage(client, payload, appId, options = {}) {
@@ -26,7 +27,6 @@ async function processTypeXMessage(client, payload, appId, options = {}) {
26
27
  // Attempt simple parsing if it looks like JSON? For now assume plain text or handle in future.
27
28
  // Basic logging
28
29
  logger?.info(`Processing TypeX message from ${senderId} in ${chatId}`);
29
- logger?.info(`channel: ${JSON.stringify(channel)}, account: ${accountId}, type: ${typeof accountId}}`);
30
30
  // Build Context for Agent
31
31
  const ctx = {
32
32
  Body: text,
@@ -73,11 +73,10 @@ async function processTypeXMessage(client, payload, appId, options = {}) {
73
73
  channel: "openclaw-extension-typex",
74
74
  accountId,
75
75
  deliver: async (payload) => {
76
- logger?.info(`payload: ${payload}`);
77
76
  const responsePayload = payload;
78
77
  // Handle text response
79
78
  if (responsePayload.text) {
80
- await (0, send_js_1.sendMessageTypeX)(client, responsePayload.text);
79
+ await (0, send_js_1.sendMessageTypeX)(client, responsePayload.text, { msgType: types_js_1.TypeXMessageEnum.richText });
81
80
  }
82
81
  // Handle media if present in response
83
82
  const mediaUrls = responsePayload.mediaUrls?.length
@@ -86,7 +85,7 @@ async function processTypeXMessage(client, payload, appId, options = {}) {
86
85
  ? [responsePayload.mediaUrl]
87
86
  : [];
88
87
  for (const mediaUrl of mediaUrls) {
89
- await (0, send_js_1.sendMessageTypeX)(client, {}, { mediaUrl });
88
+ await (0, send_js_1.sendMessageTypeX)(client, {}, { mediaUrl, msgType: types_js_1.TypeXMessageEnum.richText });
90
89
  }
91
90
  },
92
91
  onError: (err) => {
@@ -42,7 +42,7 @@ async function monitorTypeXProvider(opts) {
42
42
  try {
43
43
  const { account, runtime, abortSignal, log, typexCfg, cfg } = opts;
44
44
  const accountObj = account;
45
- const { email, token, appId } = accountObj.config;
45
+ const { token, appId } = accountObj.config;
46
46
  // log is unknown, cast for usage
47
47
  const logger = log;
48
48
  if (!token) {
@@ -51,13 +51,11 @@ async function monitorTypeXProvider(opts) {
51
51
  }
52
52
  // Initialize Client
53
53
  const client = (0, client_js_1.getTypeXClient)(undefined, { token, skipConfigCheck: true });
54
- logger?.info(`[${accountObj.accountId}] Starting TypeX monitor for ${email || accountObj.accountId}...`);
55
- const dataDir = runtime.dirs?.state || runtime.dirs?.data || "/tmp/typex";
56
- if (dataDir === "/tmp/typex") {
57
- await fs.mkdir(dataDir, { recursive: true }).catch(() => { });
58
- }
59
- const safeId = (email || accountObj.accountId || "default").replace(/[^a-z0-9]/gi, "_");
60
- const stateFile = path.join(dataDir, `.typex_pos_${safeId}.json`);
54
+ logger?.info(`[${accountObj.accountId}] Starting TypeX monitor for ${accountObj.accountId}...`);
55
+ const baseDir = runtime.dirs?.state || runtime.dirs?.data || "/tmp/typex";
56
+ const accountDir = path.join(baseDir, accountObj.accountId);
57
+ await fs.mkdir(accountDir, { recursive: true });
58
+ const stateFile = path.join(accountDir, ".typex_pos.json");
61
59
  let currentPos = 0;
62
60
  try {
63
61
  const data = await fs.readFile(stateFile, "utf-8");
@@ -67,12 +65,27 @@ async function monitorTypeXProvider(opts) {
67
65
  }
68
66
  }
69
67
  catch {
70
- /* Ignore */
68
+ // New-path file not found — try migrating from legacy path (pre-accountId-subdir layout).
69
+ try {
70
+ const safeId = (accountObj.accountId || "default").replace(/[^a-z0-9]/gi, "_");
71
+ const legacyFile = path.join(baseDir, `.typex_pos_${safeId}.json`);
72
+ const legacyData = await fs.readFile(legacyFile, "utf-8");
73
+ const legacyJson = JSON.parse(legacyData);
74
+ if (typeof legacyJson.pos === "number") {
75
+ currentPos = legacyJson.pos;
76
+ // Persist to new location so future starts use the correct pos.
77
+ await fs.writeFile(stateFile, JSON.stringify({ pos: currentPos }));
78
+ await fs.unlink(legacyFile).catch(() => { });
79
+ logger?.info(`[${accountObj.accountId}] Migrated pos (${currentPos}) from legacy state file.`);
80
+ }
81
+ }
82
+ catch {
83
+ /* No legacy file either — start from 0. */
84
+ }
71
85
  }
72
86
  // --- Polling Loop ---
73
87
  while (!abortSignal.aborted) {
74
88
  try {
75
- logger?.info(`[${accountObj.accountId}] Polling TypeX messages (pos: ${currentPos})...`);
76
89
  const messages = await client.fetchMessages(currentPos);
77
90
  logger?.info(`[${accountObj.accountId}] Received ${messages?.length || 0} messages.`);
78
91
  if (messages && messages.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-extension-typex",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "TypeX channel integration for OpenClaw",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",