@xmanrui/dsh-im 4.2.1 → 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.1",
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",
@@ -1050,31 +1050,44 @@ var EN = Object.freeze({
1050
1050
  "\u7FA4\u804A\u548C\u79C1\u804A": "Groups and direct",
1051
1051
  "\u5173\u95ED\u5F39\u7A97": "Close dialog",
1052
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",
1053
1054
  "\u542F\u7528\u8303\u56F4": "Enable in",
1054
- "\u7FA4\u804A\u4E2D\u542F\u7528": "Enable in group chats",
1055
- "\u79C1\u804A\u4E2D\u542F\u7528": "Enable in direct chats",
1055
+ "\u542F\u7528": "Enabled",
1056
1056
  "\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09": "(This channel does not support group chats)",
1057
1057
  "\u6765\u6E90\u5B57\u6BB5": "Source fields",
1058
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",
1059
1061
  "\u6E20\u9053": "Channel",
1060
1062
  "\u4F1A\u8BDD\u7C7B\u578B": "Conversation type",
1061
1063
  "\u53D1\u9001\u8005\u6807\u8BC6": "Sender ID",
1062
1064
  "\u53D1\u9001\u8005\u6635\u79F0": "Sender name",
1063
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",
1064
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.",
1065
1069
  "\u673A\u5668\u4EBA\u6807\u8BC6": "Bot ID",
1066
1070
  "\u589E\u5F3A\u63D0\u793A\u8BCD": "Guidance",
1067
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",
1068
1074
  "\u4F7F\u7528\u8BF4\u660E": "How to use",
1069
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.",
1070
1076
  "\u751F\u6548\u89C4\u5219": "Behavior",
1071
1077
  "\u9690\u79C1\u63D0\u793A": "Privacy",
1072
1078
  "\u4F7F\u7528\u793A\u4F8B": "Example",
1073
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.",
1074
1082
  "\u586B\u5165\u793A\u4F8B": "Use example",
1075
1083
  "\u6E05\u7A7A": "Clear",
1076
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.",
1077
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.",
1078
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.",
1079
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.",
1080
1093
  "\u4E0A\u4E0B\u6587\u589E\u5F3A\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save context enhancement. Try again.",
@@ -1881,26 +1894,39 @@ var CONTEXT_ENHANCEMENT_FIELDS = Object.freeze([
1881
1894
  "botId"
1882
1895
  ]);
1883
1896
  var CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH = 8e3;
1884
- 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
1885
- 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`;
1886
1901
  var DEFAULT_CONTEXT_ENHANCEMENT_CONFIG = Object.freeze({
1887
- groupEnabled: false,
1888
- directEnabled: false,
1889
- fields: Object.freeze(["senderId"]),
1890
- 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
+ })
1891
1912
  });
1892
- 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"];
1893
1916
  function invalidConfig(message) {
1894
1917
  const error = new TypeError(message);
1895
1918
  error.code = "context-enhancement-invalid";
1896
1919
  return error;
1897
1920
  }
1898
- function validateContextEnhancementConfig(input) {
1899
- 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)) {
1900
1926
  throw invalidConfig("\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002");
1901
1927
  }
1902
- const { groupEnabled, directEnabled, fields, guidance } = input;
1903
- if (typeof groupEnabled !== "boolean" || typeof directEnabled !== "boolean") {
1928
+ const { enabled, fields, guidance } = input;
1929
+ if (typeof enabled !== "boolean") {
1904
1930
  throw invalidConfig("\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");
1905
1931
  }
1906
1932
  if (!Array.isArray(fields) || ![...fields].every((field) => CONTEXT_ENHANCEMENT_FIELDS.includes(field))) {
@@ -1910,17 +1936,46 @@ function validateContextEnhancementConfig(input) {
1910
1936
  throw invalidConfig(`\u589E\u5F3A\u63D0\u793A\u8BCD\u4E0D\u5F97\u8D85\u8FC7 ${CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH} \u4E2A\u5B57\u7B26\u3002`);
1911
1937
  }
1912
1938
  return Object.freeze({
1913
- groupEnabled,
1914
- directEnabled,
1939
+ enabled,
1915
1940
  fields: Object.freeze(CONTEXT_ENHANCEMENT_FIELDS.filter((field) => fields.includes(field))),
1916
1941
  guidance: guidance.trim() ? guidance : ""
1917
1942
  });
1918
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
+ }
1919
1970
  function normalizeContextEnhancementConfig(input) {
1920
1971
  try {
1921
1972
  return validateContextEnhancementConfig(input);
1922
1973
  } catch {
1923
- return DEFAULT_CONTEXT_ENHANCEMENT_CONFIG;
1974
+ try {
1975
+ return migrateLegacyContextEnhancementConfig(input);
1976
+ } catch {
1977
+ return DEFAULT_CONTEXT_ENHANCEMENT_CONFIG;
1978
+ }
1924
1979
  }
1925
1980
  }
1926
1981
 
@@ -2656,11 +2711,33 @@ var FIELD_LABELS = Object.freeze({
2656
2711
  senderName: "\u53D1\u9001\u8005\u6635\u79F0",
2657
2712
  botId: "\u673A\u5668\u4EBA\u6807\u8BC6"
2658
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
+ });
2659
2736
  function contextEnhancementLabel(config) {
2660
- const { groupEnabled, directEnabled } = normalizeContextEnhancementConfig(config);
2661
- if (groupEnabled && directEnabled) return "\u7FA4\u804A\u548C\u79C1\u804A";
2662
- if (groupEnabled) return "\u4EC5\u7FA4\u804A";
2663
- 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";
2664
2741
  return "\u672A\u5F00\u542F";
2665
2742
  }
2666
2743
  function ContextIcon({ kind = "sliders" }) {
@@ -2678,26 +2755,197 @@ function ContextIcon({ kind = "sliders" }) {
2678
2755
  focusable: "false"
2679
2756
  }, h2("path", { d: path }));
2680
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
+ }
2681
2923
  function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, onClose, returnFocusRef, id: id5 }) {
2682
- const [draft, setDraft] = React7.useState(() => ({
2683
- ...normalizeContextEnhancementConfig(config),
2684
- ...!groupSupported ? { groupEnabled: false } : {}
2685
- }));
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
+ });
2686
2933
  const [saving, setSaving] = React7.useState(false);
2687
2934
  const [error, setError] = React7.useState(null);
2935
+ const [activeScope, setActiveScope] = React7.useState("direct");
2688
2936
  const savingRef = React7.useRef(false);
2689
2937
  const dialogRef = React7.useRef(null);
2690
2938
  const mountedRef = React7.useRef(true);
2939
+ const groupTabRef = React7.useRef(null);
2940
+ const directTabRef = React7.useRef(null);
2691
2941
  const titleId = React7.useId();
2692
2942
  const descriptionId = React7.useId();
2693
- const groupNoticeId = React7.useId();
2694
- const guidanceId = React7.useId();
2695
- const guidanceHelpId = React7.useId();
2696
- const fieldIdPrefix = React7.useId();
2697
- const fieldsHelpId = React7.useId();
2698
- const senderNameHelpId = React7.useId();
2699
- 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);
2700
2946
  const busy = disabled || saving;
2947
+ const scopeKinds = ["direct", "group"];
2948
+ const tabRefs = { group: groupTabRef, direct: directTabRef };
2701
2949
  React7.useEffect(() => {
2702
2950
  mountedRef.current = true;
2703
2951
  dialogRef.current?.focus?.();
@@ -2711,14 +2959,34 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
2711
2959
  queueMicrotask(() => returnFocusRef.current?.focus?.());
2712
2960
  };
2713
2961
  }, [returnFocusRef]);
2714
- const change = (key, value) => {
2962
+ const changeScope = (kind, key, value) => {
2715
2963
  if (busy || savingRef.current) return;
2716
- setDraft((current) => ({ ...current, [key]: value }));
2964
+ setDraft((current) => ({
2965
+ ...current,
2966
+ [kind]: { ...current[kind], [key]: value }
2967
+ }));
2717
2968
  setError(null);
2718
2969
  };
2719
2970
  const cancel = () => {
2720
2971
  if (!savingRef.current) onClose();
2721
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
+ };
2722
2990
  const save = async () => {
2723
2991
  if (busy || savingRef.current) return;
2724
2992
  savingRef.current = true;
@@ -2812,166 +3080,45 @@ function ContextEnhancementDialog({ config, groupSupported, disabled, onSave, on
2812
3080
  onClick: cancel
2813
3081
  }, h2(ContextIcon, { kind: "close" }))
2814
3082
  ),
2815
- h2(
2816
- "fieldset",
2817
- { className: "dim-contextSection", disabled: busy },
2818
- h2("legend", null, "\u542F\u7528\u8303\u56F4"),
2819
- h2(
2820
- "div",
2821
- { className: "dim-contextSwitches" },
2822
- h2(
2823
- "label",
2824
- { className: "dim-contextSwitchRow" },
2825
- h2(
2826
- "span",
2827
- { className: "dim-contextSwitchLabel" },
2828
- h2("span", null, "\u7FA4\u804A\u4E2D\u542F\u7528"),
2829
- !groupSupported ? h2("span", {
2830
- id: groupNoticeId,
2831
- className: "dim-contextUnavailable"
2832
- }, "\uFF08\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A\uFF09") : null
2833
- ),
2834
- h2("input", {
2835
- type: "checkbox",
2836
- role: "switch",
2837
- className: "dim-contextSwitch",
2838
- checked: groupSupported && draft.groupEnabled,
2839
- disabled: busy || !groupSupported,
2840
- "aria-describedby": !groupSupported ? groupNoticeId : void 0,
2841
- onChange: (event) => {
2842
- if (groupSupported) change("groupEnabled", event.target.checked);
2843
- }
2844
- })
2845
- ),
2846
- h2(
2847
- "label",
2848
- { className: "dim-contextSwitchRow" },
2849
- h2("span", null, "\u79C1\u804A\u4E2D\u542F\u7528"),
2850
- h2("input", {
2851
- type: "checkbox",
2852
- role: "switch",
2853
- className: "dim-contextSwitch",
2854
- checked: draft.directEnabled,
2855
- disabled: busy,
2856
- onChange: (event) => change("directEnabled", event.target.checked)
2857
- })
2858
- )
2859
- )
2860
- ),
2861
- h2(
2862
- "fieldset",
2863
- { className: "dim-contextSection", disabled: busy },
2864
- h2(
2865
- "legend",
2866
- { className: "dim-contextLegend" },
2867
- h2("span", null, "\u6765\u6E90\u5B57\u6BB5"),
2868
- h2(
2869
- "span",
2870
- { className: "dim-contextHelp dim-contextLegendHelp" },
2871
- h2("button", {
2872
- type: "button",
2873
- className: "dim-contextHelpButton",
2874
- disabled: busy,
2875
- "aria-label": "\u67E5\u770B\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E",
2876
- "aria-describedby": fieldsHelpId
2877
- }, h2("span", { "aria-hidden": "true" }, "?")),
2878
- h2(
2879
- "span",
2880
- { id: fieldsHelpId, className: "dim-contextTooltip dim-contextLegendTooltip", role: "tooltip" },
2881
- "\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"
2882
- )
2883
- )
2884
- ),
2885
- h2("div", { className: "dim-contextFields" }, CONTEXT_ENHANCEMENT_FIELDS.map((field) => {
2886
- const fieldId = `${fieldIdPrefix}-${field}`;
2887
- return h2(
2888
- "div",
2889
- { key: field, className: "dim-contextField" },
2890
- h2("input", {
2891
- id: fieldId,
2892
- type: "checkbox",
2893
- name: field,
2894
- checked: draft.fields.includes(field),
2895
- disabled: busy,
2896
- onChange: (event) => change("fields", event.target.checked ? [...draft.fields, field] : draft.fields.filter((value) => value !== field))
2897
- }),
2898
- h2(
2899
- "span",
2900
- { className: "dim-contextFieldText" },
2901
- h2("label", { className: "dim-contextFieldName", htmlFor: fieldId }, FIELD_LABELS[field]),
2902
- field === "senderName" ? h2(
2903
- "span",
2904
- { className: "dim-contextHelp dim-contextFieldHelp" },
2905
- h2("button", {
2906
- type: "button",
2907
- className: "dim-contextHelpButton dim-contextFieldHelpButton",
2908
- disabled: busy,
2909
- "aria-label": "\u67E5\u770B\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E",
2910
- "aria-describedby": senderNameHelpId
2911
- }, h2("span", { "aria-hidden": "true" }, "?")),
2912
- h2("span", {
2913
- id: senderNameHelpId,
2914
- className: "dim-contextTooltip dim-contextFieldTooltip",
2915
- role: "tooltip"
2916
- }, "\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")
2917
- ) : null,
2918
- h2("label", { className: "dim-contextFieldKey", htmlFor: fieldId }, field)
2919
- )
2920
- );
2921
- }))
2922
- ),
2923
3083
  h2(
2924
3084
  "div",
2925
- { className: "dim-contextGuidance" },
2926
- h2(
2927
- "div",
2928
- { className: "dim-contextEditorHeader" },
2929
- h2(
2930
- "span",
2931
- { className: "dim-contextEditorTitle" },
2932
- h2("label", { htmlFor: guidanceId }, "\u589E\u5F3A\u63D0\u793A\u8BCD"),
2933
- h2(
2934
- "span",
2935
- { className: "dim-contextHelp" },
2936
- h2("button", {
2937
- type: "button",
2938
- className: "dim-contextHelpButton",
2939
- disabled: busy,
2940
- "aria-label": "\u67E5\u770B\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E",
2941
- "aria-describedby": guidanceHelpId
2942
- }, h2("span", { "aria-hidden": "true" }, "?")),
2943
- h2(
2944
- "span",
2945
- { id: guidanceHelpId, className: "dim-contextTooltip dim-contextGuidanceTooltip", role: "tooltip" },
2946
- h2("strong", null, "\u4F7F\u7528\u8BF4\u660E"),
2947
- 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"),
2948
- h2("strong", null, "\u751F\u6548\u89C4\u5219"),
2949
- 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"),
2950
- h2("strong", null, "\u9690\u79C1\u63D0\u793A"),
2951
- 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"),
2952
- h2("strong", null, "\u4F7F\u7528\u793A\u4F8B"),
2953
- h2("span", { className: "dim-contextTooltipExample" }, guidanceExample)
2954
- )
2955
- )
2956
- ),
2957
- h2(
2958
- "div",
2959
- { className: "dim-contextTextActions" },
2960
- h2("button", { type: "button", disabled: busy, onClick: () => change("guidance", guidanceExample) }, "\u586B\u5165\u793A\u4F8B"),
2961
- h2("button", { type: "button", disabled: busy, onClick: () => change("guidance", "") }, "\u6E05\u7A7A")
2962
- )
2963
- ),
2964
- h2("textarea", {
2965
- id: guidanceId,
2966
- value: draft.guidance,
2967
- placeholder: guidanceExample,
2968
- rows: 4,
2969
- disabled: busy,
2970
- maxLength: CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH,
2971
- "aria-describedby": guidanceHelpId,
2972
- 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);
2973
3103
  })
2974
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
+ }))),
2975
3122
  error ? h2("p", { className: "dim-contextError", role: "alert" }, error) : null,
2976
3123
  h2(
2977
3124
  "footer",
@@ -2995,7 +3142,10 @@ function ContextEnhancementEditor({ config, groupSupported = true, disabled = fa
2995
3142
  const dialogId = React7.useId();
2996
3143
  const statusId = React7.useId();
2997
3144
  const saved = normalizeContextEnhancementConfig(config);
2998
- const label = contextEnhancementLabel(groupSupported ? saved : { ...saved, groupEnabled: false });
3145
+ const label = contextEnhancementLabel(groupSupported ? saved : {
3146
+ ...saved,
3147
+ group: { ...saved.group, enabled: false }
3148
+ });
2999
3149
  return h2(
3000
3150
  React7.Fragment,
3001
3151
  null,
@@ -12776,10 +12926,15 @@ var CSS11 = String.raw`
12776
12926
  .dim-contextHeaderTooltip { width: min(340px, calc(100vw - 72px)); }
12777
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; }
12778
12928
  .dim-contextClose:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover, #eef0f3); }
12779
- .dim-contextSection { min-width: 0; margin: 14px 0; padding: 0; border: 0; }
12780
- .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; }
12781
12937
  .dim-contextLegend { position: relative; display: inline-flex; align-items: center; gap: 6px; }
12782
- .dim-contextSwitches { display: grid; grid-template-columns: 1fr; gap: 2px; }
12783
12938
  .dim-contextSwitchRow { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 34px; cursor: pointer; }
12784
12939
  .dim-contextSwitchLabel { min-width: 0; display: inline-flex; align-items: baseline; gap: 5px; flex-wrap: wrap; }
12785
12940
  .dim-contextUnavailable { color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 16px; font-weight: 400; }
@@ -12822,7 +12977,7 @@ var CSS11 = String.raw`
12822
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; }
12823
12978
  .dim-contextEntry:disabled, .dim-contextDialog button:disabled, .dim-contextDialog input:disabled, .dim-contextDialog textarea:disabled { opacity: .55; cursor: not-allowed; }
12824
12979
  @media (pointer: coarse) {
12825
- .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; }
12826
12981
  .dim-contextClose, .dim-contextTextActions button { min-width: 44px; }
12827
12982
  .dim-contextGuidance textarea { font-size: 16px; }
12828
12983
  }