@xmanrui/dsh-im 4.9.1 → 4.11.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 (72) hide show
  1. package/PROACTIVE_DELIVERY.en.md +23 -1
  2. package/PROACTIVE_DELIVERY.md +23 -1
  3. package/README.en.md +5 -1
  4. package/README.md +6 -2
  5. package/lib/client.js +2077 -673
  6. package/lib/index.js +277 -272
  7. package/package.json +13 -1
  8. package/plugin-src/client/channel-card-meta.js +9 -1
  9. package/plugin-src/client/channels/dingtalk/api.js +4 -0
  10. package/plugin-src/client/channels/dingtalk/index.js +25 -2
  11. package/plugin-src/client/channels/feishu/api.js +6 -0
  12. package/plugin-src/client/channels/feishu/group-settings.js +581 -0
  13. package/plugin-src/client/channels/feishu/index.js +26 -150
  14. package/plugin-src/client/channels/qq/api.js +4 -0
  15. package/plugin-src/client/channels/qq/index.js +25 -2
  16. package/plugin-src/client/channels/shared/token-api.js +4 -0
  17. package/plugin-src/client/channels/shared/token-channel.js +25 -3
  18. package/plugin-src/client/channels/wecom/api.js +4 -0
  19. package/plugin-src/client/channels/wecom/index.js +25 -2
  20. package/plugin-src/client/channels/weixin/api.js +4 -0
  21. package/plugin-src/client/channels/weixin/index.js +25 -2
  22. package/plugin-src/client/channels/whatsapp/api.js +4 -0
  23. package/plugin-src/client/channels/whatsapp/index.js +24 -2
  24. package/plugin-src/client/delivery-settings.js +73 -5
  25. package/plugin-src/client/global-settings.js +341 -0
  26. package/plugin-src/client/i18n.js +49 -0
  27. package/plugin-src/client/index.js +47 -6
  28. package/plugin-src/client/model-setting.js +104 -0
  29. package/plugin-src/client/styles.js +99 -0
  30. package/plugin-src/host/channels/dingtalk/production.mjs +15 -0
  31. package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
  32. package/plugin-src/host/channels/feishu/production.mjs +17 -0
  33. package/plugin-src/host/channels/feishu/rpc.mjs +32 -0
  34. package/plugin-src/host/channels/qq/production.mjs +15 -0
  35. package/plugin-src/host/channels/qq/rpc.mjs +11 -0
  36. package/plugin-src/host/channels/shared/model-setting-rpc.mjs +19 -0
  37. package/plugin-src/host/channels/shared/production.mjs +15 -0
  38. package/plugin-src/host/channels/shared/rpc.mjs +9 -0
  39. package/plugin-src/host/channels/shared/workspace-rpc.mjs +2 -0
  40. package/plugin-src/host/channels/slack/production.mjs +15 -0
  41. package/plugin-src/host/channels/slack/rpc.mjs +9 -0
  42. package/plugin-src/host/channels/wecom/production.mjs +15 -0
  43. package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
  44. package/plugin-src/host/channels/weixin/production.mjs +15 -0
  45. package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
  46. package/plugin-src/host/channels/whatsapp/production.mjs +15 -0
  47. package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
  48. package/plugin-src/host/delivery-adapter.mjs +142 -3
  49. package/plugin-src/host/delivery-rpc.mjs +12 -0
  50. package/plugin-src/host/delivery-service.mjs +125 -3
  51. package/plugin-src/host/delivery-suggestions.mjs +46 -0
  52. package/plugin-src/host/harness-session-coordinator.mjs +32 -10
  53. package/plugin-src/host/inbound-ttl-rpc.mjs +83 -0
  54. package/plugin-src/host/inbound-ttl-runtime.mjs +85 -0
  55. package/plugin-src/host/inbound-ttl-service.mjs +179 -0
  56. package/plugin-src/host/index.mjs +26 -1
  57. package/plugin-src/host/modern-harness-api.mjs +58 -2
  58. package/plugin-src/host/session-sync-coordinator.mjs +217 -0
  59. package/scripts/verify-package.mjs +12 -6
  60. package/src/channels/feishu/bridge.mjs +164 -4
  61. package/src/channels/feishu/feishu-channel.mjs +45 -10
  62. package/src/channels/feishu/feishu-runtime.mjs +9 -0
  63. package/src/channels/feishu/message-utils.mjs +13 -0
  64. package/src/channels/feishu/multi-bot-controller.mjs +16 -0
  65. package/src/channels/feishu/plugin-config-store.mjs +1 -0
  66. package/src/channels/feishu/state-store.mjs +25 -0
  67. package/src/channels/shared/bot-workspace-store.mjs +291 -38
  68. package/src/channels/shared/harness-client.mjs +124 -43
  69. package/src/channels/shared/inbound-file.mjs +117 -2
  70. package/src/channels/shared/inbound-ttl-store.mjs +110 -0
  71. package/src/channels/shared/inbound-ttl.mjs +22 -0
  72. package/src/channels/shared/model-setting.mjs +110 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmanrui/dsh-im",
3
- "version": "4.9.1",
3
+ "version": "4.11.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",
@@ -87,6 +87,18 @@
87
87
  "@deepseek-ai/dsh-client-locale"
88
88
  ],
89
89
  "platform": "web"
90
+ },
91
+ "compatibility": {
92
+ "dsh": "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.3-alpha.1",
93
+ "dshReleases": {
94
+ "0.1.2-alpha.4": "compatible",
95
+ "0.1.2-alpha.5": "compatible",
96
+ "0.1.2-rc.1": "compatible",
97
+ "0.1.3-alpha.1": "compatible"
98
+ },
99
+ "profiles": [
100
+ "web"
101
+ ]
90
102
  }
91
103
  },
92
104
  "scripts": {
@@ -22,7 +22,14 @@ function SettingsGlyph() {
22
22
  h('path', { d: 'M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06-2.83 2.83-.06-.06a1.7 1.7 0 0 0-1.88-.34 1.7 1.7 0 0 0-1.03 1.55V21h-4v-.08A1.7 1.7 0 0 0 8.97 19.4a1.7 1.7 0 0 0-1.88.34l-.06.06-2.83-2.83.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.52-1.03H3v-4h.08A1.7 1.7 0 0 0 4.6 8.97a1.7 1.7 0 0 0-.34-1.88l-.06-.06L7.03 4.2l.06.06a1.7 1.7 0 0 0 1.88.34A1.7 1.7 0 0 0 10 3.08V3h4v.08a1.7 1.7 0 0 0 1.03 1.52 1.7 1.7 0 0 0 1.88-.34l.06-.06 2.83 2.83-.06.06a1.7 1.7 0 0 0-.34 1.88A1.7 1.7 0 0 0 20.92 10H21v4h-.08A1.7 1.7 0 0 0 19.4 15Z' }));
23
23
  }
24
24
 
25
- export function BotSettingsButton({ channel, botId, botName, connected, accessPolicy }) {
25
+ export function BotSettingsButton({
26
+ channel,
27
+ botId,
28
+ botName,
29
+ connected,
30
+ accessPolicy,
31
+ channelSettings,
32
+ }) {
26
33
  const { openBotSettings } = React.useContext(BotSettingsContext);
27
34
  const tooltipId = React.useId();
28
35
  return h('span', { className: 'dim-botSettingsAction' },
@@ -33,6 +40,7 @@ export function BotSettingsButton({ channel, botId, botName, connected, accessPo
33
40
  'aria-label': '更多机器人设置',
34
41
  'aria-describedby': tooltipId,
35
42
  onClick: () => openBotSettings?.({
43
+ ...(channelSettings && typeof channelSettings === 'object' ? channelSettings : {}),
36
44
  channel,
37
45
  botId,
38
46
  botName,
@@ -1,4 +1,5 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
+ import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
2
3
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
4
  import { normalizeAccessPolicy } from '../../../../src/channels/shared/access-policy.mjs';
4
5
  import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
@@ -14,6 +15,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
14
15
  reconnectBot: 'bot.reconnect',
15
16
  deleteBot: 'bot.delete',
16
17
  setWorkspace: 'bot.workspace.set',
18
+ setModel: SET_MODEL_ENDPOINT,
17
19
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
18
20
  setContextEnhancement: 'bot.context-enhancement.set',
19
21
  setAccessPolicy: 'bot.access-policy.set',
@@ -181,6 +183,7 @@ function normalizeBot(value) {
181
183
  connected,
182
184
  configured: value.configured !== false,
183
185
  workspace: optionalString(value.workspace, 4_096) ?? '',
186
+ model: normalizeModelSelection(value.model),
184
187
  agentPreset: normalizeAgentPresetId(value.agentPreset),
185
188
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
186
189
  ...(Object.hasOwn(value, 'accessPolicy')
@@ -231,6 +234,7 @@ export function normalizeSnapshot(value) {
231
234
  provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
232
235
  testMessage: normalizeTestMessage(source.testMessage),
233
236
  agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
237
+ modelCatalog: normalizeModelCatalog(source.modelCatalog),
234
238
  };
235
239
  }
236
240
 
@@ -9,6 +9,11 @@ import {
9
9
  AgentPresetEditor,
10
10
  EMPTY_AGENT_PRESET_CATALOG,
11
11
  } from '../../agent-preset.js';
12
+ import {
13
+ EMPTY_MODEL_CATALOG,
14
+ ModelCatalogContext,
15
+ ModelEditor,
16
+ } from '../../model-setting.js';
12
17
  import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
13
18
  import {
14
19
  BotSettingsButton,
@@ -238,6 +243,7 @@ export function AccountCard({
238
243
  removing,
239
244
  onReconnect,
240
245
  onWorkspaceSave,
246
+ onModelSave,
241
247
  onAgentPresetSave,
242
248
  onContextEnhancementSave,
243
249
  onRequestRemove,
@@ -277,6 +283,11 @@ export function AccountCard({
277
283
  disabled: Boolean(busy),
278
284
  onSave: onWorkspaceSave,
279
285
  }),
286
+ h(ModelEditor, {
287
+ model: account.model,
288
+ disabled: Boolean(busy),
289
+ onSave: onModelSave,
290
+ }),
280
291
  h(AgentPresetEditor, {
281
292
  agentPreset: account.agentPreset,
282
293
  disabled: Boolean(busy),
@@ -327,6 +338,7 @@ function AccountList(props) {
327
338
  removing: props.removeTarget === account.botId,
328
339
  onReconnect: () => props.onReconnect(account),
329
340
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
341
+ onModelSave: (model) => props.onModelSave(account, model),
330
342
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
331
343
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
332
344
  onRequestRemove: () => props.onRequestRemove(account),
@@ -341,6 +353,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
341
353
  const [model, setModel] = React.useState({
342
354
  phase: 'loading', bots: [], totals: EMPTY_TOTALS, revision: 0, error: null,
343
355
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
356
+ modelCatalog: EMPTY_MODEL_CATALOG,
344
357
  });
345
358
  const [provision, setProvision] = React.useState(null);
346
359
  const [busy, setBusy] = React.useState(false);
@@ -448,6 +461,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
448
461
  revision: snapshot.revision,
449
462
  error: null,
450
463
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
464
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
451
465
  });
452
466
  discardStaleFeedback(snapshot);
453
467
  if (restoreProvisioning && snapshot.provisioning) {
@@ -564,6 +578,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
564
578
  revision: snapshot.revision,
565
579
  error: null,
566
580
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
581
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
567
582
  });
568
583
  discardStaleFeedback(snapshot);
569
584
  }
@@ -705,6 +720,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
705
720
  revision: snapshot.revision,
706
721
  error: null,
707
722
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
723
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
708
724
  });
709
725
  discardStaleFeedback(snapshot);
710
726
  }
@@ -771,6 +787,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
771
787
  revision: snapshot.revision,
772
788
  error: null,
773
789
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
790
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
774
791
  });
775
792
  discardStaleFeedback(snapshot);
776
793
  }
@@ -797,6 +814,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
797
814
  revision: snapshot.revision,
798
815
  error: null,
799
816
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
817
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
800
818
  });
801
819
  discardStaleFeedback(snapshot);
802
820
  }
@@ -859,7 +877,9 @@ export function DingtalkSettingsTab({ rpcCall }) {
859
877
  })
860
878
  : null;
861
879
 
862
- return h(AgentPresetCatalogContext.Provider, {
880
+ return h(ModelCatalogContext.Provider, {
881
+ value: model.modelCatalog ?? EMPTY_MODEL_CATALOG,
882
+ }, h(AgentPresetCatalogContext.Provider, {
863
883
  value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
864
884
  }, h('section', { className: 'ddt-page dim-channelPage', 'aria-label': '钉钉设置' },
865
885
  h(Heading, {
@@ -897,6 +917,9 @@ export function DingtalkSettingsTab({ rpcCall }) {
897
917
  removeTarget,
898
918
  onReconnect: (account) => void reconnect(account),
899
919
  onWorkspaceSave: saveWorkspace,
920
+ onModelSave: (account, selectedModel) => saveBotSetting(
921
+ account, 'model', DINGTALK_ENDPOINTS.setModel, { model: selectedModel },
922
+ ),
900
923
  onAgentPresetSave: (account, agentPreset) => saveBotSetting(
901
924
  account, 'preset', DINGTALK_ENDPOINTS.setAgentPreset, { agentPreset },
902
925
  ),
@@ -907,5 +930,5 @@ export function DingtalkSettingsTab({ rpcCall }) {
907
930
  onConfirmRemove: (account) => void remove(account),
908
931
  onCancelRemove: () => setRemoveTarget(null),
909
932
  })
910
- : null)));
933
+ : null))));
911
934
  }
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId } from "../../agent-preset.js";
10
+ import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from "../../model-setting.js";
10
11
  import { normalizeLastMessageError } from "../../last-message-error.js";
11
12
  import { normalizeAccessPolicy } from "../../../../src/channels/shared/access-policy.mjs";
12
13
  import { normalizeContextEnhancementConfig } from "../../../../src/channels/shared/context-enhancement.mjs";
@@ -25,10 +26,12 @@ export const FEISHU_ENDPOINTS = Object.freeze({
25
26
  disconnectBot: "bot.disconnect",
26
27
  deleteBot: "bot.delete",
27
28
  setWorkspace: "bot.workspace.set",
29
+ setModel: SET_MODEL_ENDPOINT,
28
30
  setAgentPreset: "bot.preset.set",
29
31
  setContextEnhancement: "bot.context-enhancement.set",
30
32
  setAccessPolicy: "bot.access-policy.set",
31
33
  setGroupResponseMode: "bot.group-response-mode.set",
34
+ setGroupTopicReply: "bot.group-topic-reply.set",
32
35
  // Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
33
36
  testConnection: "connection.test",
34
37
  disconnect: "connection.disconnect",
@@ -206,12 +209,14 @@ export function normalizeBotConnection(value, fallbackBotId) {
206
209
  connected,
207
210
  configured: value.configured !== false,
208
211
  workspace: optionalString(value.workspace)?.slice(0, 4_096) ?? "",
212
+ model: normalizeModelSelection(value.model),
209
213
  agentPreset: normalizeAgentPresetId(value.agentPreset),
210
214
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
211
215
  ...(Object.hasOwn(value, "accessPolicy")
212
216
  ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) }
213
217
  : {}),
214
218
  groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
219
+ groupTopicReply: value.groupTopicReply === true,
215
220
  groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
216
221
  bot: normalizeBot(value.bot),
217
222
  health: normalizeHealth(value.health, connected),
@@ -270,6 +275,7 @@ export function normalizeBotsSnapshot(value) {
270
275
  : undefined,
271
276
  error: normalizeError(value.error),
272
277
  agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
278
+ modelCatalog: normalizeModelCatalog(value.modelCatalog),
273
279
  };
274
280
  }
275
281