@xmanrui/dsh-im 2.6.0 → 3.0.0
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.en.md +3 -3
- package/README.md +3 -3
- package/bin/dsh-im.mjs +1 -1
- package/lib/client.js +1409 -1409
- package/lib/index.js +8 -8
- package/package.json +2 -2
- package/plugin-src/client/channels/dingtalk/index.js +0 -17
- package/plugin-src/client/channels/dingtalk/styles.js +2 -2
- package/plugin-src/client/channels/feishu/index.js +0 -29
- package/plugin-src/client/channels/feishu/styles.js +2 -2
- package/plugin-src/client/channels/qq/index.js +0 -9
- package/plugin-src/client/channels/wecom/index.js +0 -9
- package/plugin-src/client/channels/weixin/index.js +0 -19
- package/plugin-src/client/channels/weixin/styles.js +2 -2
- package/plugin-src/client/index.js +4 -4
- package/scripts/verify-package.mjs +48 -11
- package/src/channels/feishu/bridge.mjs +5 -2
- package/src/channels/feishu/message-utils.mjs +1 -1
- package/src/channels/shared/connection-test.mjs +1 -1
- package/src/channels/shared/i18n-en/feishu.mjs +6 -6
- package/src/channels/shared/i18n-en/shared-c.mjs +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmanrui/dsh-im",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"scripts": {
|
|
84
84
|
"build": "node plugin-src/client/build.mjs && node plugin-src/host/build.mjs",
|
|
85
85
|
"test": "node --test test/*.test.mjs test/channels/*/*.test.mjs",
|
|
86
|
-
"check": "npm
|
|
86
|
+
"check": "npm run build && npm test && node scripts/verify-package.mjs"
|
|
87
87
|
},
|
|
88
88
|
"engines": {
|
|
89
89
|
"node": ">=22.19"
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
} from '../../channel-card-meta.js';
|
|
17
17
|
import {
|
|
18
18
|
DINGTALK_ENDPOINTS,
|
|
19
|
-
DINGTALK_RPC_CHANNEL,
|
|
20
19
|
connectionTestFeedback,
|
|
21
20
|
formatRemaining,
|
|
22
21
|
normalizeProvisioning,
|
|
@@ -29,9 +28,6 @@ import { installDingtalkStyles } from './styles.js';
|
|
|
29
28
|
|
|
30
29
|
const ACTIVE_PROVISION_STATES = new Set(['pending', 'scanned', 'authorizing', 'creating', 'connecting']);
|
|
31
30
|
|
|
32
|
-
export const name = 'dingtalk-settings';
|
|
33
|
-
export const inject = ['slots', 'connection'];
|
|
34
|
-
|
|
35
31
|
function DingtalkIcon({ size = 28 }) {
|
|
36
32
|
return h('svg', {
|
|
37
33
|
width: size,
|
|
@@ -864,16 +860,3 @@ export function DingtalkSettingsTab({ rpcCall }) {
|
|
|
864
860
|
})
|
|
865
861
|
: null)));
|
|
866
862
|
}
|
|
867
|
-
|
|
868
|
-
export function apply(ctx) {
|
|
869
|
-
ctx.effect(() => installDingtalkStyles(), 'dingtalk-settings: install client styles');
|
|
870
|
-
const rpcCall = (endpoint, payload, signal) =>
|
|
871
|
-
ctx.connection.rpc.call(DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
|
|
872
|
-
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
|
873
|
-
name: 'settings.plugins.tab',
|
|
874
|
-
id: 'dingtalk',
|
|
875
|
-
order: 40,
|
|
876
|
-
label: '钉钉',
|
|
877
|
-
inject: () => ({ rpcCall }),
|
|
878
|
-
}, DingtalkSettingsTab));
|
|
879
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const DINGTALK_STYLE_ID = 'xmanrui-dsh-dingtalk-settings';
|
|
1
|
+
export const DINGTALK_STYLE_ID = 'xmanrui-dsh-im-dingtalk-settings';
|
|
2
2
|
|
|
3
3
|
const CSS = String.raw`
|
|
4
4
|
.ddt-page {
|
|
@@ -126,7 +126,7 @@ export function installDingtalkStyles() {
|
|
|
126
126
|
const existing = document.querySelector(`style[data-plugin-css="${DINGTALK_STYLE_ID}"]`);
|
|
127
127
|
if (existing) return () => {};
|
|
128
128
|
const style = document.createElement('style');
|
|
129
|
-
style.dataset.plugin = '@xmanrui/dsh-
|
|
129
|
+
style.dataset.plugin = '@xmanrui/dsh-im';
|
|
130
130
|
style.dataset.pluginCss = DINGTALK_STYLE_ID;
|
|
131
131
|
style.textContent = CSS;
|
|
132
132
|
document.head.appendChild(style);
|
|
@@ -6,7 +6,6 @@ import { h } from "../../i18n.js";
|
|
|
6
6
|
import {
|
|
7
7
|
FEISHU_ENDPOINTS,
|
|
8
8
|
FEISHU_REGISTRATION_OPERATIONS,
|
|
9
|
-
FEISHU_RPC_CHANNEL,
|
|
10
9
|
formatRemaining,
|
|
11
10
|
normalizeBotsSnapshot,
|
|
12
11
|
normalizeGroupResponseMode,
|
|
@@ -28,11 +27,6 @@ import {
|
|
|
28
27
|
ChannelListHeading,
|
|
29
28
|
LastMessageErrorSummary,
|
|
30
29
|
} from "../../channel-card-meta.js";
|
|
31
|
-
import { installFeishuStyles } from "./styles.js";
|
|
32
|
-
|
|
33
|
-
export const name = "feishu-settings";
|
|
34
|
-
export const inject = ["slots", "connection"];
|
|
35
|
-
|
|
36
30
|
const CALLBACK_REPAIR_OPERATION = FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR;
|
|
37
31
|
const GROUP_MESSAGE_PERMISSION_OPERATION = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
|
|
38
32
|
|
|
@@ -1540,26 +1534,3 @@ export function FeishuSettingsTab({ rpcCall }) {
|
|
|
1540
1534
|
),
|
|
1541
1535
|
));
|
|
1542
1536
|
}
|
|
1543
|
-
|
|
1544
|
-
export function apply(ctx) {
|
|
1545
|
-
ctx.effect(
|
|
1546
|
-
() => installFeishuStyles(),
|
|
1547
|
-
"feishu-settings: install client styles",
|
|
1548
|
-
);
|
|
1549
|
-
|
|
1550
|
-
const rpcCall = (endpoint, payload, signal) =>
|
|
1551
|
-
ctx.connection.rpc.call(FEISHU_RPC_CHANNEL, endpoint, payload, signal);
|
|
1552
|
-
|
|
1553
|
-
ctx.slots.inject("settings.plugins.tab", () =>
|
|
1554
|
-
ctx.slots.register(
|
|
1555
|
-
{
|
|
1556
|
-
name: "settings.plugins.tab",
|
|
1557
|
-
id: "feishu",
|
|
1558
|
-
order: 20,
|
|
1559
|
-
label: "飞书",
|
|
1560
|
-
inject: () => ({ rpcCall }),
|
|
1561
|
-
},
|
|
1562
|
-
FeishuSettingsTab,
|
|
1563
|
-
),
|
|
1564
|
-
);
|
|
1565
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const FEISHU_STYLE_ID = "
|
|
1
|
+
export const FEISHU_STYLE_ID = "xmanrui-dsh-im-feishu-settings";
|
|
2
2
|
|
|
3
3
|
const CSS = String.raw`
|
|
4
4
|
.bxf-page {
|
|
@@ -562,7 +562,7 @@ export function installFeishuStyles() {
|
|
|
562
562
|
}
|
|
563
563
|
|
|
564
564
|
const style = document.createElement("style");
|
|
565
|
-
style.dataset.plugin = "@xmanrui/dsh-
|
|
565
|
+
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
566
566
|
style.dataset.pluginCss = FEISHU_STYLE_ID;
|
|
567
567
|
style.textContent = CSS;
|
|
568
568
|
document.head.appendChild(style);
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
import { installDingtalkStyles } from '../dingtalk/styles.js';
|
|
19
19
|
import {
|
|
20
20
|
QQ_ENDPOINTS,
|
|
21
|
-
QQ_RPC_CHANNEL,
|
|
22
21
|
connectionTestFeedback,
|
|
23
22
|
formatRemaining,
|
|
24
23
|
normalizeProvisioning,
|
|
@@ -514,11 +513,3 @@ export function QqSettingsTab({ rpcCall }) {
|
|
|
514
513
|
? h(EmptyView, { busy, onStart: () => void startProvisioning() }) : null,
|
|
515
514
|
botList)));
|
|
516
515
|
}
|
|
517
|
-
|
|
518
|
-
export function apply(ctx) {
|
|
519
|
-
ctx.effect(() => installQqStyles(), 'qq-settings: install client styles');
|
|
520
|
-
const rpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(QQ_RPC_CHANNEL, endpoint, payload, signal);
|
|
521
|
-
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
|
522
|
-
name: 'settings.plugins.tab', id: 'qq', order: 50, label: 'QQ', inject: () => ({ rpcCall }),
|
|
523
|
-
}, QqSettingsTab));
|
|
524
|
-
}
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
import { installDingtalkStyles } from '../dingtalk/styles.js';
|
|
19
19
|
import {
|
|
20
20
|
WECOM_ENDPOINTS,
|
|
21
|
-
WECOM_RPC_CHANNEL,
|
|
22
21
|
formatRemaining,
|
|
23
22
|
normalizeProvisioning,
|
|
24
23
|
normalizeSnapshot,
|
|
@@ -546,11 +545,3 @@ export function WecomSettingsTab({ rpcCall }) {
|
|
|
546
545
|
? h(EmptyView, { busy, onStart: () => void startProvisioning() }) : null,
|
|
547
546
|
botList)));
|
|
548
547
|
}
|
|
549
|
-
|
|
550
|
-
export function apply(ctx) {
|
|
551
|
-
ctx.effect(() => installWecomStyles(), 'wecom-settings: install client styles');
|
|
552
|
-
const rpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_RPC_CHANNEL, endpoint, payload, signal);
|
|
553
|
-
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
|
554
|
-
name: 'settings.plugins.tab', id: 'wecom', order: 45, label: '企业微信', inject: () => ({ rpcCall }),
|
|
555
|
-
}, WecomSettingsTab));
|
|
556
|
-
}
|
|
@@ -5,7 +5,6 @@ import { QrActionIcon } from '../../credential-binding.js';
|
|
|
5
5
|
import { h } from '../../i18n.js';
|
|
6
6
|
import {
|
|
7
7
|
WEIXIN_ENDPOINTS,
|
|
8
|
-
WEIXIN_RPC_CHANNEL,
|
|
9
8
|
formatRemaining,
|
|
10
9
|
normalizeProvisioning,
|
|
11
10
|
normalizeSnapshot,
|
|
@@ -27,11 +26,6 @@ import {
|
|
|
27
26
|
ChannelListHeading,
|
|
28
27
|
LastMessageErrorSummary,
|
|
29
28
|
} from '../../channel-card-meta.js';
|
|
30
|
-
import { installWeixinStyles } from './styles.js';
|
|
31
|
-
|
|
32
|
-
export const name = 'weixin-settings';
|
|
33
|
-
export const inject = ['slots', 'connection'];
|
|
34
|
-
|
|
35
29
|
const Button = React.forwardRef(function Button(
|
|
36
30
|
{ children, kind = 'secondary', className = '', ...props },
|
|
37
31
|
ref,
|
|
@@ -717,16 +711,3 @@ export function WeixinSettingsTab({ rpcCall }) {
|
|
|
717
711
|
: null),
|
|
718
712
|
));
|
|
719
713
|
}
|
|
720
|
-
|
|
721
|
-
export function apply(ctx) {
|
|
722
|
-
ctx.effect(() => installWeixinStyles(), 'weixin-settings: install client styles');
|
|
723
|
-
const rpcCall = (endpoint, payload, signal) =>
|
|
724
|
-
ctx.connection.rpc.call(WEIXIN_RPC_CHANNEL, endpoint, payload, signal);
|
|
725
|
-
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
|
726
|
-
name: 'settings.plugins.tab',
|
|
727
|
-
id: 'weixin',
|
|
728
|
-
order: 30,
|
|
729
|
-
label: '微信',
|
|
730
|
-
inject: () => ({ rpcCall }),
|
|
731
|
-
}, WeixinSettingsTab));
|
|
732
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const WEIXIN_STYLE_ID = 'xmanrui-dsh-weixin-settings';
|
|
1
|
+
export const WEIXIN_STYLE_ID = 'xmanrui-dsh-im-weixin-settings';
|
|
2
2
|
|
|
3
3
|
const CSS = String.raw`
|
|
4
4
|
.dxw-page {
|
|
@@ -107,7 +107,7 @@ export function installWeixinStyles() {
|
|
|
107
107
|
const existing = document.querySelector(`style[data-plugin-css="${WEIXIN_STYLE_ID}"]`);
|
|
108
108
|
if (existing) return () => {};
|
|
109
109
|
const style = document.createElement('style');
|
|
110
|
-
style.dataset.plugin = '@xmanrui/dsh-
|
|
110
|
+
style.dataset.plugin = '@xmanrui/dsh-im';
|
|
111
111
|
style.dataset.pluginCss = WEIXIN_STYLE_ID;
|
|
112
112
|
style.textContent = CSS;
|
|
113
113
|
document.head.appendChild(style);
|
|
@@ -333,10 +333,10 @@ export function apply(ctx) {
|
|
|
333
333
|
pickDirectory: () => ctx.workspaces.pickDirectory(),
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
-
ctx.slots.inject('settings.
|
|
337
|
-
name: 'settings.
|
|
338
|
-
id: 'im',
|
|
339
|
-
order:
|
|
336
|
+
ctx.slots.inject('settings.section', () => ctx.slots.register({
|
|
337
|
+
name: 'settings.section',
|
|
338
|
+
id: 'xmanrui-dsh-im',
|
|
339
|
+
order: 21,
|
|
340
340
|
label: () => t('IM机器人'),
|
|
341
341
|
locale: IM_LOCALE_NAMESPACE,
|
|
342
342
|
inject: () => ({
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import { access, readFile, stat } from 'node:fs/promises';
|
|
1
|
+
import { access, readFile, readdir, stat } from 'node:fs/promises';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
|
|
5
5
|
const root = resolve(import.meta.dirname, '..');
|
|
6
|
+
|
|
7
|
+
async function readSourceTree(directory) {
|
|
8
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
9
|
+
const chunks = [];
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const path = resolve(directory, entry.name);
|
|
12
|
+
if (entry.isDirectory()) {
|
|
13
|
+
chunks.push(await readSourceTree(path));
|
|
14
|
+
} else if (entry.isFile() && /\.m?js$/u.test(entry.name)) {
|
|
15
|
+
chunks.push(await readFile(path, 'utf8'));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return chunks.join('\n');
|
|
19
|
+
}
|
|
20
|
+
|
|
6
21
|
const required = [
|
|
7
22
|
'lib/index.js',
|
|
8
23
|
'lib/client.js',
|
|
@@ -35,7 +50,17 @@ const required = [
|
|
|
35
50
|
];
|
|
36
51
|
await Promise.all(required.map((path) => access(resolve(root, path))));
|
|
37
52
|
|
|
38
|
-
const [
|
|
53
|
+
const [
|
|
54
|
+
client,
|
|
55
|
+
host,
|
|
56
|
+
patch,
|
|
57
|
+
manifestText,
|
|
58
|
+
lockText,
|
|
59
|
+
hostSource,
|
|
60
|
+
clientEntrySource,
|
|
61
|
+
clientSources,
|
|
62
|
+
executable,
|
|
63
|
+
] = await Promise.all([
|
|
39
64
|
readFile(resolve(root, 'lib/client.js'), 'utf8'),
|
|
40
65
|
readFile(resolve(root, 'lib/index.js'), 'utf8'),
|
|
41
66
|
readFile(resolve(root, 'cordis.patch.yml'), 'utf8'),
|
|
@@ -43,6 +68,7 @@ const [client, host, patch, manifestText, lockText, hostSource, clientSource, ex
|
|
|
43
68
|
readFile(resolve(root, 'package-lock.json'), 'utf8'),
|
|
44
69
|
readFile(resolve(root, 'plugin-src/host/index.mjs'), 'utf8'),
|
|
45
70
|
readFile(resolve(root, 'plugin-src/client/index.js'), 'utf8'),
|
|
71
|
+
readSourceTree(resolve(root, 'plugin-src/client')),
|
|
46
72
|
stat(resolve(root, 'bin/dsh-im.mjs')),
|
|
47
73
|
]);
|
|
48
74
|
const manifest = JSON.parse(manifestText);
|
|
@@ -82,17 +108,28 @@ if (forbiddenDshLockPaths.length > 0) {
|
|
|
82
108
|
);
|
|
83
109
|
}
|
|
84
110
|
|
|
85
|
-
if (
|
|
111
|
+
if (!/\bid\s*:\s*["']@xmanrui\/dsh-im["']/u.test(client)) {
|
|
86
112
|
throw new Error('client bundle does not register the dsh-im loader id');
|
|
87
113
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
114
|
+
const sourceSectionMarkers = [
|
|
115
|
+
/ctx\.slots\.inject\(\s*["']settings\.section["']/u,
|
|
116
|
+
/name\s*:\s*["']settings\.section["']/u,
|
|
117
|
+
/id\s*:\s*["']xmanrui-dsh-im["']/u,
|
|
118
|
+
/order\s*:\s*21\b/u,
|
|
119
|
+
/label\s*:\s*\(\)\s*=>\s*t\(\s*["']IM机器人["']\s*\)/u,
|
|
120
|
+
/locale\s*:\s*IM_LOCALE_NAMESPACE\b/u,
|
|
121
|
+
];
|
|
122
|
+
const bundleSectionPattern = /name\s*:\s*["']settings\.section["']\s*,\s*id\s*:\s*["']xmanrui-dsh-im["']\s*,\s*order\s*:\s*21\s*,\s*label\s*:\s*\(\)\s*=>\s*[$A-Z_a-z][$\w]*\(\s*["']IM(?:机器人|\\u673A\\u5668\\u4EBA)["']\s*\)\s*,\s*locale\s*:\s*(?:[$A-Z_a-z][$\w]*|["']dsh-im["'])/u;
|
|
123
|
+
if (sourceSectionMarkers.some((pattern) => !pattern.test(clientEntrySource))
|
|
124
|
+
|| !/IM_LOCALE_NAMESPACE\s*=\s*["']dsh-im["']/u.test(clientSources)
|
|
125
|
+
|| !bundleSectionPattern.test(client)) {
|
|
126
|
+
throw new Error('client bundle does not register the localized top-level IM settings section');
|
|
127
|
+
}
|
|
128
|
+
if ((client.match(/\.slots\.inject\(\s*["']settings\.section["']/gu) ?? []).length !== 1) {
|
|
129
|
+
throw new Error('client bundle must register exactly one top-level settings section');
|
|
93
130
|
}
|
|
94
|
-
if (
|
|
95
|
-
throw new Error('client bundle
|
|
131
|
+
if (client.includes('settings.plugins.tab') || clientSources.includes('settings.plugins.tab')) {
|
|
132
|
+
throw new Error('client source or bundle still contains the legacy Plugins-tab settings entry');
|
|
96
133
|
}
|
|
97
134
|
if (/role:\s*["']switch|type:\s*["']checkbox/.test(client)) {
|
|
98
135
|
throw new Error('client bundle contains a channel enable switch');
|
|
@@ -115,7 +152,7 @@ if (/@xmanrui\/dsh-(?:feishu|weixin|dingtalk)/.test(host)) {
|
|
|
115
152
|
throw new Error('host bundle still imports an external channel plugin');
|
|
116
153
|
}
|
|
117
154
|
if (/@xmanrui\/dsh-(?:feishu|weixin|dingtalk)/.test(
|
|
118
|
-
manifestText + lockText + hostSource +
|
|
155
|
+
manifestText + lockText + hostSource + clientSources,
|
|
119
156
|
)) {
|
|
120
157
|
throw new Error('source or package metadata still depends on an external channel plugin');
|
|
121
158
|
}
|
|
@@ -159,7 +159,7 @@ function artifactFailureText(fileName, error) {
|
|
|
159
159
|
const name = String(fileName ?? t('结果文件')).replace(/[\r\n]+/g, ' ').trim() || t('结果文件');
|
|
160
160
|
switch (error?.code) {
|
|
161
161
|
case 'artifact-permission-required':
|
|
162
|
-
return t('结果文件「{name}」已生成,但机器人缺少飞书文件上传权限 im:resource。请私聊机器人执行 /repair
|
|
162
|
+
return t('结果文件「{name}」已生成,但机器人缺少飞书文件上传权限 im:resource。请私聊机器人执行 /repair 命令,或者在「IM机器人」设置页点击“补全权限”按钮并扫码。完成飞书要求的发布审批后重试。', { name });
|
|
163
163
|
case 'artifact-too-large':
|
|
164
164
|
return t('结果文件「{name}」超过飞书 30 MB 上限,未发送。', { name });
|
|
165
165
|
case 'artifact-empty':
|
|
@@ -945,7 +945,10 @@ export class FeishuHarnessBridge {
|
|
|
945
945
|
const text = message.content;
|
|
946
946
|
const hasImages = hasInboundImages(message);
|
|
947
947
|
const hasFiles = hasInboundFiles(message);
|
|
948
|
-
|
|
948
|
+
// 命令识别对 text 与纯文本 post 一视同仁:post 富文本若仅含单个
|
|
949
|
+
// 文本段落(如复制粘贴的 /new),同样按命令处理;带图片/文件不认。
|
|
950
|
+
// accept() 侧已用 nonEmptyString(content) 判定,两侧保持一致。
|
|
951
|
+
const commandText = !hasImages && !hasFiles && text ? text.trim() : null;
|
|
949
952
|
if (!text && !hasImages && !hasFiles) {
|
|
950
953
|
await this.#send(event.message.chat_id, t('目前支持文字、图片和文件消息。'));
|
|
951
954
|
return;
|
|
@@ -5,7 +5,7 @@ const FEISHU_MISSING_MESSAGE_SCOPE_CODE = 99991672;
|
|
|
5
5
|
const FEISHU_ERROR_BODY_LIMIT = 64 * 1024;
|
|
6
6
|
const FEISHU_ERROR_BODY_TIMEOUT_MS = 1_000;
|
|
7
7
|
const FEISHU_IMAGE_PERMISSION_MESSAGE =
|
|
8
|
-
'飞书机器人缺少图片读取权限 im:message:readonly(飞书显示为“获取单聊、群组消息”)。请私聊机器人执行 /repair
|
|
8
|
+
'飞书机器人缺少图片读取权限 im:message:readonly(飞书显示为“获取单聊、群组消息”)。请私聊机器人执行 /repair 命令,或者在「IM机器人」设置页点击“补全权限”按钮并扫码。按飞书提示发布新版本、完成必要审批后,再重新发送图片。';
|
|
9
9
|
|
|
10
10
|
export function conversationKey(event) {
|
|
11
11
|
const chatType = event?.message?.chat_type;
|
|
@@ -29,7 +29,7 @@ export function connectionTestTarget(state) {
|
|
|
29
29
|
|
|
30
30
|
export function connectionTestMessage(botName, channelLabel = t('机器人')) {
|
|
31
31
|
const name = cleanText(botName) ?? channelLabel;
|
|
32
|
-
return `${t('✅ DeepSeek Harness 连接测试成功')}\n${t('
|
|
32
|
+
return `${t('✅ DeepSeek Harness 连接测试成功')}\n${t('这条消息由「IM机器人」设置页中的“{name}”机器人卡片发出。', { name })}`;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export function connectionTestTargetUnavailable(channelLabel = t('机器人')) {
|
|
@@ -18,8 +18,8 @@ export default {
|
|
|
18
18
|
'机器人正在移除或已重新接入,无法操作原会话的工作区。':
|
|
19
19
|
'The bot is being removed or has been reconnected; the original session’s workspace cannot be changed.',
|
|
20
20
|
'操作失败,请稍后重试。': 'The operation failed. Please try again later.',
|
|
21
|
-
'结果文件「{name}」已生成,但机器人缺少飞书文件上传权限 im:resource。请私聊机器人执行 /repair
|
|
22
|
-
'The result file "{name}" was generated, but the bot lacks the Feishu file-upload scope im:resource. Run /repair in a direct chat with the bot, or click the “Complete permissions” button on the
|
|
21
|
+
'结果文件「{name}」已生成,但机器人缺少飞书文件上传权限 im:resource。请私聊机器人执行 /repair 命令,或者在「IM机器人」设置页点击“补全权限”按钮并扫码。完成飞书要求的发布审批后重试。':
|
|
22
|
+
'The result file "{name}" was generated, but the bot lacks the Feishu file-upload scope im:resource. Run /repair in a direct chat with the bot, or click the “Complete permissions” button on the IM Bot settings page and scan the QR code. Complete any publishing approval Feishu requires, then try again.',
|
|
23
23
|
'结果文件「{name}」超过飞书 30 MB 上限,未发送。':
|
|
24
24
|
'The result file "{name}" exceeds the Feishu 30 MB limit and was not sent.',
|
|
25
25
|
'结果文件「{name}」为空,飞书不允许发送空文件。':
|
|
@@ -28,8 +28,8 @@ export default {
|
|
|
28
28
|
'The result file "{name}" was temporarily rate-limited by Feishu and could not be sent. Please try again later.',
|
|
29
29
|
'结果文件「{name}」已生成,但暂时未能发送,请稍后重试。':
|
|
30
30
|
'The result file "{name}" was generated but could not be sent right now. Please try again later.',
|
|
31
|
-
'处理失败,请稍后重试。如果问题持续,请在 DeepSeek Harness
|
|
32
|
-
'Message processing failed. Please try again later. If the problem persists, check the connection status on the
|
|
31
|
+
'处理失败,请稍后重试。如果问题持续,请在 DeepSeek Harness 的「IM机器人」设置页检查飞书连接状态。':
|
|
32
|
+
'Message processing failed. Please try again later. If the problem persists, check the Feishu connection status on the IM Bot settings page in DeepSeek Harness.',
|
|
33
33
|
'已开启全新 Harness 会话。': 'A brand-new Harness session has started.',
|
|
34
34
|
'飞书机器人与 DeepSeek Harness 连接正常。':
|
|
35
35
|
'The Feishu bot is connected to DeepSeek Harness and working normally.',
|
|
@@ -338,8 +338,8 @@ export default {
|
|
|
338
338
|
'飞书机器人': 'Feishu bot',
|
|
339
339
|
|
|
340
340
|
// feishu/message-utils.mjs
|
|
341
|
-
'飞书机器人缺少图片读取权限 im:message:readonly(飞书显示为“获取单聊、群组消息”)。请私聊机器人执行 /repair
|
|
342
|
-
'The Feishu bot is missing the image-read scope im:message:readonly, shown by Feishu as “Read direct and group messages.” Run /repair in a direct chat with the bot, or click the “Complete permissions” button on the
|
|
341
|
+
'飞书机器人缺少图片读取权限 im:message:readonly(飞书显示为“获取单聊、群组消息”)。请私聊机器人执行 /repair 命令,或者在「IM机器人」设置页点击“补全权限”按钮并扫码。按飞书提示发布新版本、完成必要审批后,再重新发送图片。':
|
|
342
|
+
'The Feishu bot is missing the image-read scope im:message:readonly, shown by Feishu as “Read direct and group messages.” Run /repair in a direct chat with the bot, or click the “Complete permissions” button on the IM Bot settings page and scan the QR code. Publish a new version and complete any approval requested by Feishu, then resend the image.',
|
|
343
343
|
|
|
344
344
|
// feishu/feishu-runtime.mjs — callback probe notices
|
|
345
345
|
'✅ 修复完成:已实测收到 card.action.trigger,菜单按钮现在可用。':
|
|
@@ -73,8 +73,8 @@ export default {
|
|
|
73
73
|
// connection-test.mjs
|
|
74
74
|
'✅ DeepSeek Harness 连接测试成功':
|
|
75
75
|
'✅ DeepSeek Harness connection test succeeded',
|
|
76
|
-
'
|
|
77
|
-
'This message was sent from the "{name}" bot card on the
|
|
76
|
+
'这条消息由「IM机器人」设置页中的“{name}”机器人卡片发出。':
|
|
77
|
+
'This message was sent from the "{name}" bot card on the IM Bot settings page.',
|
|
78
78
|
'{channelLabel}尚未收到可用于测试的私聊消息。':
|
|
79
79
|
'The {channelLabel} has not received a direct message that can be used for testing yet.',
|
|
80
80
|
'机器人': 'bot',
|