@xmanrui/dsh-im 4.2.0 → 4.3.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/lib/client.js CHANGED
@@ -571,7 +571,7 @@ var React23 = __toESM(require("react"), 1);
571
571
  // package.json
572
572
  var package_default = {
573
573
  name: "@xmanrui/dsh-im",
574
- version: "4.2.0",
574
+ version: "4.3.0",
575
575
  description: "\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
576
576
  keywords: [
577
577
  "deepseek-harness",
@@ -670,7 +670,8 @@ var package_default = {
670
670
  "@tencent-connect/qqbot-nodejs": "1.0.4",
671
671
  "@wecom/aibot-node-sdk": "1.0.7",
672
672
  "dingtalk-stream": "2.1.4",
673
- qrcode: "1.5.4"
673
+ qrcode: "1.5.4",
674
+ undici: "7.29.0"
674
675
  },
675
676
  devDependencies: {
676
677
  "@deepseek-ai/cordis": "4.0.1",
@@ -1049,31 +1050,44 @@ var EN = Object.freeze({
1049
1050
  "\u7FA4\u804A\u548C\u79C1\u804A": "Groups and direct",
1050
1051
  "\u5173\u95ED\u5F39\u7A97": "Close dialog",
1051
1052
  "\u67E5\u770B\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BF4\u660E": "View context enhancement details",
1053
+ "\u4E0A\u4E0B\u6587\u589E\u5F3A\u8303\u56F4": "Context enhancement scope",
1052
1054
  "\u542F\u7528\u8303\u56F4": "Enable in",
1053
- "\u7FA4\u804A\u4E2D\u542F\u7528": "Enable in group chats",
1054
- "\u79C1\u804A\u4E2D\u542F\u7528": "Enable in direct chats",
1055
+ "\u542F\u7528": "Enabled",
1055
1056
  "\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09": "(This channel does not support group chats)",
1056
1057
  "\u6765\u6E90\u5B57\u6BB5": "Source fields",
1057
1058
  "\u67E5\u770B\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E": "View source field details",
1059
+ "\u67E5\u770B\u7FA4\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E": "View group source field details",
1060
+ "\u67E5\u770B\u79C1\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E": "View direct source field details",
1058
1061
  "\u6E20\u9053": "Channel",
1059
1062
  "\u4F1A\u8BDD\u7C7B\u578B": "Conversation type",
1060
1063
  "\u53D1\u9001\u8005\u6807\u8BC6": "Sender ID",
1061
1064
  "\u53D1\u9001\u8005\u6635\u79F0": "Sender name",
1062
1065
  "\u67E5\u770B\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E": "View sender name field details",
1066
+ "\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E": "View group sender name field details",
1067
+ "\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E": "View direct sender name field details",
1063
1068
  "\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002": "This field is not available on every channel. If the current message has no sender name, <dsh_im_source> omits senderName even when the field is selected.",
1064
1069
  "\u673A\u5668\u4EBA\u6807\u8BC6": "Bot ID",
1065
1070
  "\u589E\u5F3A\u63D0\u793A\u8BCD": "Guidance",
1066
1071
  "\u67E5\u770B\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E": "View guidance instructions",
1072
+ "\u67E5\u770B\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E": "View group guidance instructions",
1073
+ "\u67E5\u770B\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E": "View direct guidance instructions",
1067
1074
  "\u4F7F\u7528\u8BF4\u660E": "How to use",
1068
1075
  "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528 <dsh_im_source> \u4E2D\u5DF2\u9009\u62E9\u7684\u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002": "Tell the model how to use the selected fields in <dsh_im_source>. Enter only the body; the plugin adds paired <dsh_im_source_guidance> tags.",
1069
1076
  "\u751F\u6548\u89C4\u5219": "Behavior",
1070
1077
  "\u9690\u79C1\u63D0\u793A": "Privacy",
1071
1078
  "\u4F7F\u7528\u793A\u4F8B": "Example",
1072
1079
  "\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 <dsh_im_source> \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002\nconversationType\u662F\u7FA4\u804A\u65F6\u56DE\u590D\u4E25\u8083\u4E00\u70B9\uFF0CconversationType\u662F\u79C1\u804A\u65F6\u56DE\u590D\u4E00\u5B9A\u8981\u5E7D\u9ED8\u641E\u7B11\uFF0C\u50CF\u5468\u661F\u9A70\u7684\u7535\u5F71\u4E00\u6837\u641E\u7B11": "Understand the source only from fields actually present in <dsh_im_source> for the current message; do not guess or fill in missing fields.\nWhen conversationType is group, reply more seriously. When conversationType is direct, make the reply humorous and funny.",
1080
+ "\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 <dsh_im_source> \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002\n\u5F53\u524D\u6D88\u606F\u6765\u81EA\u7FA4\u804A\uFF0C\u8BF7\u4F7F\u7528\u4E25\u8083\u3001\u514B\u5236\u3001\u7B80\u6D01\u7684\u8868\u8FBE\u65B9\u5F0F\u3002": "Understand the source only from fields actually present in <dsh_im_source> for the current message; do not guess or fill in missing fields.\nThis message is from a group chat. Use a serious, restrained, and concise style.",
1081
+ "\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 <dsh_im_source> \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002\n\u5F53\u524D\u6D88\u606F\u6765\u81EA\u79C1\u804A\uFF0C\u53EF\u4EE5\u4F7F\u7528\u66F4\u8F7B\u677E\u3001\u5E7D\u9ED8\u3001\u8BE6\u7EC6\u7684\u8868\u8FBE\u65B9\u5F0F\u3002": "Understand the source only from fields actually present in <dsh_im_source> for the current message; do not guess or fill in missing fields.\nThis message is from a direct chat. You may use a lighter, more humorous, and detailed style.",
1073
1082
  "\u586B\u5165\u793A\u4F8B": "Use example",
1074
1083
  "\u6E05\u7A7A": "Clear",
1075
1084
  "\u9009\u62E9\u5728\u54EA\u4E9B\u4F1A\u8BDD\u4E2D\u542F\u7528\u3001\u63D0\u4F9B\u54EA\u4E9B\u6765\u6E90\u5B57\u6BB5\uFF0C\u4EE5\u53CA\u5982\u4F55\u4F7F\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u4EC5\u4F7F\u7528\u5DF2\u6709\u6D88\u606F\u5143\u6570\u636E\uFF0C\u4E0D\u67E5\u8BE2\u5E73\u53F0 API\u3002": "Choose which conversations to enhance, which source fields to include, and how to use them. Only existing message metadata is used; no platform APIs are queried.",
1076
1085
  "\u589E\u5F3A\u63D0\u793A\u8BCD\u4E2D\u8BF7\u4F7F\u7528\u5B57\u6BB5\u540D\uFF08\u5982 senderId\u3001conversationType\uFF09\u5F15\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u53EA\u53D1\u9001\u52FE\u9009\u4E14\u5F53\u524D\u6D88\u606F\u4E2D\u53EF\u7528\u7684\u5B57\u6BB5\uFF0C\u4E0D\u4F1A\u989D\u5916\u67E5\u8BE2\u6216\u8865\u5168\u3002": "Reference these values by field name (such as senderId or conversationType) in the guidance. Only selected fields available in the current message are sent; no extra lookups are made.",
1086
+ "\u589E\u5F3A\u63D0\u793A\u8BCD\u4E2D\u8BF7\u4F7F\u7528\u5B57\u6BB5\u540D\uFF08\u5982 senderId\u3001conversationType\uFF09\u5F15\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u53EA\u53D1\u9001\u5F53\u524D\u4F1A\u8BDD\u4E2D\u52FE\u9009\u4E14\u53EF\u7528\u7684\u5B57\u6BB5\uFF0C\u4E0D\u4F1A\u989D\u5916\u67E5\u8BE2\u6216\u8865\u5168\u3002": "Reference these values by field name (such as senderId or conversationType) in the guidance. Only fields selected and available in the current conversation are sent; no extra lookups are made.",
1087
+ "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u7FA4\u804A\u6D88\u606F\u7684 <dsh_im_source> \u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002": "Tell the model how to use <dsh_im_source> fields for the current group message. Enter only the body; the plugin adds paired <dsh_im_source_guidance> tags.",
1088
+ "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u79C1\u804A\u6D88\u606F\u7684 <dsh_im_source> \u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002": "Tell the model how to use <dsh_im_source> fields for the current direct message. Enter only the body; the plugin adds paired <dsh_im_source_guidance> tags.",
1089
+ "\u4EC5\u5728\u7FA4\u804A\u5F00\u5173\u5F00\u542F\u65F6\u4F7F\u7528\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\u4E0D\u518D\u9644\u52A0\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\uFF1B\u6240\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F53\u524D\u573A\u666F\u8BBE\u7F6E\u53D1\u9001\u3002": "Used only when group enhancement is enabled. Clear and save to omit group guidance; selected source fields still follow the group settings.",
1090
+ "\u4EC5\u5728\u79C1\u804A\u5F00\u5173\u5F00\u542F\u65F6\u4F7F\u7528\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\u4E0D\u518D\u9644\u52A0\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\uFF1B\u6240\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F53\u524D\u573A\u666F\u8BBE\u7F6E\u53D1\u9001\u3002": "Used only when direct enhancement is enabled. Clear and save to omit direct guidance; selected source fields still follow the direct settings.",
1077
1091
  "\u53EA\u9700\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\uFF0C\u4E0D\u518D\u9644\u52A0\u589E\u5F3A\u63D0\u793A\u8BCD\uFF0C\u5DF2\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F00\u5173\u8BBE\u7F6E\u53D1\u9001\u3002": "Enter only the body; the plugin adds paired <dsh_im_source_guidance> tags. Clear and save to omit guidance. Selected source fields still follow the conversation switches.",
1078
1092
  "\u53D1\u9001\u8005\u6807\u8BC6\u53EF\u80FD\u5305\u542B\u5E73\u53F0\u7528\u6237 ID \u6216\u7535\u8BDD\u53F7\u7801\u5F62\u5F0F\u7684\u6807\u8BC6\u3002\u5173\u95ED\u5F00\u5173\u4E0D\u4F1A\u5220\u9664\u5DF2\u7ECF\u5199\u5165\u4F1A\u8BDD\u5386\u53F2\u7684\u4FE1\u606F\u3002": "Sender IDs may contain platform user IDs or phone-number-like identifiers. Turning this off does not remove information already saved in conversation history.",
1079
1093
  "\u4E0A\u4E0B\u6587\u589E\u5F3A\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save context enhancement. Try again.",
@@ -1880,26 +1894,39 @@ var CONTEXT_ENHANCEMENT_FIELDS = Object.freeze([
1880
1894
  "botId"
1881
1895
  ]);
1882
1896
  var CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH = 8e3;
1883
- var CONTEXT_GUIDANCE_EXAMPLE = `\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 <dsh_im_source> \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002
1884
- conversationType\u662F\u7FA4\u804A\u65F6\u56DE\u590D\u4E25\u8083\u4E00\u70B9\uFF0CconversationType\u662F\u79C1\u804A\u65F6\u56DE\u590D\u4E00\u5B9A\u8981\u5E7D\u9ED8\u641E\u7B11\uFF0C\u50CF\u5468\u661F\u9A70\u7684\u7535\u5F71\u4E00\u6837\u641E\u7B11`;
1897
+ var CONTEXT_GROUP_GUIDANCE_EXAMPLE = `\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 <dsh_im_source> \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002
1898
+ \u5F53\u524D\u6D88\u606F\u6765\u81EA\u7FA4\u804A\uFF0C\u8BF7\u4F7F\u7528\u4E25\u8083\u3001\u514B\u5236\u3001\u7B80\u6D01\u7684\u8868\u8FBE\u65B9\u5F0F\u3002`;
1899
+ var CONTEXT_DIRECT_GUIDANCE_EXAMPLE = `\u4EC5\u4F9D\u636E\u5F53\u524D\u6D88\u606F\u7684 <dsh_im_source> \u4E2D\u5B9E\u9645\u63D0\u4F9B\u7684\u5B57\u6BB5\u7406\u89E3\u6765\u6E90\uFF1B\u6CA1\u6709\u63D0\u4F9B\u7684\u5B57\u6BB5\u4E0D\u8981\u731C\u6D4B\u6216\u8865\u5168\u3002
1900
+ \u5F53\u524D\u6D88\u606F\u6765\u81EA\u79C1\u804A\uFF0C\u53EF\u4EE5\u4F7F\u7528\u66F4\u8F7B\u677E\u3001\u5E7D\u9ED8\u3001\u8BE6\u7EC6\u7684\u8868\u8FBE\u65B9\u5F0F\u3002`;
1885
1901
  var DEFAULT_CONTEXT_ENHANCEMENT_CONFIG = Object.freeze({
1886
- groupEnabled: false,
1887
- directEnabled: false,
1888
- fields: Object.freeze(["senderId"]),
1889
- guidance: ""
1902
+ group: Object.freeze({
1903
+ enabled: false,
1904
+ fields: Object.freeze(["senderId"]),
1905
+ guidance: ""
1906
+ }),
1907
+ direct: Object.freeze({
1908
+ enabled: false,
1909
+ fields: Object.freeze(["senderId"]),
1910
+ guidance: ""
1911
+ })
1890
1912
  });
1891
- var CONFIG_KEYS = ["groupEnabled", "directEnabled", "fields", "guidance"];
1913
+ var CONFIG_KEYS = ["group", "direct"];
1914
+ var SCOPE_KEYS = ["enabled", "fields", "guidance"];
1915
+ var LEGACY_CONFIG_KEYS = ["groupEnabled", "directEnabled", "fields", "guidance"];
1892
1916
  function invalidConfig(message) {
1893
1917
  const error = new TypeError(message);
1894
1918
  error.code = "context-enhancement-invalid";
1895
1919
  return error;
1896
1920
  }
1897
- function validateContextEnhancementConfig(input) {
1898
- if (!input || typeof input !== "object" || Array.isArray(input) || ![Object.prototype, null].includes(Object.getPrototypeOf(input)) || Reflect.ownKeys(input).length !== CONFIG_KEYS.length || !CONFIG_KEYS.every((key) => Object.hasOwn(input, key))) {
1921
+ function hasExactKeys(input, keys) {
1922
+ return input && typeof input === "object" && !Array.isArray(input) && [Object.prototype, null].includes(Object.getPrototypeOf(input)) && Reflect.ownKeys(input).length === keys.length && keys.every((key) => Object.hasOwn(input, key));
1923
+ }
1924
+ function validateContextEnhancementScope(input) {
1925
+ if (!hasExactKeys(input, SCOPE_KEYS)) {
1899
1926
  throw invalidConfig("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");
1900
1927
  }
1901
- const { groupEnabled, directEnabled, fields, guidance } = input;
1902
- if (typeof groupEnabled !== "boolean" || typeof directEnabled !== "boolean") {
1928
+ const { enabled, fields, guidance } = input;
1929
+ if (typeof enabled !== "boolean") {
1903
1930
  throw invalidConfig("\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");
1904
1931
  }
1905
1932
  if (!Array.isArray(fields) || ![...fields].every((field) => CONTEXT_ENHANCEMENT_FIELDS.includes(field))) {
@@ -1909,17 +1936,46 @@ function validateContextEnhancementConfig(input) {
1909
1936
  throw invalidConfig(`\u589E\u5F3A\u63D0\u793A\u8BCD\u4E0D\u5F97\u8D85\u8FC7 ${CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH} \u4E2A\u5B57\u7B26\u3002`);
1910
1937
  }
1911
1938
  return Object.freeze({
1912
- groupEnabled,
1913
- directEnabled,
1939
+ enabled,
1914
1940
  fields: Object.freeze(CONTEXT_ENHANCEMENT_FIELDS.filter((field) => fields.includes(field))),
1915
1941
  guidance: guidance.trim() ? guidance : ""
1916
1942
  });
1917
1943
  }
1944
+ function validateContextEnhancementConfig(input) {
1945
+ if (!hasExactKeys(input, CONFIG_KEYS)) {
1946
+ throw invalidConfig("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");
1947
+ }
1948
+ return Object.freeze({
1949
+ group: validateContextEnhancementScope(input.group),
1950
+ direct: validateContextEnhancementScope(input.direct)
1951
+ });
1952
+ }
1953
+ function migrateLegacyContextEnhancementConfig(input) {
1954
+ if (!hasExactKeys(input, LEGACY_CONFIG_KEYS)) {
1955
+ throw invalidConfig("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");
1956
+ }
1957
+ return validateContextEnhancementConfig({
1958
+ group: {
1959
+ enabled: input.groupEnabled,
1960
+ fields: input.fields,
1961
+ guidance: input.guidance
1962
+ },
1963
+ direct: {
1964
+ enabled: input.directEnabled,
1965
+ fields: input.fields,
1966
+ guidance: input.guidance
1967
+ }
1968
+ });
1969
+ }
1918
1970
  function normalizeContextEnhancementConfig(input) {
1919
1971
  try {
1920
1972
  return validateContextEnhancementConfig(input);
1921
1973
  } catch {
1922
- return DEFAULT_CONTEXT_ENHANCEMENT_CONFIG;
1974
+ try {
1975
+ return migrateLegacyContextEnhancementConfig(input);
1976
+ } catch {
1977
+ return DEFAULT_CONTEXT_ENHANCEMENT_CONFIG;
1978
+ }
1923
1979
  }
1924
1980
  }
1925
1981
 
@@ -2655,11 +2711,33 @@ var FIELD_LABELS = Object.freeze({
2655
2711
  senderName: "\u53D1\u9001\u8005\u6635\u79F0",
2656
2712
  botId: "\u673A\u5668\u4EBA\u6807\u8BC6"
2657
2713
  });
2714
+ var SCOPE_COPY = Object.freeze({
2715
+ group: Object.freeze({
2716
+ title: "\u7FA4\u804A",
2717
+ enable: "\u542F\u7528",
2718
+ fieldsHelpLabel: "\u67E5\u770B\u7FA4\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E",
2719
+ senderNameHelpLabel: "\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E",
2720
+ guidanceLabel: "\u589E\u5F3A\u63D0\u793A\u8BCD",
2721
+ guidanceHelpLabel: "\u67E5\u770B\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E",
2722
+ guidanceUsage: "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u7FA4\u804A\u6D88\u606F\u7684 <dsh_im_source> \u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002",
2723
+ guidanceBehavior: "\u4EC5\u5728\u7FA4\u804A\u5F00\u5173\u5F00\u542F\u65F6\u4F7F\u7528\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\u4E0D\u518D\u9644\u52A0\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\uFF1B\u6240\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F53\u524D\u573A\u666F\u8BBE\u7F6E\u53D1\u9001\u3002"
2724
+ }),
2725
+ direct: Object.freeze({
2726
+ title: "\u79C1\u804A",
2727
+ enable: "\u542F\u7528",
2728
+ fieldsHelpLabel: "\u67E5\u770B\u79C1\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E",
2729
+ senderNameHelpLabel: "\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E",
2730
+ guidanceLabel: "\u589E\u5F3A\u63D0\u793A\u8BCD",
2731
+ guidanceHelpLabel: "\u67E5\u770B\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E",
2732
+ guidanceUsage: "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u79C1\u804A\u6D88\u606F\u7684 <dsh_im_source> \u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002",
2733
+ guidanceBehavior: "\u4EC5\u5728\u79C1\u804A\u5F00\u5173\u5F00\u542F\u65F6\u4F7F\u7528\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\u4E0D\u518D\u9644\u52A0\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\uFF1B\u6240\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F53\u524D\u573A\u666F\u8BBE\u7F6E\u53D1\u9001\u3002"
2734
+ })
2735
+ });
2658
2736
  function contextEnhancementLabel(config) {
2659
- const { groupEnabled, directEnabled } = normalizeContextEnhancementConfig(config);
2660
- if (groupEnabled && directEnabled) return "\u7FA4\u804A\u548C\u79C1\u804A";
2661
- if (groupEnabled) return "\u4EC5\u7FA4\u804A";
2662
- if (directEnabled) return "\u4EC5\u79C1\u804A";
2737
+ const { group, direct } = normalizeContextEnhancementConfig(config);
2738
+ if (group.enabled && direct.enabled) return "\u7FA4\u804A\u548C\u79C1\u804A";
2739
+ if (group.enabled) return "\u4EC5\u7FA4\u804A";
2740
+ if (direct.enabled) return "\u4EC5\u79C1\u804A";
2663
2741
  return "\u672A\u5F00\u542F";
2664
2742
  }
2665
2743
  function ContextIcon({ kind = "sliders" }) {
@@ -2677,26 +2755,197 @@ function ContextIcon({ kind = "sliders" }) {
2677
2755
  focusable: "false"
2678
2756
  }, h2("path", { d: path }));
2679
2757
  }
2758
+ function ContextEnhancementScopeEditor({
2759
+ kind,
2760
+ scope,
2761
+ example,
2762
+ supported,
2763
+ busy,
2764
+ idPrefix,
2765
+ onChange
2766
+ }) {
2767
+ const copy = SCOPE_COPY[kind];
2768
+ const unavailableId = `${idPrefix}-${kind}-unavailable`;
2769
+ const fieldsHelpId = `${idPrefix}-${kind}-fields-help`;
2770
+ const senderNameHelpId = `${idPrefix}-${kind}-sender-name-help`;
2771
+ const guidanceId = `${idPrefix}-${kind}-guidance`;
2772
+ const guidanceHelpId = `${idPrefix}-${kind}-guidance-help`;
2773
+ const disabled = busy || !supported;
2774
+ return h2(
2775
+ "fieldset",
2776
+ {
2777
+ className: "dim-contextSection dim-contextScope",
2778
+ "data-context-kind": kind,
2779
+ "aria-label": copy.title,
2780
+ disabled
2781
+ },
2782
+ h2(
2783
+ "label",
2784
+ { className: "dim-contextSwitchRow" },
2785
+ h2(
2786
+ "span",
2787
+ { className: "dim-contextSwitchLabel" },
2788
+ h2("span", null, copy.enable),
2789
+ !supported ? h2("span", {
2790
+ id: unavailableId,
2791
+ className: "dim-contextUnavailable"
2792
+ }, "\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09") : null
2793
+ ),
2794
+ h2("input", {
2795
+ type: "checkbox",
2796
+ role: "switch",
2797
+ className: "dim-contextSwitch",
2798
+ checked: supported && scope.enabled,
2799
+ disabled,
2800
+ "aria-describedby": !supported ? unavailableId : void 0,
2801
+ onChange: (event) => {
2802
+ if (supported) onChange("enabled", event.target.checked);
2803
+ }
2804
+ })
2805
+ ),
2806
+ h2(
2807
+ "div",
2808
+ { className: "dim-contextScopeBlock" },
2809
+ h2(
2810
+ "div",
2811
+ { className: "dim-contextLegend" },
2812
+ h2("span", null, "\u6765\u6E90\u5B57\u6BB5"),
2813
+ h2(
2814
+ "span",
2815
+ { className: "dim-contextHelp dim-contextLegendHelp" },
2816
+ h2("button", {
2817
+ type: "button",
2818
+ className: "dim-contextHelpButton",
2819
+ disabled,
2820
+ "aria-label": copy.fieldsHelpLabel,
2821
+ "aria-describedby": fieldsHelpId
2822
+ }, h2("span", { "aria-hidden": "true" }, "?")),
2823
+ h2(
2824
+ "span",
2825
+ { id: fieldsHelpId, className: "dim-contextTooltip dim-contextLegendTooltip", role: "tooltip" },
2826
+ "\u589E\u5F3A\u63D0\u793A\u8BCD\u4E2D\u8BF7\u4F7F\u7528\u5B57\u6BB5\u540D\uFF08\u5982 senderId\u3001conversationType\uFF09\u5F15\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u53EA\u53D1\u9001\u5F53\u524D\u4F1A\u8BDD\u4E2D\u52FE\u9009\u4E14\u53EF\u7528\u7684\u5B57\u6BB5\uFF0C\u4E0D\u4F1A\u989D\u5916\u67E5\u8BE2\u6216\u8865\u5168\u3002"
2827
+ )
2828
+ )
2829
+ ),
2830
+ h2("div", { className: "dim-contextFields" }, CONTEXT_ENHANCEMENT_FIELDS.map((field) => {
2831
+ const fieldId = `${idPrefix}-${kind}-field-${field}`;
2832
+ return h2(
2833
+ "div",
2834
+ { key: field, className: "dim-contextField" },
2835
+ h2("input", {
2836
+ id: fieldId,
2837
+ type: "checkbox",
2838
+ name: `${kind}-${field}`,
2839
+ checked: scope.fields.includes(field),
2840
+ disabled,
2841
+ onChange: (event) => onChange("fields", event.target.checked ? [...scope.fields, field] : scope.fields.filter((value) => value !== field))
2842
+ }),
2843
+ h2(
2844
+ "span",
2845
+ { className: "dim-contextFieldText" },
2846
+ h2("label", { className: "dim-contextFieldName", htmlFor: fieldId }, FIELD_LABELS[field]),
2847
+ field === "senderName" ? h2(
2848
+ "span",
2849
+ { className: "dim-contextHelp dim-contextFieldHelp" },
2850
+ h2("button", {
2851
+ type: "button",
2852
+ className: "dim-contextHelpButton dim-contextFieldHelpButton",
2853
+ disabled,
2854
+ "aria-label": copy.senderNameHelpLabel,
2855
+ "aria-describedby": senderNameHelpId
2856
+ }, h2("span", { "aria-hidden": "true" }, "?")),
2857
+ h2("span", {
2858
+ id: senderNameHelpId,
2859
+ className: "dim-contextTooltip dim-contextFieldTooltip",
2860
+ role: "tooltip"
2861
+ }, "\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002")
2862
+ ) : null,
2863
+ h2("label", { className: "dim-contextFieldKey", htmlFor: fieldId }, field)
2864
+ )
2865
+ );
2866
+ }))
2867
+ ),
2868
+ h2(
2869
+ "div",
2870
+ { className: "dim-contextGuidance dim-contextScopeBlock" },
2871
+ h2(
2872
+ "div",
2873
+ { className: "dim-contextEditorHeader" },
2874
+ h2(
2875
+ "span",
2876
+ { className: "dim-contextEditorTitle" },
2877
+ h2("label", { htmlFor: guidanceId }, copy.guidanceLabel),
2878
+ h2(
2879
+ "span",
2880
+ { className: "dim-contextHelp" },
2881
+ h2("button", {
2882
+ type: "button",
2883
+ className: "dim-contextHelpButton",
2884
+ disabled,
2885
+ "aria-label": copy.guidanceHelpLabel,
2886
+ "aria-describedby": guidanceHelpId
2887
+ }, h2("span", { "aria-hidden": "true" }, "?")),
2888
+ h2(
2889
+ "span",
2890
+ { id: guidanceHelpId, className: "dim-contextTooltip dim-contextGuidanceTooltip", role: "tooltip" },
2891
+ h2("strong", null, "\u4F7F\u7528\u8BF4\u660E"),
2892
+ h2("span", null, copy.guidanceUsage),
2893
+ h2("strong", null, "\u751F\u6548\u89C4\u5219"),
2894
+ h2("span", null, copy.guidanceBehavior),
2895
+ h2("strong", null, "\u9690\u79C1\u63D0\u793A"),
2896
+ h2("span", null, "\u53D1\u9001\u8005\u6807\u8BC6\u53EF\u80FD\u5305\u542B\u5E73\u53F0\u7528\u6237 ID \u6216\u7535\u8BDD\u53F7\u7801\u5F62\u5F0F\u7684\u6807\u8BC6\u3002\u5173\u95ED\u5F00\u5173\u4E0D\u4F1A\u5220\u9664\u5DF2\u7ECF\u5199\u5165\u4F1A\u8BDD\u5386\u53F2\u7684\u4FE1\u606F\u3002"),
2897
+ h2("strong", null, "\u4F7F\u7528\u793A\u4F8B"),
2898
+ h2("span", { className: "dim-contextTooltipExample" }, example)
2899
+ )
2900
+ )
2901
+ ),
2902
+ h2(
2903
+ "div",
2904
+ { className: "dim-contextTextActions" },
2905
+ h2("button", { type: "button", disabled, onClick: () => onChange("guidance", example) }, "\u586B\u5165\u793A\u4F8B"),
2906
+ h2("button", { type: "button", disabled, onClick: () => onChange("guidance", "") }, "\u6E05\u7A7A")
2907
+ )
2908
+ ),
2909
+ h2("textarea", {
2910
+ id: guidanceId,
2911
+ value: scope.guidance,
2912
+ placeholder: example,
2913
+ rows: 4,
2914
+ disabled,
2915
+ "data-context-kind": kind,
2916
+ maxLength: CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH,
2917
+ "aria-describedby": guidanceHelpId,
2918
+ onChange: (event) => onChange("guidance", event.target.value)
2919
+ })
2920
+ )
2921
+ );
2922
+ }
2680
2923
  function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id5 }) {
2681
- const [draft, setDraft] = React7.useState(() => ({
2682
- ...normalizeContextEnhancementConfig(config),
2683
- ...!groupSupported ? { groupEnabled: false } : {}
2684
- }));
2924
+ const [draft, setDraft] = React7.useState(() => {
2925
+ const normalized = normalizeContextEnhancementConfig(config);
2926
+ return {
2927
+ ...normalized,
2928
+ ...!groupSupported ? {
2929
+ group: { ...normalized.group, enabled: false }
2930
+ } : {}
2931
+ };
2932
+ });
2685
2933
  const [saving, setSaving] = React7.useState(false);
2686
2934
  const [error, setError] = React7.useState(null);
2935
+ const [activeScope, setActiveScope] = React7.useState("direct");
2687
2936
  const savingRef = React7.useRef(false);
2688
2937
  const dialogRef = React7.useRef(null);
2689
2938
  const mountedRef = React7.useRef(true);
2939
+ const groupTabRef = React7.useRef(null);
2940
+ const directTabRef = React7.useRef(null);
2690
2941
  const titleId = React7.useId();
2691
2942
  const descriptionId = React7.useId();
2692
- const groupNoticeId = React7.useId();
2693
- const guidanceId = React7.useId();
2694
- const guidanceHelpId = React7.useId();
2695
- const fieldIdPrefix = React7.useId();
2696
- const fieldsHelpId = React7.useId();
2697
- const senderNameHelpId = React7.useId();
2698
- const guidanceExample = localizeText(CONTEXT_GUIDANCE_EXAMPLE);
2943
+ const scopeIdPrefix = React7.useId();
2944
+ const groupGuidanceExample = localizeText(CONTEXT_GROUP_GUIDANCE_EXAMPLE);
2945
+ const directGuidanceExample = localizeText(CONTEXT_DIRECT_GUIDANCE_EXAMPLE);
2699
2946
  const busy = disabled || saving;
2947
+ const scopeKinds = ["direct", "group"];
2948
+ const tabRefs = { group: groupTabRef, direct: directTabRef };
2700
2949
  React7.useEffect(() => {
2701
2950
  mountedRef.current = true;
2702
2951
  dialogRef.current?.focus?.();
@@ -2710,14 +2959,34 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
2710
2959
  queueMicrotask(() => returnFocusRef.current?.focus?.());
2711
2960
  };
2712
2961
  }, [returnFocusRef]);
2713
- const change = (key, value) => {
2962
+ const changeScope = (kind, key, value) => {
2714
2963
  if (busy || savingRef.current) return;
2715
- setDraft((current) => ({ ...current, [key]: value }));
2964
+ setDraft((current) => ({
2965
+ ...current,
2966
+ [kind]: { ...current[kind], [key]: value }
2967
+ }));
2716
2968
  setError(null);
2717
2969
  };
2718
2970
  const cancel = () => {
2719
2971
  if (!savingRef.current) onClose();
2720
2972
  };
2973
+ const activateScope = (kind, focus = false) => {
2974
+ if (busy || !scopeKinds.includes(kind)) return;
2975
+ setActiveScope(kind);
2976
+ if (focus) tabRefs[kind].current?.focus?.();
2977
+ };
2978
+ const handleTabKeyDown = (event, kind) => {
2979
+ let next;
2980
+ if (event.key === "Home") next = scopeKinds[0];
2981
+ else if (event.key === "End") next = scopeKinds.at(-1);
2982
+ else if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
2983
+ const offset = event.key === "ArrowRight" ? 1 : -1;
2984
+ next = scopeKinds[(scopeKinds.indexOf(kind) + offset + scopeKinds.length) % scopeKinds.length];
2985
+ }
2986
+ if (!next) return;
2987
+ event.preventDefault();
2988
+ activateScope(next, true);
2989
+ };
2721
2990
  const save = async () => {
2722
2991
  if (busy || savingRef.current) return;
2723
2992
  savingRef.current = true;
@@ -2811,166 +3080,45 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
2811
3080
  onClick: cancel
2812
3081
  }, h2(ContextIcon, { kind: "close" }))
2813
3082
  ),
2814
- h2(
2815
- "fieldset",
2816
- { className: "dim-contextSection", disabled: busy },
2817
- h2("legend", null, "\u542F\u7528\u8303\u56F4"),
2818
- h2(
2819
- "div",
2820
- { className: "dim-contextSwitches" },
2821
- h2(
2822
- "label",
2823
- { className: "dim-contextSwitchRow" },
2824
- h2(
2825
- "span",
2826
- { className: "dim-contextSwitchLabel" },
2827
- h2("span", null, "\u7FA4\u804A\u4E2D\u542F\u7528"),
2828
- !groupSupported ? h2("span", {
2829
- id: groupNoticeId,
2830
- className: "dim-contextUnavailable"
2831
- }, "\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09") : null
2832
- ),
2833
- h2("input", {
2834
- type: "checkbox",
2835
- role: "switch",
2836
- className: "dim-contextSwitch",
2837
- checked: groupSupported && draft.groupEnabled,
2838
- disabled: busy || !groupSupported,
2839
- "aria-describedby": !groupSupported ? groupNoticeId : void 0,
2840
- onChange: (event) => {
2841
- if (groupSupported) change("groupEnabled", event.target.checked);
2842
- }
2843
- })
2844
- ),
2845
- h2(
2846
- "label",
2847
- { className: "dim-contextSwitchRow" },
2848
- h2("span", null, "\u79C1\u804A\u4E2D\u542F\u7528"),
2849
- h2("input", {
2850
- type: "checkbox",
2851
- role: "switch",
2852
- className: "dim-contextSwitch",
2853
- checked: draft.directEnabled,
2854
- disabled: busy,
2855
- onChange: (event) => change("directEnabled", event.target.checked)
2856
- })
2857
- )
2858
- )
2859
- ),
2860
- h2(
2861
- "fieldset",
2862
- { className: "dim-contextSection", disabled: busy },
2863
- h2(
2864
- "legend",
2865
- { className: "dim-contextLegend" },
2866
- h2("span", null, "\u6765\u6E90\u5B57\u6BB5"),
2867
- h2(
2868
- "span",
2869
- { className: "dim-contextHelp dim-contextLegendHelp" },
2870
- h2("button", {
2871
- type: "button",
2872
- className: "dim-contextHelpButton",
2873
- disabled: busy,
2874
- "aria-label": "\u67E5\u770B\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E",
2875
- "aria-describedby": fieldsHelpId
2876
- }, h2("span", { "aria-hidden": "true" }, "?")),
2877
- h2(
2878
- "span",
2879
- { id: fieldsHelpId, className: "dim-contextTooltip dim-contextLegendTooltip", role: "tooltip" },
2880
- "\u589E\u5F3A\u63D0\u793A\u8BCD\u4E2D\u8BF7\u4F7F\u7528\u5B57\u6BB5\u540D\uFF08\u5982 senderId\u3001conversationType\uFF09\u5F15\u7528\u8FD9\u4E9B\u4FE1\u606F\u3002\u53EA\u53D1\u9001\u52FE\u9009\u4E14\u5F53\u524D\u6D88\u606F\u4E2D\u53EF\u7528\u7684\u5B57\u6BB5\uFF0C\u4E0D\u4F1A\u989D\u5916\u67E5\u8BE2\u6216\u8865\u5168\u3002"
2881
- )
2882
- )
2883
- ),
2884
- h2("div", { className: "dim-contextFields" }, CONTEXT_ENHANCEMENT_FIELDS.map((field) => {
2885
- const fieldId = `${fieldIdPrefix}-${field}`;
2886
- return h2(
2887
- "div",
2888
- { key: field, className: "dim-contextField" },
2889
- h2("input", {
2890
- id: fieldId,
2891
- type: "checkbox",
2892
- name: field,
2893
- checked: draft.fields.includes(field),
2894
- disabled: busy,
2895
- onChange: (event) => change("fields", event.target.checked ? [...draft.fields, field] : draft.fields.filter((value) => value !== field))
2896
- }),
2897
- h2(
2898
- "span",
2899
- { className: "dim-contextFieldText" },
2900
- h2("label", { className: "dim-contextFieldName", htmlFor: fieldId }, FIELD_LABELS[field]),
2901
- field === "senderName" ? h2(
2902
- "span",
2903
- { className: "dim-contextHelp dim-contextFieldHelp" },
2904
- h2("button", {
2905
- type: "button",
2906
- className: "dim-contextHelpButton dim-contextFieldHelpButton",
2907
- disabled: busy,
2908
- "aria-label": "\u67E5\u770B\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E",
2909
- "aria-describedby": senderNameHelpId
2910
- }, h2("span", { "aria-hidden": "true" }, "?")),
2911
- h2("span", {
2912
- id: senderNameHelpId,
2913
- className: "dim-contextTooltip dim-contextFieldTooltip",
2914
- role: "tooltip"
2915
- }, "\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002")
2916
- ) : null,
2917
- h2("label", { className: "dim-contextFieldKey", htmlFor: fieldId }, field)
2918
- )
2919
- );
2920
- }))
2921
- ),
2922
3083
  h2(
2923
3084
  "div",
2924
- { className: "dim-contextGuidance" },
2925
- h2(
2926
- "div",
2927
- { className: "dim-contextEditorHeader" },
2928
- h2(
2929
- "span",
2930
- { className: "dim-contextEditorTitle" },
2931
- h2("label", { htmlFor: guidanceId }, "\u589E\u5F3A\u63D0\u793A\u8BCD"),
2932
- h2(
2933
- "span",
2934
- { className: "dim-contextHelp" },
2935
- h2("button", {
2936
- type: "button",
2937
- className: "dim-contextHelpButton",
2938
- disabled: busy,
2939
- "aria-label": "\u67E5\u770B\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E",
2940
- "aria-describedby": guidanceHelpId
2941
- }, h2("span", { "aria-hidden": "true" }, "?")),
2942
- h2(
2943
- "span",
2944
- { id: guidanceHelpId, className: "dim-contextTooltip dim-contextGuidanceTooltip", role: "tooltip" },
2945
- h2("strong", null, "\u4F7F\u7528\u8BF4\u660E"),
2946
- h2("span", null, "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528 <dsh_im_source> \u4E2D\u5DF2\u9009\u62E9\u7684\u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002"),
2947
- h2("strong", null, "\u751F\u6548\u89C4\u5219"),
2948
- h2("span", null, "\u53EA\u9700\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002\u6E05\u7A7A\u5E76\u4FDD\u5B58\u540E\uFF0C\u4E0D\u518D\u9644\u52A0\u589E\u5F3A\u63D0\u793A\u8BCD\uFF0C\u5DF2\u9009\u6765\u6E90\u5B57\u6BB5\u4ECD\u6309\u5F00\u5173\u8BBE\u7F6E\u53D1\u9001\u3002"),
2949
- h2("strong", null, "\u9690\u79C1\u63D0\u793A"),
2950
- h2("span", null, "\u53D1\u9001\u8005\u6807\u8BC6\u53EF\u80FD\u5305\u542B\u5E73\u53F0\u7528\u6237 ID \u6216\u7535\u8BDD\u53F7\u7801\u5F62\u5F0F\u7684\u6807\u8BC6\u3002\u5173\u95ED\u5F00\u5173\u4E0D\u4F1A\u5220\u9664\u5DF2\u7ECF\u5199\u5165\u4F1A\u8BDD\u5386\u53F2\u7684\u4FE1\u606F\u3002"),
2951
- h2("strong", null, "\u4F7F\u7528\u793A\u4F8B"),
2952
- h2("span", { className: "dim-contextTooltipExample" }, guidanceExample)
2953
- )
2954
- )
2955
- ),
2956
- h2(
2957
- "div",
2958
- { className: "dim-contextTextActions" },
2959
- h2("button", { type: "button", disabled: busy, onClick: () => change("guidance", guidanceExample) }, "\u586B\u5165\u793A\u4F8B"),
2960
- h2("button", { type: "button", disabled: busy, onClick: () => change("guidance", "") }, "\u6E05\u7A7A")
2961
- )
2962
- ),
2963
- h2("textarea", {
2964
- id: guidanceId,
2965
- value: draft.guidance,
2966
- placeholder: guidanceExample,
2967
- rows: 4,
2968
- disabled: busy,
2969
- maxLength: CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH,
2970
- "aria-describedby": guidanceHelpId,
2971
- onChange: (event) => change("guidance", event.target.value)
3085
+ { className: "dim-contextTabs", role: "tablist", "aria-label": "\u4E0A\u4E0B\u6587\u589E\u5F3A\u8303\u56F4" },
3086
+ scopeKinds.map((kind) => {
3087
+ const selected = activeScope === kind;
3088
+ return h2("button", {
3089
+ key: kind,
3090
+ id: `${scopeIdPrefix}-${kind}-tab`,
3091
+ ref: tabRefs[kind],
3092
+ type: "button",
3093
+ role: "tab",
3094
+ className: "dim-contextTab",
3095
+ "data-context-kind": kind,
3096
+ "aria-selected": selected,
3097
+ "aria-controls": `${scopeIdPrefix}-${kind}-panel`,
3098
+ tabIndex: selected ? 0 : -1,
3099
+ disabled: busy,
3100
+ onClick: () => activateScope(kind),
3101
+ onKeyDown: (event) => handleTabKeyDown(event, kind)
3102
+ }, SCOPE_COPY[kind].title);
2972
3103
  })
2973
3104
  ),
3105
+ scopeKinds.map((kind) => h2("div", {
3106
+ key: kind,
3107
+ id: `${scopeIdPrefix}-${kind}-panel`,
3108
+ className: "dim-contextTabPanel",
3109
+ role: "tabpanel",
3110
+ "data-context-kind": kind,
3111
+ "aria-labelledby": `${scopeIdPrefix}-${kind}-tab`,
3112
+ hidden: activeScope !== kind
3113
+ }, h2(ContextEnhancementScopeEditor, {
3114
+ kind,
3115
+ scope: draft[kind],
3116
+ example: kind === "group" ? groupGuidanceExample : directGuidanceExample,
3117
+ supported: kind === "group" ? groupSupported : true,
3118
+ busy,
3119
+ idPrefix: scopeIdPrefix,
3120
+ onChange: (key, value) => changeScope(kind, key, value)
3121
+ }))),
2974
3122
  error ? h2("p", { className: "dim-contextError", role: "alert" }, error) : null,
2975
3123
  h2(
2976
3124
  "footer",
@@ -2994,7 +3142,10 @@ function ContextEnhancementEditor({ config, groupSupported = true, disabled = fa
2994
3142
  const dialogId = React7.useId();
2995
3143
  const statusId = React7.useId();
2996
3144
  const saved = normalizeContextEnhancementConfig(config);
2997
- const label = contextEnhancementLabel(groupSupported ? saved : { ...saved, groupEnabled: false });
3145
+ const label = contextEnhancementLabel(groupSupported ? saved : {
3146
+ ...saved,
3147
+ group: { ...saved.group, enabled: false }
3148
+ });
2998
3149
  return h2(
2999
3150
  React7.Fragment,
3000
3151
  null,
@@ -12775,10 +12926,15 @@ var CSS11 = String.raw`
12775
12926
  .dim-contextHeaderTooltip { width: min(340px, calc(100vw - 72px)); }
12776
12927
  .dim-contextClose { width: 30px; height: 30px; flex: none; display: grid; place-items: center; padding: 0; border: 0; border-radius: 6px; color: var(--dsw-alias-label-secondary, #646a73); background: transparent; cursor: pointer; }
12777
12928
  .dim-contextClose:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eef0f3); }
12778
- .dim-contextSection { min-width: 0; margin: 14px 0; padding: 0; border: 0; }
12779
- .dim-contextSection legend { margin-bottom: 8px; padding: 0; font-weight: 500; }
12929
+ .dim-contextTabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px; margin-top: 14px; padding: 3px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 8px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
12930
+ .dim-contextTab { min-width: 0; min-height: 34px; padding: 5px 12px; border: 0; border-radius: 6px; color: var(--dsw-alias-label-secondary, #646a73); background: transparent; font: inherit; font-weight: 500; cursor: pointer; transition: color .15s ease, background .15s ease, box-shadow .15s ease; }
12931
+ .dim-contextTab:hover:not(:disabled):not([aria-selected="true"]) { color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #eef0f3); }
12932
+ .dim-contextTab[aria-selected="true"] { color: var(--dsw-alias-state-business-primary, #3370ff); background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 1px 3px rgb(31 35 41 / 12%); }
12933
+ .dim-contextTabPanel[hidden] { display: none; }
12934
+ .dim-contextSection { min-width: 0; margin: 0; padding: 0; border: 0; }
12935
+ .dim-contextScope { margin-top: 10px; padding: 12px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 9px; background: var(--dsw-alias-bg-layer-1, #fff); }
12936
+ .dim-contextScopeBlock { margin-top: 12px; }
12780
12937
  .dim-contextLegend { position: relative; display: inline-flex; align-items: center; gap: 6px; }
12781
- .dim-contextSwitches { display: grid; grid-template-columns: 1fr; gap: 2px; }
12782
12938
  .dim-contextSwitchRow { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 34px; cursor: pointer; }
12783
12939
  .dim-contextSwitchLabel { min-width: 0; display: inline-flex; align-items: baseline; gap: 5px; flex-wrap: wrap; }
12784
12940
  .dim-contextUnavailable { color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 16px; font-weight: 400; }
@@ -12821,7 +12977,7 @@ var CSS11 = String.raw`
12821
12977
  .dim-contextEntry:focus-visible, .dim-contextDialog button:focus-visible, .dim-contextDialog input:focus-visible, .dim-contextDialog textarea:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 2px; }
12822
12978
  .dim-contextEntry:disabled, .dim-contextDialog button:disabled, .dim-contextDialog input:disabled, .dim-contextDialog textarea:disabled { opacity: .55; cursor: not-allowed; }
12823
12979
  @media (pointer: coarse) {
12824
- .dim-contextEntry, .dim-contextClose, .dim-contextFooter button, .dim-contextTextActions button, .dim-contextField, .dim-contextSwitchRow { min-height: 44px; }
12980
+ .dim-contextEntry, .dim-contextTab, .dim-contextClose, .dim-contextFooter button, .dim-contextTextActions button, .dim-contextField, .dim-contextSwitchRow { min-height: 44px; }
12825
12981
  .dim-contextClose, .dim-contextTextActions button { min-width: 44px; }
12826
12982
  .dim-contextGuidance textarea { font-size: 16px; }
12827
12983
  }