palz-connector 1.1.7 → 1.1.9
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/openclaw.plugin.json +1 -1
- package/package.json +4 -10
- package/palz-connector.dev.config.json +6 -0
- package/palz-connector.prod.config.json +6 -0
- package/palz-connector.staging.config.json +6 -0
- package/src/bot.ts +9 -6
- package/src/config.ts +24 -5
- package/src/media.ts +1 -9
- package/src/monitor.ts +2 -2
- package/src/types.ts +1 -1
- package/.claude/settings.local.json +0 -8
- package/dist/index.cjs +0 -285002
- package/tsup.config.ts +0 -8
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "palz-connector",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build": "tsup"
|
|
8
|
-
},
|
|
5
|
+
"main": "index.ts",
|
|
9
6
|
"description": "Palz IM 接入 OpenClaw — 模块化架构,基于 OpenClaw Runtime 消息管道",
|
|
10
7
|
"openclaw": {
|
|
11
8
|
"extensions": [
|
|
12
|
-
"
|
|
9
|
+
"./index.ts"
|
|
13
10
|
],
|
|
14
11
|
"channel": {
|
|
15
12
|
"id": "palz-connector",
|
|
@@ -18,11 +15,8 @@
|
|
|
18
15
|
"order": 100
|
|
19
16
|
}
|
|
20
17
|
},
|
|
21
|
-
"
|
|
18
|
+
"dependencies": {
|
|
22
19
|
"ali-oss": "^6.21.0",
|
|
23
|
-
"proxy-agent": "^5.0.0",
|
|
24
|
-
"tsup": "^8.5.1",
|
|
25
|
-
"typescript": "^5.9.3",
|
|
26
20
|
"ws": "^8.18.0"
|
|
27
21
|
}
|
|
28
22
|
}
|
package/src/bot.ts
CHANGED
|
@@ -141,8 +141,8 @@ async function dispatchPalzMessage(params: HandlePalzMessageParams): Promise<voi
|
|
|
141
141
|
log(`${tag}: [STEP 4 输出] mediaList=${JSON.stringify(mediaList.map((m) => ({ path: m.path, contentType: m.contentType })))} mediaPayload=${JSON.stringify(mediaPayload)}`);
|
|
142
142
|
|
|
143
143
|
// STEP 5: 解析路由
|
|
144
|
-
const routeInput = { cfg: "(cfg)", channel: "palz-connector", accountId, peer: { kind: "direct", id: peerId }
|
|
145
|
-
log(`${tag}: [STEP 5/6 路由解析] 输入: ${JSON.stringify(routeInput)}`);
|
|
144
|
+
const routeInput = { cfg: "(cfg)", channel: "palz-connector", accountId, peer: { kind: "direct", id: peerId } };
|
|
145
|
+
log(`${tag}: [STEP 5/6 路由解析] 输入: ${JSON.stringify(routeInput)} agent_id=${msg.agent_id ?? "(auto)"}`);
|
|
146
146
|
const route = core.channel.routing.resolveAgentRoute({
|
|
147
147
|
cfg,
|
|
148
148
|
channel: "palz-connector",
|
|
@@ -150,10 +150,13 @@ async function dispatchPalzMessage(params: HandlePalzMessageParams): Promise<voi
|
|
|
150
150
|
peer: { kind: "direct", id: peerId },
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
// IM 指定 agent_id 时走指定 agent,否则强制走 main
|
|
154
|
+
const effectiveAgentId = msg.agent_id || "main";
|
|
155
|
+
if (route.agentId !== effectiveAgentId) {
|
|
156
|
+
const oldAgentId = route.agentId;
|
|
157
|
+
route.agentId = effectiveAgentId;
|
|
158
|
+
route.sessionKey = route.sessionKey.replace(`agent:${oldAgentId}:`, `agent:${effectiveAgentId}:`);
|
|
159
|
+
log(`${tag}: [STEP 5 覆盖] agentId: ${oldAgentId} -> ${effectiveAgentId}, sessionKey=${route.sessionKey} (${msg.agent_id ? "IM指定" : "默认main"})`);
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
log(`${tag}: [STEP 5 输出] agentId=${route.agentId} sessionKey=${route.sessionKey} accountId=${route.accountId} matchedBy=${route.matchedBy}`);
|
package/src/config.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 配置来源:
|
|
5
5
|
* - botId: 仅从环境变量 botID 读取
|
|
6
|
-
* - streamUrl / apiBaseUrl / sessionTimeout:
|
|
6
|
+
* - streamUrl / apiBaseUrl / sessionTimeout: 从配置文件读取
|
|
7
|
+
* - 若环境变量 HELM_ENV 存在且非空,读取 palz-connector.{HELM_ENV}.config.json
|
|
8
|
+
* - 否则读取默认配置文件 palz-connector.config.json
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
import fs from "fs";
|
|
@@ -12,18 +14,29 @@ import type { PalzConfig, ResolvedPalzAccount } from "./types.js";
|
|
|
12
14
|
|
|
13
15
|
const DEFAULT_ACCOUNT_ID = "__default__";
|
|
14
16
|
const DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1000;
|
|
15
|
-
const
|
|
17
|
+
const DEFAULT_CONFIG_FILENAME = "palz-connector.config.json";
|
|
16
18
|
|
|
17
19
|
let _cachedFileConfig: Record<string, any> | null = null;
|
|
18
20
|
let _configLoggedOnce = false;
|
|
19
21
|
let _configAdapterLoggedOnce = false;
|
|
20
22
|
|
|
23
|
+
function getConfigFilename(): string {
|
|
24
|
+
const helmEnv = process.env.HELM_ENV?.trim();
|
|
25
|
+
if (helmEnv) {
|
|
26
|
+
return `palz-connector.${helmEnv}.config.json`;
|
|
27
|
+
}
|
|
28
|
+
return DEFAULT_CONFIG_FILENAME;
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
function loadConfigFile(): Record<string, any> {
|
|
22
32
|
if (_cachedFileConfig) return _cachedFileConfig;
|
|
23
33
|
|
|
34
|
+
const helmEnv = process.env.HELM_ENV?.trim();
|
|
35
|
+
const configFilename = getConfigFilename();
|
|
36
|
+
|
|
24
37
|
const candidates = [
|
|
25
|
-
path.resolve(process.cwd(),
|
|
26
|
-
path.resolve(__dirname, "..",
|
|
38
|
+
path.resolve(process.cwd(), configFilename),
|
|
39
|
+
path.resolve(__dirname, "..", configFilename),
|
|
27
40
|
];
|
|
28
41
|
|
|
29
42
|
for (const filePath of candidates) {
|
|
@@ -31,7 +44,7 @@ function loadConfigFile(): Record<string, any> {
|
|
|
31
44
|
if (fs.existsSync(filePath)) {
|
|
32
45
|
const raw = fs.readFileSync(filePath, "utf-8");
|
|
33
46
|
_cachedFileConfig = JSON.parse(raw);
|
|
34
|
-
console.log("palz-config: [loadFile] loaded from " + filePath);
|
|
47
|
+
console.log("palz-config: [loadFile] HELM_ENV=" + JSON.stringify(helmEnv || undefined) + " loaded from " + filePath);
|
|
35
48
|
console.log("palz-config: [loadFile] content=" + JSON.stringify(_cachedFileConfig));
|
|
36
49
|
return _cachedFileConfig!;
|
|
37
50
|
}
|
|
@@ -40,6 +53,12 @@ function loadConfigFile(): Record<string, any> {
|
|
|
40
53
|
}
|
|
41
54
|
}
|
|
42
55
|
|
|
56
|
+
if (helmEnv) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
"palz-config: [loadFile] HELM_ENV=\"" + helmEnv + "\" but config file \"" + configFilename + "\" not found, searched: " + candidates.join(", ")
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
43
62
|
console.warn("palz-config: [loadFile] no config file found, searched: " + candidates.join(", "));
|
|
44
63
|
_cachedFileConfig = {};
|
|
45
64
|
return _cachedFileConfig;
|
package/src/media.ts
CHANGED
|
@@ -148,15 +148,7 @@ export async function loadMediaAsOssUrl(
|
|
|
148
148
|
|
|
149
149
|
// 本地文件路径(绝对或相对)→ 上传到 OSS
|
|
150
150
|
const rawPath = mediaUrl.replace(/^MEDIA:/, "");
|
|
151
|
-
|
|
152
|
-
if (path.isAbsolute(rawPath)) {
|
|
153
|
-
filePath = rawPath;
|
|
154
|
-
} else {
|
|
155
|
-
// 相对路径优先在 MEDIA_DIR 下查找(如 ./media/xxx 取 xxx 部分)
|
|
156
|
-
const basename = rawPath.replace(/^\.?\/?media\//, "");
|
|
157
|
-
const mediaFilePath = path.join(MEDIA_DIR, basename);
|
|
158
|
-
filePath = fs.existsSync(mediaFilePath) ? mediaFilePath : path.resolve(rawPath);
|
|
159
|
-
}
|
|
151
|
+
const filePath = path.isAbsolute(rawPath) ? rawPath : path.resolve(rawPath);
|
|
160
152
|
if (fs.existsSync(filePath)) {
|
|
161
153
|
try {
|
|
162
154
|
const ossUrl = await uploadFileToOss(filePath, log);
|
package/src/monitor.ts
CHANGED
|
@@ -38,7 +38,7 @@ export async function monitorPalzProvider(params: MonitorPalzParams): Promise<vo
|
|
|
38
38
|
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
|
39
39
|
let currentWs: WebSocket | null = null;
|
|
40
40
|
let consecutive4002 = 0;
|
|
41
|
-
const MAX_CONSECUTIVE_4002 =
|
|
41
|
+
const MAX_CONSECUTIVE_4002 = 10;
|
|
42
42
|
|
|
43
43
|
const cleanup = () => {
|
|
44
44
|
closed = true;
|
|
@@ -85,7 +85,7 @@ export async function monitorPalzProvider(params: MonitorPalzParams): Promise<vo
|
|
|
85
85
|
ws.ping();
|
|
86
86
|
} catch {}
|
|
87
87
|
}
|
|
88
|
-
},
|
|
88
|
+
}, 30_000);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
ws.on("message", (data: Buffer) => {
|
package/src/types.ts
CHANGED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(grep \"palz-connector\\\\|channel\\\\|tools\" /Users/liuxiang/Downloads/openclaw-2026.3.12/src/agents/*.ts)",
|
|
5
|
-
"Bash(grep -r \"dispatchReplyFromConfig\\\\|senderIsOwner\\\\|CommandAuthorized\" /Users/liuxiang/node_modules/@openclaw/feishu/src/*.ts)"
|
|
6
|
-
]
|
|
7
|
-
}
|
|
8
|
-
}
|