@xmanrui/dsh-im 3.1.0 → 3.2.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.
Files changed (64) hide show
  1. package/README.en.md +15 -0
  2. package/README.md +15 -0
  3. package/lib/client.js +1653 -333
  4. package/lib/index.js +235 -223
  5. package/package.json +5 -1
  6. package/plugin-src/client/channels/dingtalk/api.js +3 -0
  7. package/plugin-src/client/channels/dingtalk/index.js +18 -5
  8. package/plugin-src/client/channels/feishu/api.js +3 -0
  9. package/plugin-src/client/channels/feishu/index.js +18 -5
  10. package/plugin-src/client/channels/qq/api.js +3 -0
  11. package/plugin-src/client/channels/qq/index.js +13 -0
  12. package/plugin-src/client/channels/shared/token-api.js +3 -0
  13. package/plugin-src/client/channels/shared/token-channel.js +13 -1
  14. package/plugin-src/client/channels/wecom/api.js +3 -0
  15. package/plugin-src/client/channels/wecom/index.js +13 -0
  16. package/plugin-src/client/channels/weixin/api.js +3 -0
  17. package/plugin-src/client/channels/weixin/index.js +19 -5
  18. package/plugin-src/client/channels/whatsapp/api.js +3 -0
  19. package/plugin-src/client/channels/whatsapp/index.js +13 -0
  20. package/plugin-src/client/context-enhancement.js +275 -0
  21. package/plugin-src/client/i18n.js +54 -3
  22. package/plugin-src/client/styles.js +78 -0
  23. package/plugin-src/client/update-panel.js +108 -7
  24. package/plugin-src/host/channels/dingtalk/production.mjs +1 -0
  25. package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
  26. package/plugin-src/host/channels/feishu/production.mjs +3 -0
  27. package/plugin-src/host/channels/feishu/rpc.mjs +13 -0
  28. package/plugin-src/host/channels/qq/production.mjs +1 -0
  29. package/plugin-src/host/channels/qq/rpc.mjs +11 -0
  30. package/plugin-src/host/channels/shared/context-enhancement-rpc.mjs +17 -0
  31. package/plugin-src/host/channels/shared/production.mjs +1 -0
  32. package/plugin-src/host/channels/shared/rpc.mjs +9 -0
  33. package/plugin-src/host/channels/shared/workspace-rpc.mjs +1 -0
  34. package/plugin-src/host/channels/slack/production.mjs +1 -0
  35. package/plugin-src/host/channels/slack/rpc.mjs +10 -0
  36. package/plugin-src/host/channels/wecom/production.mjs +1 -0
  37. package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
  38. package/plugin-src/host/channels/weixin/production.mjs +1 -0
  39. package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
  40. package/plugin-src/host/channels/whatsapp/production.mjs +1 -0
  41. package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
  42. package/plugin-src/host/update-runtime.mjs +3 -2
  43. package/plugin-src/host/update-service.mjs +2 -0
  44. package/scripts/verify-package.mjs +15 -2
  45. package/src/channels/dingtalk/dingtalk-api.mjs +39 -16
  46. package/src/channels/dingtalk/dingtalk-bridge.mjs +52 -23
  47. package/src/channels/dingtalk/dingtalk-runtime.mjs +20 -1
  48. package/src/channels/discord/discord-runtime.mjs +18 -4
  49. package/src/channels/feishu/bridge.mjs +20 -4
  50. package/src/channels/feishu/feishu-channel.mjs +100 -44
  51. package/src/channels/feishu/feishu-runtime.mjs +4 -0
  52. package/src/channels/qq/qq-bridge.mjs +20 -4
  53. package/src/channels/qq/qq-runtime.mjs +4 -0
  54. package/src/channels/shared/bot-workspace-store.mjs +103 -6
  55. package/src/channels/shared/context-enhancement.mjs +135 -0
  56. package/src/channels/shared/i18n-en/feishu.mjs +2 -0
  57. package/src/channels/shared/text-harness-bridge.mjs +19 -4
  58. package/src/channels/slack/slack-runtime.mjs +4 -0
  59. package/src/channels/telegram/telegram-runtime.mjs +24 -2
  60. package/src/channels/wecom/wecom-bridge.mjs +18 -3
  61. package/src/channels/wecom/wecom-runtime.mjs +4 -0
  62. package/src/channels/weixin/weixin-bridge.mjs +19 -4
  63. package/src/channels/weixin/weixin-runtime.mjs +4 -0
  64. package/src/channels/whatsapp/whatsapp-runtime.mjs +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmanrui/dsh-im",
3
- "version": "3.1.0",
3
+ "version": "3.2.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",
@@ -30,6 +30,10 @@
30
30
  {
31
31
  "name": "C3H3-AI",
32
32
  "url": "https://github.com/C3H3-AI"
33
+ },
34
+ {
35
+ "name": "divingleee",
36
+ "url": "https://github.com/divingleee"
33
37
  }
34
38
  ],
35
39
  "license": "MIT",
@@ -1,5 +1,6 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
2
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
+ import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
3
4
 
4
5
  export const DINGTALK_RPC_CHANNEL = '/dingtalk';
5
6
 
@@ -13,6 +14,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
13
14
  deleteBot: 'bot.delete',
14
15
  setWorkspace: 'bot.workspace.set',
15
16
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
17
+ setContextEnhancement: 'bot.context-enhancement.set',
16
18
  });
17
19
 
18
20
  const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
@@ -162,6 +164,7 @@ function normalizeBot(value) {
162
164
  configured: value.configured !== false,
163
165
  workspace: optionalString(value.workspace, 4_096) ?? '',
164
166
  agentPreset: normalizeAgentPresetId(value.agentPreset),
167
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
165
168
  bot: {
166
169
  name: optionalString(bot.name, 100) ?? '钉钉机器人',
167
170
  clientIdMasked: optionalString(bot.clientIdMasked, 140) ?? '已安全保存',
@@ -3,6 +3,7 @@ import * as React from 'react';
3
3
  import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
4
4
  import { h } from '../../i18n.js';
5
5
  import { WorkspaceEditor } from '../../workspace-editor.js';
6
+ import { ContextEnhancementEditor } from '../../context-enhancement.js';
6
7
  import {
7
8
  AgentPresetCatalogContext,
8
9
  AgentPresetEditor,
@@ -220,6 +221,7 @@ export function AccountCard({
220
221
  onReconnect,
221
222
  onWorkspaceSave,
222
223
  onAgentPresetSave,
224
+ onContextEnhancementSave,
223
225
  onRequestRemove,
224
226
  onConfirmRemove,
225
227
  onCancelRemove,
@@ -254,6 +256,11 @@ export function AccountCard({
254
256
  disabled: Boolean(busy),
255
257
  onSave: onAgentPresetSave,
256
258
  }),
259
+ h(ContextEnhancementEditor, {
260
+ config: account.contextEnhancement,
261
+ disabled: Boolean(busy),
262
+ onSave: onContextEnhancementSave,
263
+ }),
257
264
  h('div', { className: 'ddt-accountFooter dim-cardFooter' },
258
265
  h('div', { className: 'dim-cardFooterLayout' },
259
266
  h('div', { className: 'ddt-actions dim-cardActions' },
@@ -294,6 +301,7 @@ function AccountList(props) {
294
301
  onReconnect: () => props.onReconnect(account),
295
302
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
296
303
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
304
+ onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
297
305
  onRequestRemove: () => props.onRequestRemove(account),
298
306
  onConfirmRemove: () => props.onConfirmRemove(account),
299
307
  onCancelRemove: props.onCancelRemove,
@@ -737,13 +745,13 @@ export function DingtalkSettingsTab({ rpcCall }) {
737
745
  }
738
746
  }, [discardStaleFeedback, invoke, loadStatus, setBotBusy, workspaceFence]);
739
747
 
740
- const saveAgentPreset = React.useCallback(async (account, agentPreset) => {
748
+ const saveBotSetting = React.useCallback(async (account, operation, endpoint, payload) => {
741
749
  const snapshotVersion = workspaceFence.beginMutation();
742
- setBotBusy(account.botId, 'preset');
750
+ setBotBusy(account.botId, operation);
743
751
  try {
744
752
  const snapshot = normalizeSnapshot(await invoke(
745
- DINGTALK_ENDPOINTS.setAgentPreset,
746
- { botId: account.botId, agentPreset },
753
+ endpoint,
754
+ { botId: account.botId, ...payload },
747
755
  ));
748
756
  if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
749
757
  setModel({
@@ -853,7 +861,12 @@ export function DingtalkSettingsTab({ rpcCall }) {
853
861
  removeTarget,
854
862
  onReconnect: (account) => void reconnect(account),
855
863
  onWorkspaceSave: saveWorkspace,
856
- onAgentPresetSave: saveAgentPreset,
864
+ onAgentPresetSave: (account, agentPreset) => saveBotSetting(
865
+ account, 'preset', DINGTALK_ENDPOINTS.setAgentPreset, { agentPreset },
866
+ ),
867
+ onContextEnhancementSave: (account, config) => saveBotSetting(
868
+ account, 'context-enhancement', DINGTALK_ENDPOINTS.setContextEnhancement, { config },
869
+ ),
857
870
  onRequestRemove: (account) => setRemoveTarget(account.botId),
858
871
  onConfirmRemove: (account) => void remove(account),
859
872
  onCancelRemove: () => setRemoveTarget(null),
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId } from "../../agent-preset.js";
10
10
  import { normalizeLastMessageError } from "../../last-message-error.js";
11
+ import { normalizeContextEnhancementConfig } from "../../../../src/channels/shared/context-enhancement.mjs";
11
12
 
12
13
  export const FEISHU_RPC_CHANNEL = "/feishu";
13
14
 
@@ -24,6 +25,7 @@ export const FEISHU_ENDPOINTS = Object.freeze({
24
25
  deleteBot: "bot.delete",
25
26
  setWorkspace: "bot.workspace.set",
26
27
  setAgentPreset: "bot.preset.set",
28
+ setContextEnhancement: "bot.context-enhancement.set",
27
29
  setGroupResponseMode: "bot.group-response-mode.set",
28
30
  // Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
29
31
  testConnection: "connection.test",
@@ -203,6 +205,7 @@ export function normalizeBotConnection(value, fallbackBotId) {
203
205
  configured: value.configured !== false,
204
206
  workspace: optionalString(value.workspace)?.slice(0, 4_096) ?? "",
205
207
  agentPreset: normalizeAgentPresetId(value.agentPreset),
208
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
206
209
  groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
207
210
  groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
208
211
  bot: normalizeBot(value.bot),
@@ -16,6 +16,7 @@ import {
16
16
  } from "./api.js";
17
17
  import { useAnimationFrameScheduler } from "../../lifecycle.js";
18
18
  import { WorkspaceEditor } from "../../workspace-editor.js";
19
+ import { ContextEnhancementEditor } from "../../context-enhancement.js";
19
20
  import {
20
21
  AgentPresetCatalogContext,
21
22
  AgentPresetEditor,
@@ -553,6 +554,7 @@ export function BotCard({
553
554
  onRepairCallback,
554
555
  onWorkspaceSave,
555
556
  onAgentPresetSave,
557
+ onContextEnhancementSave,
556
558
  onGroupResponseModeSave,
557
559
  onGroupMessagePermissionAuthorize,
558
560
  onRequestRemove,
@@ -611,6 +613,11 @@ export function BotCard({
611
613
  disabled: Boolean(busy),
612
614
  onSave: onAgentPresetSave,
613
615
  }),
616
+ h(ContextEnhancementEditor, {
617
+ config: connection.contextEnhancement,
618
+ disabled: Boolean(busy),
619
+ onSave: onContextEnhancementSave,
620
+ }),
614
621
  h(GroupResponseModeEditor, {
615
622
  value: connection.groupResponseMode,
616
623
  permissionGranted: connection.groupMessagePermissionGranted,
@@ -708,6 +715,7 @@ function BotList(props) {
708
715
  onRepairCallback: () => props.onRepairCallback(bot),
709
716
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
710
717
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
718
+ onContextEnhancementSave: (config) => props.onContextEnhancementSave(bot, config),
711
719
  onGroupResponseModeSave: (groupResponseMode) => props.onGroupResponseModeSave(bot, groupResponseMode),
712
720
  onGroupMessagePermissionAuthorize: () => props.onGroupMessagePermissionAuthorize(bot),
713
721
  onRequestRemove: () => props.onRequestRemove(bot),
@@ -1296,15 +1304,15 @@ export function FeishuSettingsTab({ rpcCall }) {
1296
1304
  }
1297
1305
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
1298
1306
 
1299
- const saveAgentPreset = React.useCallback(async (connection, agentPreset) => {
1307
+ const saveBotSetting = React.useCallback(async (connection, operation, endpoint, payload) => {
1300
1308
  const { botId } = connection;
1301
1309
  const snapshotVersion = workspaceFence.beginMutation();
1302
- setBotBusy(botId, "preset");
1310
+ setBotBusy(botId, operation);
1303
1311
  setBotError(botId, null);
1304
1312
  try {
1305
1313
  const snapshot = normalizeBotsSnapshot(await invoke(
1306
- FEISHU_ENDPOINTS.setAgentPreset,
1307
- { botId, agentPreset },
1314
+ endpoint,
1315
+ { botId, ...payload },
1308
1316
  ));
1309
1317
  if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
1310
1318
  mergeSnapshot(snapshot);
@@ -1521,7 +1529,12 @@ export function FeishuSettingsTab({ rpcCall }) {
1521
1529
  onReconnect: (bot) => void reconnectOneBot(bot),
1522
1530
  onRepairCallback: repairCallback,
1523
1531
  onWorkspaceSave: saveWorkspace,
1524
- onAgentPresetSave: saveAgentPreset,
1532
+ onAgentPresetSave: (connection, agentPreset) => saveBotSetting(
1533
+ connection, "preset", FEISHU_ENDPOINTS.setAgentPreset, { agentPreset },
1534
+ ),
1535
+ onContextEnhancementSave: (connection, config) => saveBotSetting(
1536
+ connection, "context-enhancement", FEISHU_ENDPOINTS.setContextEnhancement, { config },
1537
+ ),
1525
1538
  onGroupResponseModeSave: saveGroupResponseMode,
1526
1539
  onGroupMessagePermissionAuthorize: authorizeGroupMessages,
1527
1540
  onRequestRemove: requestRemove,
@@ -1,5 +1,6 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
2
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
+ import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
3
4
 
4
5
  export const QQ_RPC_CHANNEL = '/qq';
5
6
 
@@ -13,6 +14,7 @@ export const QQ_ENDPOINTS = Object.freeze({
13
14
  deleteBot: 'bot.delete',
14
15
  setWorkspace: 'bot.workspace.set',
15
16
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
17
+ setContextEnhancement: 'bot.context-enhancement.set',
16
18
  });
17
19
 
18
20
  const PROVISION_STATES = new Set(['starting', 'pending', 'refreshing', 'connecting', 'connected', 'failed', 'cancelled']);
@@ -87,6 +89,7 @@ function normalizeBot(value) {
87
89
  state: connected ? 'connected' : state,
88
90
  workspace: text(value.workspace, '', 4_096),
89
91
  agentPreset: normalizeAgentPresetId(value.agentPreset),
92
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
90
93
  bot: {
91
94
  name: text(value.bot?.name, 'QQ机器人', 100),
92
95
  appIdMasked: text(value.bot?.appIdMasked, '应用标识已安全保存', 140),
@@ -4,6 +4,7 @@ import { QqLogoGlyph } from '../../channel-logos.js';
4
4
  import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
5
5
  import { h } from '../../i18n.js';
6
6
  import { WorkspaceEditor } from '../../workspace-editor.js';
7
+ import { ContextEnhancementEditor } from '../../context-enhancement.js';
7
8
  import {
8
9
  AgentPresetCatalogContext,
9
10
  AgentPresetEditor,
@@ -166,6 +167,7 @@ export function AccountCard({
166
167
  onReconnect,
167
168
  onWorkspaceSave,
168
169
  onAgentPresetSave,
170
+ onContextEnhancementSave,
169
171
  onRequestRemove,
170
172
  onConfirmRemove,
171
173
  onCancelRemove,
@@ -198,6 +200,11 @@ export function AccountCard({
198
200
  disabled: Boolean(busy),
199
201
  onSave: onAgentPresetSave,
200
202
  }),
203
+ h(ContextEnhancementEditor, {
204
+ config: account.contextEnhancement,
205
+ disabled: Boolean(busy),
206
+ onSave: onContextEnhancementSave,
207
+ }),
201
208
  h('div', { className: 'ddt-accountFooter dim-cardFooter' },
202
209
  h('div', { className: 'dim-cardFooterLayout' },
203
210
  h('div', { className: 'ddt-actions dim-cardActions' },
@@ -468,6 +475,12 @@ export function QqSettingsTab({ rpcCall }) {
468
475
  QQ_ENDPOINTS.setAgentPreset,
469
476
  { botId: account.botId, agentPreset },
470
477
  ),
478
+ onContextEnhancementSave: (config) => botAction(
479
+ account,
480
+ 'context-enhancement',
481
+ QQ_ENDPOINTS.setContextEnhancement,
482
+ { botId: account.botId, config },
483
+ ),
471
484
  onRequestRemove: () => setRemoveTarget(account.botId),
472
485
  onCancelRemove: () => setRemoveTarget(null),
473
486
  onConfirmRemove: async () => {
@@ -1,5 +1,6 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
2
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
+ import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
3
4
 
4
5
  const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
5
6
 
@@ -29,6 +30,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
29
30
  deleteBot: 'bot.delete',
30
31
  setWorkspace: 'bot.workspace.set',
31
32
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
33
+ setContextEnhancement: 'bot.context-enhancement.set',
32
34
  });
33
35
 
34
36
  export function createTokenChannelApi(channel, connectionSummary, {
@@ -57,6 +59,7 @@ export function createTokenChannelApi(channel, connectionSummary, {
57
59
  state: connected ? 'connected' : state,
58
60
  workspace: text(value.workspace, '', 4_096),
59
61
  agentPreset: normalizeAgentPresetId(value.agentPreset),
62
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
60
63
  bot: {
61
64
  name: text(value.bot?.name, `${channel}机器人`, 100),
62
65
  username: text(value.bot?.username, '', 100),
@@ -4,6 +4,7 @@ import { CredentialActionIcon, CredentialBindingPanel } from '../../credential-b
4
4
  import { h } from '../../i18n.js';
5
5
  import { installDingtalkStyles } from '../dingtalk/styles.js';
6
6
  import { WorkspaceEditor } from '../../workspace-editor.js';
7
+ import { ContextEnhancementEditor } from '../../context-enhancement.js';
7
8
  import {
8
9
  AgentPresetCatalogContext,
9
10
  AgentPresetEditor,
@@ -73,7 +74,7 @@ export function createTokenChannelSettings(definition) {
73
74
  accountSettingsEndpoint = null,
74
75
  } = definition;
75
76
 
76
- function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
77
+ function AccountCard({ account, busy, testNotice, removing, onReconnect, onWorkspaceSave, onAgentPresetSave, onContextEnhancementSave, onAccountSettingsSave, onRequestRemove, onConfirmRemove, onCancelRemove }) {
77
78
  const state = busy === 'reconnect' ? 'connecting' : account.state;
78
79
  const tone = account.connected ? 'success' : state === 'error' ? 'error' : 'warning';
79
80
  const stateLabel = account.connected ? '运行正常' : state === 'connecting' ? '正在连接' : '连接未就绪';
@@ -105,6 +106,11 @@ export function createTokenChannelSettings(definition) {
105
106
  disabled: Boolean(busy),
106
107
  onSave: onAgentPresetSave,
107
108
  }),
109
+ h(ContextEnhancementEditor, {
110
+ config: account.contextEnhancement,
111
+ disabled: Boolean(busy),
112
+ onSave: onContextEnhancementSave,
113
+ }),
108
114
  AccountSettings ? h(AccountSettings, {
109
115
  account,
110
116
  busy: Boolean(busy),
@@ -309,6 +315,12 @@ export function createTokenChannelSettings(definition) {
309
315
  endpoints.setAgentPreset,
310
316
  { botId: account.botId, agentPreset },
311
317
  ),
318
+ onContextEnhancementSave: (config) => botAction(
319
+ account,
320
+ 'context-enhancement',
321
+ endpoints.setContextEnhancement,
322
+ { botId: account.botId, config },
323
+ ),
312
324
  onAccountSettingsSave: AccountSettings && accountSettingsEndpoint
313
325
  ? (payload) => botAction(
314
326
  account,
@@ -1,5 +1,6 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
2
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
+ import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
3
4
 
4
5
  export const WECOM_RPC_CHANNEL = '/wecom';
5
6
 
@@ -13,6 +14,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
13
14
  deleteBot: 'bot.delete',
14
15
  setWorkspace: 'bot.workspace.set',
15
16
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
17
+ setContextEnhancement: 'bot.context-enhancement.set',
16
18
  });
17
19
 
18
20
  const PROVISION_STATES = new Set(['starting', 'pending', 'refreshing', 'connecting', 'connected', 'failed', 'cancelled']);
@@ -96,6 +98,7 @@ function normalizeBot(value) {
96
98
  state: connected ? 'connected' : state,
97
99
  workspace: text(value.workspace, '', 4_096),
98
100
  agentPreset: normalizeAgentPresetId(value.agentPreset),
101
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
99
102
  bot: {
100
103
  name: text(value.bot?.name, '企业微信机器人', 100),
101
104
  appIdMasked: text(value.bot?.appIdMasked, '应用标识已安全保存', 140),
@@ -4,6 +4,7 @@ import { WecomLogoGlyph } from '../../channel-logos.js';
4
4
  import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
5
5
  import { h } from '../../i18n.js';
6
6
  import { WorkspaceEditor } from '../../workspace-editor.js';
7
+ import { ContextEnhancementEditor } from '../../context-enhancement.js';
7
8
  import {
8
9
  AgentPresetCatalogContext,
9
10
  AgentPresetEditor,
@@ -165,6 +166,7 @@ export function AccountCard({
165
166
  onReconnect,
166
167
  onWorkspaceSave,
167
168
  onAgentPresetSave,
169
+ onContextEnhancementSave,
168
170
  onRequestRemove,
169
171
  onConfirmRemove,
170
172
  onCancelRemove,
@@ -197,6 +199,11 @@ export function AccountCard({
197
199
  disabled: Boolean(busy),
198
200
  onSave: onAgentPresetSave,
199
201
  }),
202
+ h(ContextEnhancementEditor, {
203
+ config: account.contextEnhancement,
204
+ disabled: Boolean(busy),
205
+ onSave: onContextEnhancementSave,
206
+ }),
200
207
  h('div', { className: 'ddt-accountFooter dim-cardFooter' },
201
208
  h('div', { className: 'dim-cardFooterLayout' },
202
209
  h('div', { className: 'ddt-actions dim-cardActions' },
@@ -499,6 +506,12 @@ export function WecomSettingsTab({ rpcCall }) {
499
506
  WECOM_ENDPOINTS.setAgentPreset,
500
507
  { botId: account.botId, agentPreset },
501
508
  ),
509
+ onContextEnhancementSave: (config) => botAction(
510
+ account,
511
+ 'context-enhancement',
512
+ WECOM_ENDPOINTS.setContextEnhancement,
513
+ { botId: account.botId, config },
514
+ ),
502
515
  onRequestRemove: () => setRemoveTarget(account.botId),
503
516
  onCancelRemove: () => setRemoveTarget(null),
504
517
  onConfirmRemove: async () => {
@@ -1,5 +1,6 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
2
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
+ import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
3
4
 
4
5
  export const WEIXIN_RPC_CHANNEL = '/weixin';
5
6
  export const WEIXIN_ENDPOINTS = Object.freeze({
@@ -12,6 +13,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
12
13
  deleteBot: 'bot.delete',
13
14
  setWorkspace: 'bot.workspace.set',
14
15
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
16
+ setContextEnhancement: 'bot.context-enhancement.set',
15
17
  });
16
18
 
17
19
  const ACCOUNT_STATES = new Set(['connected', 'connecting', 'offline', 'error']);
@@ -121,6 +123,7 @@ function normalizeBot(value) {
121
123
  configured: value.configured === true,
122
124
  workspace: string(value.workspace).slice(0, 4_096),
123
125
  agentPreset: normalizeAgentPresetId(value.agentPreset),
126
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
124
127
  bot: {
125
128
  name: string(value.bot.name, '微信机器人'),
126
129
  accountIdMasked: string(value.bot.accountIdMasked, '已安全保存'),
@@ -15,6 +15,7 @@ import {
15
15
  } from './api.js';
16
16
  import { createPollScheduler, useAnimationFrameScheduler } from '../../lifecycle.js';
17
17
  import { WorkspaceEditor } from '../../workspace-editor.js';
18
+ import { ContextEnhancementEditor } from '../../context-enhancement.js';
18
19
  import {
19
20
  AgentPresetCatalogContext,
20
21
  AgentPresetEditor,
@@ -207,6 +208,7 @@ export function AccountCard({
207
208
  onReconnect,
208
209
  onWorkspaceSave,
209
210
  onAgentPresetSave,
211
+ onContextEnhancementSave,
210
212
  onRequestRemove,
211
213
  onConfirmRemove,
212
214
  onCancelRemove,
@@ -238,6 +240,12 @@ export function AccountCard({
238
240
  disabled: Boolean(busy),
239
241
  onSave: onAgentPresetSave,
240
242
  }),
243
+ h(ContextEnhancementEditor, {
244
+ config: account.contextEnhancement,
245
+ groupSupported: false,
246
+ disabled: Boolean(busy),
247
+ onSave: onContextEnhancementSave,
248
+ }),
241
249
  h('div', { className: 'dxw-accountFooter dim-cardFooter' },
242
250
  h('div', { className: 'dim-cardFooterLayout' },
243
251
  h('div', { className: 'dxw-actions dim-cardActions' },
@@ -280,6 +288,7 @@ function AccountList(props) {
280
288
  onReconnect: () => props.onReconnect(account),
281
289
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
282
290
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
291
+ onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
283
292
  onRequestRemove: () => props.onRequestRemove(account),
284
293
  onConfirmRemove: () => props.onConfirmRemove(account),
285
294
  onCancelRemove: props.onCancelRemove,
@@ -594,13 +603,13 @@ export function WeixinSettingsTab({ rpcCall }) {
594
603
  }
595
604
  }, [invoke, loadStatus, setBotBusy, workspaceFence]);
596
605
 
597
- const saveAgentPreset = React.useCallback(async (account, agentPreset) => {
606
+ const saveBotSetting = React.useCallback(async (account, operation, endpoint, payload) => {
598
607
  const snapshotVersion = workspaceFence.beginMutation();
599
- setBotBusy(account.botId, 'preset');
608
+ setBotBusy(account.botId, operation);
600
609
  try {
601
610
  const snapshot = normalizeSnapshot(await invoke(
602
- WEIXIN_ENDPOINTS.setAgentPreset,
603
- { botId: account.botId, agentPreset },
611
+ endpoint,
612
+ { botId: account.botId, ...payload },
604
613
  ));
605
614
  if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
606
615
  setModel({
@@ -703,7 +712,12 @@ export function WeixinSettingsTab({ rpcCall }) {
703
712
  removeTarget,
704
713
  onReconnect: (account) => void reconnect(account),
705
714
  onWorkspaceSave: saveWorkspace,
706
- onAgentPresetSave: saveAgentPreset,
715
+ onAgentPresetSave: (account, agentPreset) => saveBotSetting(
716
+ account, 'preset', WEIXIN_ENDPOINTS.setAgentPreset, { agentPreset },
717
+ ),
718
+ onContextEnhancementSave: (account, config) => saveBotSetting(
719
+ account, 'context-enhancement', WEIXIN_ENDPOINTS.setContextEnhancement, { config },
720
+ ),
707
721
  onRequestRemove: (account) => setRemoveTarget(account.botId),
708
722
  onConfirmRemove: (account) => void remove(account),
709
723
  onCancelRemove: () => setRemoveTarget(null),
@@ -1,5 +1,6 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
2
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
+ import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
3
4
 
4
5
  export const WHATSAPP_RPC_CHANNEL = '/whatsapp';
5
6
 
@@ -13,6 +14,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
13
14
  setAccessPolicy: 'bot.access-policy.set',
14
15
  setWorkspace: 'bot.workspace.set',
15
16
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
17
+ setContextEnhancement: 'bot.context-enhancement.set',
16
18
  });
17
19
 
18
20
  const PROVISION_STATES = new Set(['starting', 'pending', 'connecting', 'connected', 'failed', 'cancelled']);
@@ -88,6 +90,7 @@ function normalizeBot(value) {
88
90
  state: connected ? 'connected' : state,
89
91
  workspace: text(value.workspace, '', 4_096),
90
92
  agentPreset: normalizeAgentPresetId(value.agentPreset),
93
+ contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
91
94
  accessPolicy: {
92
95
  accessMode: ['self-only', 'private-allowlist', 'open'].includes(
93
96
  value.accessPolicy?.accessMode,
@@ -4,6 +4,7 @@ import { WhatsappLogoGlyph } from '../../channel-logos.js';
4
4
  import { QrActionIcon } from '../../credential-binding.js';
5
5
  import { h } from '../../i18n.js';
6
6
  import { WorkspaceEditor } from '../../workspace-editor.js';
7
+ import { ContextEnhancementEditor } from '../../context-enhancement.js';
7
8
  import {
8
9
  AgentPresetCatalogContext,
9
10
  AgentPresetEditor,
@@ -297,6 +298,7 @@ export function WhatsappAccountCard({
297
298
  onReconnect,
298
299
  onWorkspaceSave,
299
300
  onAgentPresetSave,
301
+ onContextEnhancementSave,
300
302
  onAccessPolicySave,
301
303
  onRequestRemove,
302
304
  onConfirmRemove,
@@ -334,6 +336,11 @@ export function WhatsappAccountCard({
334
336
  disabled: Boolean(busy),
335
337
  onSave: onAgentPresetSave,
336
338
  }),
339
+ h(ContextEnhancementEditor, {
340
+ config: account.contextEnhancement,
341
+ disabled: Boolean(busy),
342
+ onSave: onContextEnhancementSave,
343
+ }),
337
344
  h(WhatsappAccessSettings, {
338
345
  account,
339
346
  busy: Boolean(busy),
@@ -596,6 +603,12 @@ export function WhatsappSettingsTab({ rpcCall }) {
596
603
  WHATSAPP_ENDPOINTS.setAgentPreset,
597
604
  { botId: account.botId, agentPreset },
598
605
  ),
606
+ onContextEnhancementSave: (config) => botAction(
607
+ account,
608
+ 'context-enhancement',
609
+ WHATSAPP_ENDPOINTS.setContextEnhancement,
610
+ { botId: account.botId, config },
611
+ ),
599
612
  onAccessPolicySave: (accessPolicy) => botAction(
600
613
  account,
601
614
  'access',