palz-connector 1.7.3-beta.1 → 1.7.4-beta.2

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "palz-connector",
3
3
  "name": "Palz Connector Channel",
4
- "version": "1.7.3-beta.1",
4
+ "version": "1.7.4-beta.2",
5
5
  "description": "Palz IM 接入 OpenClaw",
6
6
  "channels": [
7
7
  "palz-connector"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "palz-connector",
3
- "version": "1.7.3-beta.1",
3
+ "version": "1.7.4-beta.2",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "description": "Palz IM 接入 OpenClaw — 模块化架构,基于 OpenClaw Runtime 消息管道",
@@ -21,6 +21,8 @@
21
21
  "id": "palz-connector",
22
22
  "label": "Palz Connector",
23
23
  "selectionLabel": "Palz Connector (IM)",
24
+ "docsPath": "/channels/palz-connector",
25
+ "docsLabel": "Palz Connector",
24
26
  "order": 100
25
27
  }
26
28
  },
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "enabled": true,
3
- "streamUrl": "ws://14.103.148.99:8090/ws/bot",
4
- "apiBaseUrl": "http://14.103.148.99:8090/api",
3
+ "streamUrl": "ws://claw-server:8787/ws/bot",
4
+ "apiBaseUrl": "http://claw-server:8787/api",
5
5
  "clawGatewayUrl": "http://claw-gateway:8080",
6
- "activityReportEnabled": false,
6
+ "activityReportEnabled": true,
7
7
  "sessionTimeout": 1800000,
8
8
  "groupContextCache": false,
9
9
  "showProcess": true,
10
- "kbEngineUrl": "http://127.0.0.1:8070",
10
+ "kbEngineUrl": "http://uniclaw-kb-engine:8070",
11
11
  "controlPort": 8008
12
12
  }
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "enabled": true,
3
- "streamUrl": "ws://claw-server:8787/ws/bot",
4
- "apiBaseUrl": "http://claw-server:8787/api",
3
+ "streamUrl": "ws://claw-server:8787/im-server/ws/bot",
4
+ "apiBaseUrl": "http://claw-server:8787/im-server/api",
5
5
  "clawGatewayUrl": "http://claw-gateway:8080",
6
6
  "activityReportEnabled": true,
7
7
  "sessionTimeout": 1800000,
8
8
  "groupContextCache": false,
9
9
  "showProcess": true,
10
+ "processLanguage": "en",
10
11
  "kbEngineUrl": "http://uniclaw-kb-engine:8070",
11
12
  "controlPort": 8008
12
13
  }
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "enabled": true,
3
- "streamUrl": "ws://claw-server:8787/ws/bot",
4
- "apiBaseUrl": "http://claw-server:8787/api",
3
+ "streamUrl": "ws://claw-server:8787/im-server/ws/bot",
4
+ "apiBaseUrl": "http://claw-server:8787/im-server/api",
5
5
  "clawGatewayUrl": "http://claw-gateway:8080",
6
6
  "activityReportEnabled": true,
7
7
  "sessionTimeout": 1800000,
8
8
  "groupContextCache": false,
9
9
  "showProcess": true,
10
+ "processLanguage": "en",
10
11
  "kbEngineUrl": "http://uniclaw-kb-engine:8070",
11
12
  "controlPort": 8008
12
13
  }
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "enabled": true,
3
- "streamUrl": "ws://claw-server:8787/ws/bot",
4
- "apiBaseUrl": "http://claw-server:8787/api",
3
+ "streamUrl": "ws://claw-server:8787/im-server/ws/bot",
4
+ "apiBaseUrl": "http://claw-server:8787/im-server/api",
5
5
  "clawGatewayUrl": "http://claw-gateway:8080",
6
6
  "activityReportEnabled": true,
7
7
  "sessionTimeout": 1800000,
8
8
  "groupContextCache": false,
9
9
  "showProcess": true,
10
+ "processLanguage": "en",
10
11
  "kbEngineUrl": "http://uniclaw-kb-engine:8070",
11
12
  "controlPort": 8008
12
13
  }
package/src/bot.js CHANGED
@@ -228,19 +228,6 @@ function buildUniclawEventContext(params) {
228
228
  },
229
229
  };
230
230
  }
231
- function buildFileSharingSystemPrompt() {
232
- return [
233
- "## File Sharing",
234
- "When you create or generate a file that the user requested (documents, images, presentations, spreadsheets, archives, etc.), you MUST include a MEDIA: token in your reply so the file gets delivered to the user.",
235
- "Always write your normal text reply first (description, summary, or explanation), then append the MEDIA: line(s) at the end.",
236
- "Format: place `MEDIA: <absolute-file-path>` on its own line at the end of your reply.",
237
- "Example:",
238
- " Here is the presentation you requested. It includes 5 slides covering the main topics.",
239
- " MEDIA: /path/to/workspace/output.pptx",
240
- "Without the MEDIA: line, the user only sees text and cannot download the file.",
241
- "Multiple files: one MEDIA: line per file.",
242
- ].join("\n");
243
- }
244
231
  function buildKbIngestNoticeMessage(results) {
245
232
  const lines = results.map((result, index) => {
246
233
  const details = [
@@ -391,10 +378,13 @@ async function _handlePalzMessageInner(params) {
391
378
  if (!suppressAck) {
392
379
  try {
393
380
  log(`${tag}: [ACK] 发送确认消息 conv=${msg.conversation_id} sender=${msg.sender_id}`);
381
+ const ackContent = account.config.processLanguage === "en"
382
+ ? "Got it, thinking…"
383
+ : "收到,正在思考中…";
394
384
  await sendToPalzIM({
395
385
  config: account.config,
396
386
  conversationId: msg.conversation_id,
397
- content: "收到,正在思考中…",
387
+ content: ackContent,
398
388
  conversationType: msg.conversation_type || "direct",
399
389
  msgId: msg.msg_id,
400
390
  senderId: msg.sender_id,
@@ -681,7 +671,6 @@ async function _dispatchPalzMessageInner(params) {
681
671
  log(`${tag}: ${step6bCtx}`);
682
672
  span?.addEvent(step6bCtx);
683
673
  const showProcess = config.showProcess === true;
684
- const groupSystemPrompt = buildFileSharingSystemPrompt();
685
674
  const ctx = core.channel.reply.finalizeInboundContext({
686
675
  Body: combinedBody,
687
676
  BodyForAgent: messageBody,
@@ -714,7 +703,6 @@ async function _dispatchPalzMessageInner(params) {
714
703
  CommandAuthorized: commandAuthorized,
715
704
  OriginatingChannel: "palz-connector",
716
705
  OriginatingTo: palzTo,
717
- GroupSystemPrompt: groupSystemPrompt,
718
706
  ...mediaPayload,
719
707
  });
720
708
  const step6bOutput = `[STEP 6b 输出] finalized context keys=[${Object.keys(ctx).join(",")}] CommandAuthorized=${ctx.CommandAuthorized}`;
package/src/channel.js CHANGED
@@ -16,6 +16,8 @@ export const palzPlugin = {
16
16
  id: "palz-connector",
17
17
  label: "Palz Connector",
18
18
  selectionLabel: "Palz Connector (IM)",
19
+ docsPath: "/channels/palz-connector",
20
+ docsLabel: "Palz Connector",
19
21
  blurb: "Palz IM 接入 OpenClaw",
20
22
  order: 100,
21
23
  },
@@ -40,6 +42,7 @@ export const palzPlugin = {
40
42
  clawGatewayUrl: { type: "string" },
41
43
  activityReportEnabled: { type: "boolean" },
42
44
  sessionTimeout: { type: "integer", minimum: 0 },
45
+ processLanguage: { type: "string", enum: ["zh", "en"] },
43
46
  controlPort: { type: "integer", minimum: 0 },
44
47
  },
45
48
  },
package/src/config.js CHANGED
@@ -15,6 +15,7 @@ const __dirname = path.dirname(__filename);
15
15
  export const PALZ_MANAGER_ACCOUNT_ID = "palz-manager";
16
16
  const DEFAULT_SESSION_TIMEOUT = 30 * 60 * 1000;
17
17
  const DEFAULT_CONFIG_FILENAME = "palz-connector.config.json";
18
+ const DEFAULT_PROCESS_LANGUAGE = "zh";
18
19
  let _cachedFileConfig = null;
19
20
  let _configLoggedOnce = false;
20
21
  let _configAdapterLoggedOnce = false;
@@ -57,6 +58,7 @@ function loadConfigFile() {
57
58
  }
58
59
  export function resolvePalzConfig(_cfg, botId) {
59
60
  const file = loadConfigFile();
61
+ const processLanguage = file.processLanguage === "en" ? "en" : DEFAULT_PROCESS_LANGUAGE;
60
62
  const config = {
61
63
  enabled: file.enabled !== false,
62
64
  botId: botId ?? "",
@@ -67,6 +69,7 @@ export function resolvePalzConfig(_cfg, botId) {
67
69
  sessionTimeout: file.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT,
68
70
  groupContextCache: file.groupContextCache !== false,
69
71
  showProcess: file.showProcess === true,
72
+ processLanguage,
70
73
  kbEngineUrl: file.kbEngineUrl || "",
71
74
  controlPort: file.controlPort,
72
75
  };
@@ -27,6 +27,7 @@ export function createPalzReplyDispatcher(params) {
27
27
  const error = typeof runtime?.error === "function" ? runtime.error : console.error;
28
28
  const streamState = enableStreaming ? createStreamingState() : null;
29
29
  const tag = `palz[${accountId}]`;
30
+ const processLanguage = config.processLanguage;
30
31
  // 风控状态(dispatcher 实例级):当前正文回复(palzMsgType===undefined)命中腾讯
31
32
  // 内容风控(80001)时置位,rawError 保留原始错误文案供上层回灌给 agent 做规避指引。
32
33
  // 每个 dispatcher 实例对应一轮 dispatch,新实例自动重置。
@@ -114,14 +115,14 @@ export function createPalzReplyDispatcher(params) {
114
115
  const toolName = data.name ?? data.toolName;
115
116
  if (phase === "start") {
116
117
  const display = resolveToolDisplay(toolName, data.args);
117
- const text = formatToolStartText(toolName, data.args);
118
+ const text = formatToolStartText(toolName, data.args, processLanguage);
118
119
  log(`${tag}: [TOOL_EVENTS] tool_start name=${toolName} detail=${display.detail ?? "(none)"}`);
119
120
  enqueueIMSend(text, undefined, "tool_start", "tool_start");
120
121
  }
121
122
  if (phase === "result") {
122
123
  const isError = data.isError === true;
123
124
  const meta = typeof data.meta === "string" ? data.meta : undefined;
124
- const text = formatToolResultText(toolName, data.result, isError, meta);
125
+ const text = formatToolResultText(toolName, data.result, isError, meta, processLanguage);
125
126
  const resultSummary = isError ? "Error" : formatResultSummary(data.result);
126
127
  log(`${tag}: [TOOL_EVENTS] tool_result name=${toolName} is_error=${isError} summary=${resultSummary}`);
127
128
  enqueueIMSend(text, undefined, "tool_result", "tool_result");
@@ -4,6 +4,30 @@
4
4
  * 提供工具名到 emoji/title/detailKeys 的映射,以及生成纯文本摘要和结构化内容的辅助函数。
5
5
  * 参考 OpenClaw 的 tool-display-overrides.json 和 ui/tool-display.ts。
6
6
  */
7
+ const TOOL_DISPLAY_LABELS = {
8
+ zh: {
9
+ startSuffix: "开始调用",
10
+ argsLabel: "参数",
11
+ completedSuffix: "调用完成",
12
+ resultLabel: "调用结果",
13
+ successText: "成功",
14
+ failedText: "失败",
15
+ errorLabel: "错误信息",
16
+ summaryLabel: "结果摘要",
17
+ successFallbackSuffix: "执行成功",
18
+ },
19
+ en: {
20
+ startSuffix: "started",
21
+ argsLabel: "Arguments",
22
+ completedSuffix: "completed",
23
+ resultLabel: "Result",
24
+ successText: "success",
25
+ failedText: "failed",
26
+ errorLabel: "Error",
27
+ summaryLabel: "Summary",
28
+ successFallbackSuffix: "succeeded",
29
+ },
30
+ };
7
31
  const TOOL_DISPLAY_MAP = {
8
32
  web_search: { emoji: "🔎", title: "Web Search", detailKeys: ["query", "count"] },
9
33
  web_fetch: { emoji: "📄", title: "Web Fetch", detailKeys: ["url", "extractMode", "maxChars"] },
@@ -47,6 +71,9 @@ export function truncateText(text, headLen = 80, tailLen = 40) {
47
71
  return text;
48
72
  return `${text.slice(0, headLen)}...${text.slice(-tailLen)}`;
49
73
  }
74
+ function resolveLanguage(language) {
75
+ return language === "en" ? "en" : "zh";
76
+ }
50
77
  // ============ Detail 提取 ============
51
78
  function extractDetail(args, detailKeys) {
52
79
  if (!args || typeof args !== "object" || !detailKeys.length)
@@ -115,28 +142,30 @@ export function resolveToolDisplay(name, args) {
115
142
  return { emoji, title, detail };
116
143
  }
117
144
  // ============ 纯文本格式化 ============
118
- export function formatToolStartText(name, args) {
145
+ export function formatToolStartText(name, args, language) {
119
146
  const display = resolveToolDisplay(name, args);
120
- const lines = [`${display.emoji} ${display.title} 开始调用`];
147
+ const labels = TOOL_DISPLAY_LABELS[resolveLanguage(language)];
148
+ const lines = [`${display.emoji} ${display.title} ${labels.startSuffix}`];
121
149
  if (display.detail) {
122
- lines.push(`参数: ${display.detail}`);
150
+ lines.push(`${labels.argsLabel}: ${display.detail}`);
123
151
  }
124
152
  return lines.join("\n");
125
153
  }
126
- export function formatToolResultText(name, result, isError, meta) {
154
+ export function formatToolResultText(name, result, isError, meta, language) {
127
155
  const display = resolveToolDisplay(name);
128
- const lines = [`${display.emoji} ${display.title} 调用完成`];
156
+ const labels = TOOL_DISPLAY_LABELS[resolveLanguage(language)];
157
+ const lines = [`${display.emoji} ${display.title} ${labels.completedSuffix}`];
129
158
  if (isError) {
130
- lines.push("调用结果: 失败");
159
+ lines.push(`${labels.resultLabel}: ${labels.failedText}`);
131
160
  const errMsg = extractErrorMessage(result);
132
161
  if (errMsg) {
133
- lines.push(`错误信息: ${truncateText(errMsg, 80, 40)}`);
162
+ lines.push(`${labels.errorLabel}: ${truncateText(errMsg, 80, 40)}`);
134
163
  }
135
164
  }
136
165
  else {
137
- lines.push("调用结果: 成功");
138
- const resultMeta = meta ? truncateText(meta, 120, 40) : `${display.title}执行成功`;
139
- lines.push(`结果摘要: ${resultMeta}`);
166
+ lines.push(`${labels.resultLabel}: ${labels.successText}`);
167
+ const resultMeta = meta ? truncateText(meta, 120, 40) : `${display.title} ${labels.successFallbackSuffix}`;
168
+ lines.push(`${labels.summaryLabel}: ${resultMeta}`);
140
169
  }
141
170
  return lines.join("\n");
142
171
  }