dsh-diff-approval 0.30.1 → 0.31.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.
@@ -16,7 +16,7 @@ export declare const ANNOTATE_SKILL_DESCRIPTION: string;
16
16
  /** Extra routing guidance for the catalog. */
17
17
  export declare const ANNOTATE_SKILL_WHEN_TO_USE: string;
18
18
  /** The instruction body the agent loads. */
19
- export declare const ANNOTATE_SKILL_CONTENT = "# \u7528\u5361\u7247\u7ED9\u4EE3\u7801\u505A\u6279\u6CE8\n\n\u6539\u52A8\u5BA1\u6279\u9762\u677F\u91CC\u7684\u5361\u7247 = \u9488\u5BF9**\u5177\u4F53\u51E0\u884C\u4EE3\u7801**\u7684\u5BF9\u8BDD\u3002\u4F60\u5199\u7684\u6279\u6CE8\u4F1A\u6210\u4E3A\u5361\u7247\u7684\u7B2C\u4E00\u6761\u5185\u5BB9\uFF08\u4F60\u5728\u5DE5\u5177\u91CC\u5199\u7684 `note`\uFF09\uFF0C\u7528\u6237\u5C31\u5728\u4EE3\u7801\u65C1\u8FB9\u770B\u5230\u5B83\uFF0C\u5E76\u4E14\u53EF\u4EE5\u5728\u8FD9\u5F20\u5361\u7247\u91CC\u56DE\u4F60\uFF1B\u4ED6\u7684\u56DE\u590D\u4F1A\u4EE5 `[\u8BC4\u8BBA] (path:lines)` \u7684\u6D88\u606F\u56DE\u5230\u4F60\u3002\n\n## \u4EC0\u4E48\u65F6\u5019\u8BE5\u7528\n\n- \u7528\u6237\u60F3\u8BFB\u4EE3\u7801\uFF1A\u628A**\u8C03\u7528\u94FE**\u4E00\u6B65\u6B65\u6279\u6CE8\u51FA\u6765\uFF08\u6BCF\u4E2A\u5173\u952E\u8C03\u7528\u70B9\u4E00\u5F20\u5361\uFF0C\u6309\u9605\u8BFB\u987A\u5E8F\uFF09\uFF0C\u6BD4\u5728\u56DE\u590D\u91CC\u8D34\u4E00\u5927\u6BB5\u4EE3\u7801\u6216\u884C\u53F7\u6E05\u5355\u6E05\u695A\u5F97\u591A\u3002\n- \u4F60\u8981\u6307\u51FA\u67D0\u6BB5\u4EE3\u7801\u7684\u95EE\u9898\u3001\u7406\u7531\u3001\u6216\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9\uFF08Review \u573A\u666F\uFF09\uFF0C\u8BA9\u8BC1\u636E\u5C31\u8D34\u5728\u8BC1\u636E\u6240\u5728\u7684\u884C\u4E0A\u3002\n- \u4F60\u6B63\u5728\u8BA8\u8BBA\u67D0\u6BB5\u4EE3\u7801\uFF0C\u60F3\u628A\u8BDD\u76F4\u63A5\u6302\u5728\u90A3\u4E9B\u884C\u4E0A\uFF0C\u800C\u4E0D\u662F\u8BA9\u7528\u6237\u5728\u56DE\u590D\u91CC\u5BF9\u7740\u884C\u53F7\u627E\u3002\n\n\u4E0D\u8981\u5728\u7528\u6237\u6CA1\u8BA9\u4F60\u8BB2\u4EE3\u7801\u65F6\u5237\u5361\u7247\uFF0C\u4E5F\u4E0D\u8981\u7528\u5B83\u4EE3\u66FF\u56DE\u590D\uFF1A\u5361\u7247\u662F**\u8865\u5145**\uFF0C\u4F60\u7684\u56DE\u7B54\u8FD8\u662F\u8981\u5199\u5728\u56DE\u590D\u91CC\uFF08\u53EF\u4EE5\u7B80\u77ED\u8BF4\"\u5DF2\u5728\u4EE3\u7801\u4E0A\u6807\u4E86 3 \u5904\"\u5E76\u7ED9\u51FA\u8981\u70B9\uFF09\u3002\n\n## \u600E\u4E48\u8C03\u7528 `diff_approval_annotate`\n\n- `path`\uFF1A\u9762\u677F\u91CC\u90A3\u4E2A\u6587\u4EF6\u3002\u4F60\u8BFB\u6587\u4EF6\u65F6\u7528\u7684\u8DEF\u5F84\u4E5F\u884C\uFF08\u6309\u5C3E\u90E8\u5339\u914D\uFF09\uFF1B\u5339\u914D\u5230\u591A\u4E2A\u4F1A\u88AB\u62D2\uFF0C\u628A\u5B8C\u6574\u8DEF\u5F84\u7ED9\u5B83\u3002\n **\u6587\u4EF6\u8FD8\u4E0D\u5728\u9762\u677F\u7684\u5217\u8868\u91CC\u4E5F\u6CA1\u5173\u7CFB\uFF1A\u4F1A\u81EA\u52A8\u52A0\u8FDB\u53BB**\uFF08\u5DE5\u4F5C\u533A\u91CC\u80FD\u8BFB\u6210\u6587\u672C\u7684\u6587\u4EF6\uFF09\uFF0C\u6240\u4EE5\"\u7528\u6237\u60F3\u8BFB\u61C2\u67D0\u4E2A\u6587\u4EF6\"\u4E0D\u5FC5\u5148\u7B49\u6539\u52A8\u53D1\u751F\u3002\u5DE5\u4F5C\u533A\u4E4B\u5916\u3001\u6216\u8BFB\u4E0D\u51FA\u6587\u672C\uFF0C\u624D\u4F1A\u88AB\u62D2\u3002\n- `startLine` / `endLine`\uFF1A**\u73B0\u5728**\u7684\u884C\u53F7\uFF081 \u8D77\uFF0C\u542B\u4E24\u7AEF\uFF1B\u7701\u7565 `endLine` \u5C31\u662F\u4E00\u884C\uFF09\u3002\u5148\u8BFB\u6587\u4EF6\u518D\u5199\u53F7\uFF0C\u522B\u51ED\u8BB0\u5FC6\u3002\n- `note`\uFF1A\u5361\u7247\u4E0A\u5199\u7684\u8BDD\u3002\u8981\u77ED\u2014\u2014\u5361\u7247\u662F**\u6309\u884C**\u6392\u7248\u3001\u884C\u9AD8\u6309\u884C\u7B97\u7684\uFF08\u4E0A\u9650 1000 \u5B57\u7B26\uFF0C\u8D85\u4E86\u4F1A\u88AB\u62D2\uFF09\u3002\u8BB2\u6D41\u7A0B\u65F6\uFF0C\u628A\u8FD9\u4E00\u6B65\u7684\u5E8F\u53F7\u5199\u5728 note \u7684**\u6700\u524D\u9762**\uFF08`1. \u2026`\u3001`2. \u2026`\uFF09\u3002\n- `quote`\uFF08\u53EF\u9009\uFF0C\u5EFA\u8BAE\u7ED9\uFF09\uFF1A\u4F60\u8BFB\u5230\u7684\u90A3\u51E0\u884C\u539F\u6587\uFF08\u6362\u884C\u8FDE\u63A5\uFF09\u3002\u6587\u4EF6\u5728\u4F60\u8BFB\u5B8C\u4E4B\u540E\u53C8\u53D8\u4E86\u7684\u8BDD\uFF0C\u4F1A\u5F53\u573A\u88AB\u62D2\u5E76\u628A\u73B0\u5728\u7684\u539F\u6587\u7ED9\u4F60\uFF0C\u907F\u514D\u6279\u6CE8\u6302\u5728\u9519\u8BEF\u7684\u884C\u4E0A\u3002\n\n## \u8BB2\u6D41\u7A0B\u5C31\u5728\u6B63\u6587\u5F00\u5934\u5199\u5E8F\u53F7\n\n\u5982\u679C\u8FD9\u51E0\u5F20\u5361\u662F**\u4E00\u6761\u6D41\u7A0B/\u8C03\u7528\u94FE\u7684\u6B65\u9AA4**\uFF0C\u628A\u5E8F\u53F7\u5199\u5728 note \u7684\u6700\u524D\u9762\uFF0C\u7528\u6237\u5C31\u80FD\u6309\u53F7\u8BFB\uFF1A\n\n- \u5E8F\u53F7\u6CA1\u6709\u4E13\u95E8\u53C2\u6570\uFF0C\u4E5F\u4E0D\u662F\u9762\u677F\u753B\u7684\u2014\u2014\u5B83\u5C31\u662F\u6B63\u6587\u7684\u5934\u51E0\u4E2A\u5B57\u7B26\uFF0C\u6240\u4EE5\u5361\u7247\u91CC\u3001\u5217\u8868\u91CC\u3001\u590D\u5236\u51FA\u53BB\u7684\u5185\u5BB9\u91CC\u90FD\u5E26\u7740\u5B83\uFF0C\u4F60\u5728\u56DE\u590D\u91CC\u4E5F\u80FD\u5F15\u7528\u540C\u4E00\u4E2A\u53F7\u3002\n- \u53F7\u7531\u4F60\u6392\uFF1A\u6309\u4F60\u5E0C\u671B\u7528\u6237\u9605\u8BFB\u7684\u987A\u5E8F\uFF1B1\u30012\u30013\u2026 \u8FDE\u4E0D\u8FDE\u7EED\u3001\u91CD\u4E0D\u91CD\u590D\u90FD\u968F\u4F60\uFF08**\u4E0D\u9700\u8981\u552F\u4E00**\uFF0C\u8BB2\u540C\u4E00\u4E2A\u70B9\u7684\u8865\u5145\u5361\u53EF\u4EE5\u540C\u53F7\uFF09\u3002\n- \u987A\u5E8F\u53F7\u4E5F\u5199\u8FDB\u4F60\u7684\u56DE\u590D\uFF08\"\u6211\u5728\u4EE3\u7801\u4E0A\u6807\u4E86 1\u20135\uFF0C\u4ECE X \u5F00\u59CB\"\uFF09\uFF0C\u8FD9\u6837\u9762\u677F\u91CC\u7684\u53F7\u548C\u56DE\u590D\u91CC\u7684\u53F7\u5BF9\u5F97\u4E0A\u3002\n- \u96F6\u6563\u7684\u6279\u6CE8\uFF08\u4E0D\u662F\u4E00\u4E32\u6B65\u9AA4\uFF09**\u4E0D\u8981**\u5199\u53F7\u3002\n\n## \u4E00\u5F20\u5361\u4E00\u4E2A\u70B9\n\n- \u8303\u56F4\u8981\u5C0F\uFF1A**\u6700\u591A 60 \u884C**\uFF0C\u901A\u5E38 1\u20135 \u884C\u5C31\u591F\u3002\u8981\u8BB2\u6574\u6BB5\u903B\u8F91\u5C31\u62C6\u6210\u51E0\u5F20\u5361\u3002\n- \u4E00\u6761\u8C03\u7528\u94FE = \u4E00\u5F20\u5361\u4E00\u4E2A\u8C03\u7528\u70B9\uFF0C\u6309\u4F60\u5E94\u8BE5\u8BA9\u7528\u6237\u9605\u8BFB\u7684\u987A\u5E8F\u4F9D\u6B21\u521B\u5EFA\uFF1B\u4E0D\u8981\u628A\u6240\u6709\u6B65\u9AA4\u585E\u8FDB\u4E00\u5F20\u5361\u3002\n- note \u91CC\u53EA\u8C08\u8FD9\u4E9B\u884C\uFF08\u6700\u591A\u5E26\u4E0A\u76F4\u63A5\u76F8\u90BB\u7684\u4E00\u4E24\u884C\uFF09\uFF0C\u4E0D\u8981\u6269\u5230\u6574\u4E2A\u6587\u4EF6\u6216\u6574\u4E2A\u4EFB\u52A1\u3002\n- \u5199\u6CD5\u6CBF\u7528\u6279\u6CE8\u7684\u89C4\u77E9\uFF1A\u4E0D\u8D85\u8FC7 3 \u884C\u3001\u884C\u95F4\u4E0D\u7A7A\u884C\u3001**\u4E0D\u8981 Markdown \u8868\u683C/\u5217\u8868/\u6807\u9898/\u56F4\u680F\u4EE3\u7801\u5757**\uFF08\u5361\u7247\u6309\u884C\u6392\u7248\uFF0C\u8868\u683C\u4F1A\u8BFB\u6210\u4E00\u5806\u7AD6\u7EBF\u5E76\u628A\u9AD8\u5EA6\u7B97\u9519\uFF09\uFF0C\u884C\u5185\u53EA\u7528 `\u4EE3\u7801` \u548C **\u52A0\u7C97**\u3002\u8981\u5F15\u7528\u522B\u5904\u5C31\u5199 `\u6587\u4EF6:\u884C\u53F7`\u3002\n- \u7528\u7528\u6237\u7684\u8BED\u8A00\u5199 note\u3002\n\n## \u90A3\u51E0\u884C\u5DF2\u7ECF\u88AB\u5360\u7528\u65F6\n\n\u5982\u679C\u8FD9\u4E9B\u884C\u5DF2\u7ECF\u843D\u5728**\u67D0\u5F20\u5361\u7247\u91CC**\uFF0C\u8C03\u7528\u4F1A\u88AB\u62D2\uFF0C\u62D2\u7EDD\u4FE1\u606F\u91CC\u4F1A\u5199\u660E\u662F\u54EA\u4E00\u5F20\uFF08id\u3001\u884C\u53F7\u3001\u5B83\u5F00\u5934\u7684\u8BDD\uFF09\u3002\u8FD9\u4E0D\u662F\u9519\u8BEF\uFF0C\u662F\"\u8FD9\u91CC\u5DF2\u7ECF\u6709\u8BDD\u8BF4\u4E86\"\uFF1A\n\n- \u6362\u4E00\u5904\u884C\u53F7\uFF1B\u6216\u8005\n- \u628A\u8FD9\u4EF6\u4E8B\u5199\u8FDB\u4F60\u7684\u56DE\u590D\u91CC\uFF0C\u4E0D\u8981\u8BD5\u56FE\u786C\u585E\u8FDB\u90A3\u5F20\u5361\uFF1A\u90A3\u5F20\u5361\u7684\u5BF9\u8BDD\u5C5E\u4E8E\u5199\u5B83\u7684\u4EBA\uFF08\u53EF\u80FD\u662F\u7528\u6237\uFF0C\u4E5F\u53EF\u80FD\u662F\u4F60\u65E9\u5148\u5199\u7684\uFF09\u3002\u5982\u679C\u7528\u6237\u60F3\u5728\u90A3\u5F20\u5361\u4E0A\u7EE7\u7EED\u804A\uFF0C\u4ED6\u4F1A\u5728\u5361\u7247\u91CC\u56DE\u590D\u4F60\uFF0C\u90A3\u65F6\u4F60\u4F1A\u6536\u5230 `[\u8BC4\u8BBA]`\uFF0C\u6309 `dsh-diff-approval-comment` \u7684\u89C4\u77E9\u56DE\u7B54\u5373\u53EF\u3002\n\n**\u4E0D\u8981**\u5728\u56DE\u590D\u91CC\u5047\u88C5\u5DF2\u7ECF\u6279\u6CE8\u6210\u529F\u2014\u2014\u5DE5\u5177\u8FD4\u56DE\u7684\u662F\"refused: ...\"\u5C31\u8BF4\u660E\u6CA1\u6709\u5361\u7247\u88AB\u521B\u5EFA\u3002\n";
19
+ export declare const ANNOTATE_SKILL_CONTENT = "# \u7528\u5361\u7247\u7ED9\u4EE3\u7801\u505A\u6279\u6CE8\n\n\u6539\u52A8\u5BA1\u6279\u9762\u677F\u91CC\u7684\u5361\u7247 = \u9488\u5BF9**\u5177\u4F53\u51E0\u884C\u4EE3\u7801**\u7684\u5BF9\u8BDD\u3002\u4F60\u5199\u7684\u6279\u6CE8\u4F1A\u6210\u4E3A\u5361\u7247\u7684\u7B2C\u4E00\u6761\u5185\u5BB9\uFF08\u4F60\u5728\u5DE5\u5177\u91CC\u5199\u7684 `note`\uFF09\uFF0C\u7528\u6237\u5C31\u5728\u4EE3\u7801\u65C1\u8FB9\u770B\u5230\u5B83\uFF0C\u5E76\u4E14\u53EF\u4EE5\u5728\u8FD9\u5F20\u5361\u7247\u91CC\u56DE\u4F60\uFF1B\u4ED6\u7684\u56DE\u590D\u4F1A\u4EE5 `[\u8BC4\u8BBA] (path:lines)` \u7684\u6D88\u606F\u56DE\u5230\u4F60\u3002\n\n## \u4EC0\u4E48\u65F6\u5019\u8BE5\u7528\n\n- \u7528\u6237\u60F3\u8BFB\u4EE3\u7801\uFF1A\u628A**\u8C03\u7528\u94FE**\u4E00\u6B65\u6B65\u6279\u6CE8\u51FA\u6765\uFF08\u6BCF\u4E2A\u5173\u952E\u8C03\u7528\u70B9\u4E00\u5F20\u5361\uFF0C\u6309\u9605\u8BFB\u987A\u5E8F\uFF09\uFF0C\u6BD4\u5728\u56DE\u590D\u91CC\u8D34\u4E00\u5927\u6BB5\u4EE3\u7801\u6216\u884C\u53F7\u6E05\u5355\u6E05\u695A\u5F97\u591A\u3002\n- \u4F60\u8981\u6307\u51FA\u67D0\u6BB5\u4EE3\u7801\u7684\u95EE\u9898\u3001\u7406\u7531\u3001\u6216\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9\uFF08Review \u573A\u666F\uFF09\uFF0C\u8BA9\u8BC1\u636E\u5C31\u8D34\u5728\u8BC1\u636E\u6240\u5728\u7684\u884C\u4E0A\u3002\n- \u4F60\u6B63\u5728\u8BA8\u8BBA\u67D0\u6BB5\u4EE3\u7801\uFF0C\u60F3\u628A\u8BDD\u76F4\u63A5\u6302\u5728\u90A3\u4E9B\u884C\u4E0A\uFF0C\u800C\u4E0D\u662F\u8BA9\u7528\u6237\u5728\u56DE\u590D\u91CC\u5BF9\u7740\u884C\u53F7\u627E\u3002\n\n\u4E0D\u8981\u5728\u7528\u6237\u6CA1\u8BA9\u4F60\u8BB2\u4EE3\u7801\u65F6\u5237\u5361\u7247\uFF0C\u4E5F\u4E0D\u8981\u7528\u5B83\u4EE3\u66FF\u56DE\u590D\uFF1A\u5361\u7247\u662F**\u8865\u5145**\uFF0C\u4F60\u7684\u56DE\u7B54\u8FD8\u662F\u8981\u5199\u5728\u56DE\u590D\u91CC\uFF08\u53EF\u4EE5\u7B80\u77ED\u8BF4\"\u5DF2\u5728\u4EE3\u7801\u4E0A\u6807\u4E86 3 \u5904\"\u5E76\u7ED9\u51FA\u8981\u70B9\uFF09\u3002\n\n## \u600E\u4E48\u8C03\u7528 `diff_approval_annotate`\n\n- `path`\uFF1A\u9762\u677F\u91CC\u90A3\u4E2A\u6587\u4EF6\u3002\u4F60\u8BFB\u6587\u4EF6\u65F6\u7528\u7684\u8DEF\u5F84\u4E5F\u884C\uFF08\u6309\u5C3E\u90E8\u5339\u914D\uFF09\uFF1B\u5339\u914D\u5230\u591A\u4E2A\u4F1A\u88AB\u62D2\uFF0C\u628A\u5B8C\u6574\u8DEF\u5F84\u7ED9\u5B83\u3002\n **\u6587\u4EF6\u8FD8\u4E0D\u5728\u9762\u677F\u7684\u5217\u8868\u91CC\u4E5F\u6CA1\u5173\u7CFB\uFF1A\u4F1A\u81EA\u52A8\u52A0\u8FDB\u53BB**\uFF08\u5DE5\u4F5C\u533A\u91CC\u80FD\u8BFB\u6210\u6587\u672C\u7684\u6587\u4EF6\uFF09\uFF0C\u6240\u4EE5\"\u7528\u6237\u60F3\u8BFB\u61C2\u67D0\u4E2A\u6587\u4EF6\"\u4E0D\u5FC5\u5148\u7B49\u6539\u52A8\u53D1\u751F\u3002\u5DE5\u4F5C\u533A\u4E4B\u5916\u3001\u6216\u8BFB\u4E0D\u51FA\u6587\u672C\uFF0C\u624D\u4F1A\u88AB\u62D2\u3002\n- `startLine` / `endLine`\uFF1A**\u73B0\u5728**\u7684\u884C\u53F7\uFF081 \u8D77\uFF0C\u542B\u4E24\u7AEF\uFF1B\u7701\u7565 `endLine` \u5C31\u662F\u4E00\u884C\uFF09\u3002\u5148\u8BFB\u6587\u4EF6\u518D\u5199\u53F7\uFF0C\u522B\u51ED\u8BB0\u5FC6\u3002\n- `note`\uFF1A\u5361\u7247\u4E0A\u5199\u7684\u8BDD\u3002\u8981\u77ED\u2014\u2014\u5361\u7247\u662F**\u6309\u884C**\u6392\u7248\u3001\u884C\u9AD8\u6309\u884C\u7B97\u7684\uFF08\u4E0A\u9650 1000 \u5B57\u7B26\uFF0C\u8D85\u4E86\u4F1A\u88AB\u62D2\uFF09\u3002\u8BB2\u6D41\u7A0B\u65F6\uFF0C\u628A\u8FD9\u4E00\u6B65\u7684\u5E8F\u53F7\u5199\u5728 note \u7684**\u6700\u524D\u9762**\uFF08`1. \u2026`\u3001`2. \u2026`\uFF09\u3002\n- `quote`\uFF08\u53EF\u9009\uFF0C\u5EFA\u8BAE\u7ED9\uFF09\uFF1A\u4F60\u8BFB\u5230\u7684\u90A3\u51E0\u884C\u539F\u6587\uFF08\u6362\u884C\u8FDE\u63A5\uFF09\u3002\u6587\u4EF6\u5728\u4F60\u8BFB\u5B8C\u4E4B\u540E\u53C8\u53D8\u4E86\u7684\u8BDD\uFF0C\u4F1A\u5F53\u573A\u88AB\u62D2\u5E76\u628A\u73B0\u5728\u7684\u539F\u6587\u7ED9\u4F60\uFF0C\u907F\u514D\u6279\u6CE8\u6302\u5728\u9519\u8BEF\u7684\u884C\u4E0A\u3002\n- `category`\uFF08\u53EF\u9009\uFF09\uFF1A**\u7ED9\"\u4E00\u7C7B\u6279\u6CE8\"\u8D77\u4E00\u4E2A id**\u3002\u540C\u4E00\u7C7B\uFF08\u540C\u4E00\u8F6E\u3001\u540C\u4E00\u4E3B\u9898\u3001\u540C\u4E00\u6B21\u8BB2\u89E3\uFF09\u6BCF\u6B21\u8C03\u7528\u90FD\u4F20**\u540C\u4E00\u4E2A** id\uFF0C\u6362\u6210\u53E6\u4E00\u7C7B\u5C31\u6362\u4E00\u4E2A id\u3002\u9762\u677F\u4F1A\u6309\u8FD9\u4E2A id \u7ED9\u8BC4\u8BBA\u5217\u8868\u91CC\u7684\u90A3\u6761\u8BC4\u8BBA\u753B\u4E00\u4E2A**\u5F69\u8272\u5706\u70B9**\uFF0C\u6240\u4EE5**\u540C\u4E00\u7C7B\u7684\u6279\u6CE8\u662F\u540C\u4E00\u4E2A\u989C\u8272**\uFF0C\u4E24\u7C7B\u4E4B\u95F4\u53EF\u4EE5\u9760\u989C\u8272\u533A\u5206\u3002**\u4E0D\u4F20 `category` \u5C31\u5B8C\u5168\u4E0D\u753B\u5706\u70B9**\u2014\u2014\u5B83\u662F\u53EF\u9009\u7684\uFF0C\u5706\u70B9\u53EA\u4E3A\"\u6709\u7C7B\u522B\"\u7684\u6279\u6CE8\u800C\u753B\u3002\n - \u989C\u8272\u53EA\u6709 12 \u79CD\uFF0Cid \u662F\u6563\u5217\u5230\u989C\u8272\u4E0A\u7684\uFF0C\u6240\u4EE5**\u4E24\u4E2A\u4E0D\u540C\u7684 id \u53EF\u80FD\u649E\u6210\u540C\u4E00\u4E2A\u989C\u8272**\uFF0C\u90A3\u65F6\u8FD9\u4E24\u7C7B\u770B\u8D77\u6765\u4E00\u6837\uFF1A\u8FD9\u4E0D\u662F\"\u5206\u4E86\u51E0\u7C7B\u4E00\u76EE\u4E86\u7136\"\uFF0C\u53EA\u662F\"\u540C\u4E00\u7C7B\u989C\u8272\u4E00\u81F4\"\u3002\u60F3\u8BA9\u4EBA\u5206\u5F97\u6E05\uFF0C\u5C31**\u6709\u610F\u8BC6\u5730\u590D\u7528\u540C\u4E00\u4E2A id**\uFF0C\u4E0D\u8981\u7ED9\u540C\u4E00\u7C7B\u6362\u65B0 id\u3002\n - id \u672C\u8EAB\u4E0D\u89E3\u6790\uFF1A\u968F\u4FBF\u7ED9\uFF08uuid \u4E5F\u884C\uFF09\u3002\u989C\u8272\u7531\u5B83\u7B97\u51FA\u6765\uFF1B\u4F60\u5199\u7684 id \u53EA\u51FA\u73B0\u5728\u5706\u70B9\u7684 **`title` / `aria-label`** \u91CC\uFF08\u9F20\u6807\u60AC\u505C\u3001\u6216\u8BFB\u5C4F\u8F6F\u4EF6\uFF09\uFF0C**\u4E0D\u662F\u5C4F\u5E55\u4E0A\u7684\u6587\u5B57**\u3002\u4F1A\u53BB\u6389\u4E24\u7AEF\u7A7A\u767D\uFF1B\u6700\u591A 64 \u4E2A\u5B57\u7B26\uFF0C\u8D85\u4E86**\u622A\u65AD**\uFF08\u4E0D\u4F1A\u56E0\u6B64\u62D2\u6389\u6574\u6761\u6279\u6CE8\uFF09\u3002\n\n## \u8BB2\u6D41\u7A0B\u5C31\u5728\u6B63\u6587\u5F00\u5934\u5199\u5E8F\u53F7\n\n\u5982\u679C\u8FD9\u51E0\u5F20\u5361\u662F**\u4E00\u6761\u6D41\u7A0B/\u8C03\u7528\u94FE\u7684\u6B65\u9AA4**\uFF0C\u628A\u5E8F\u53F7\u5199\u5728 note \u7684\u6700\u524D\u9762\uFF0C\u7528\u6237\u5C31\u80FD\u6309\u53F7\u8BFB\uFF1A\n\n- \u5E8F\u53F7\u6CA1\u6709\u4E13\u95E8\u53C2\u6570\uFF0C\u4E5F\u4E0D\u662F\u9762\u677F\u753B\u7684\u2014\u2014\u5B83\u5C31\u662F\u6B63\u6587\u7684\u5934\u51E0\u4E2A\u5B57\u7B26\uFF0C\u6240\u4EE5\u5361\u7247\u91CC\u3001\u5217\u8868\u91CC\u3001\u590D\u5236\u51FA\u53BB\u7684\u5185\u5BB9\u91CC\u90FD\u5E26\u7740\u5B83\uFF0C\u4F60\u5728\u56DE\u590D\u91CC\u4E5F\u80FD\u5F15\u7528\u540C\u4E00\u4E2A\u53F7\u3002\n- \u53F7\u7531\u4F60\u6392\uFF1A\u6309\u4F60\u5E0C\u671B\u7528\u6237\u9605\u8BFB\u7684\u987A\u5E8F\uFF1B1\u30012\u30013\u2026 \u8FDE\u4E0D\u8FDE\u7EED\u3001\u91CD\u4E0D\u91CD\u590D\u90FD\u968F\u4F60\uFF08**\u4E0D\u9700\u8981\u552F\u4E00**\uFF0C\u8BB2\u540C\u4E00\u4E2A\u70B9\u7684\u8865\u5145\u5361\u53EF\u4EE5\u540C\u53F7\uFF09\u3002\n- \u987A\u5E8F\u53F7\u4E5F\u5199\u8FDB\u4F60\u7684\u56DE\u590D\uFF08\"\u6211\u5728\u4EE3\u7801\u4E0A\u6807\u4E86 1\u20135\uFF0C\u4ECE X \u5F00\u59CB\"\uFF09\uFF0C\u8FD9\u6837\u9762\u677F\u91CC\u7684\u53F7\u548C\u56DE\u590D\u91CC\u7684\u53F7\u5BF9\u5F97\u4E0A\u3002\n- \u96F6\u6563\u7684\u6279\u6CE8\uFF08\u4E0D\u662F\u4E00\u4E32\u6B65\u9AA4\uFF09**\u4E0D\u8981**\u5199\u53F7\u3002\n\n## \u4E00\u5F20\u5361\u4E00\u4E2A\u70B9\n\n- \u8303\u56F4\u8981\u5C0F\uFF1A**\u6700\u591A 60 \u884C**\uFF0C\u901A\u5E38 1\u20135 \u884C\u5C31\u591F\u3002\u8981\u8BB2\u6574\u6BB5\u903B\u8F91\u5C31\u62C6\u6210\u51E0\u5F20\u5361\u3002\n- \u4E00\u6761\u8C03\u7528\u94FE = \u4E00\u5F20\u5361\u4E00\u4E2A\u8C03\u7528\u70B9\uFF0C\u6309\u4F60\u5E94\u8BE5\u8BA9\u7528\u6237\u9605\u8BFB\u7684\u987A\u5E8F\u4F9D\u6B21\u521B\u5EFA\uFF1B\u4E0D\u8981\u628A\u6240\u6709\u6B65\u9AA4\u585E\u8FDB\u4E00\u5F20\u5361\u3002\n- note \u91CC\u53EA\u8C08\u8FD9\u4E9B\u884C\uFF08\u6700\u591A\u5E26\u4E0A\u76F4\u63A5\u76F8\u90BB\u7684\u4E00\u4E24\u884C\uFF09\uFF0C\u4E0D\u8981\u6269\u5230\u6574\u4E2A\u6587\u4EF6\u6216\u6574\u4E2A\u4EFB\u52A1\u3002\n- \u5199\u6CD5\u6CBF\u7528\u6279\u6CE8\u7684\u89C4\u77E9\uFF1A\u4E0D\u8D85\u8FC7 3 \u884C\u3001\u884C\u95F4\u4E0D\u7A7A\u884C\u3001**\u4E0D\u8981 Markdown \u8868\u683C/\u5217\u8868/\u6807\u9898/\u56F4\u680F\u4EE3\u7801\u5757**\uFF08\u5361\u7247\u6309\u884C\u6392\u7248\uFF0C\u8868\u683C\u4F1A\u8BFB\u6210\u4E00\u5806\u7AD6\u7EBF\u5E76\u628A\u9AD8\u5EA6\u7B97\u9519\uFF09\uFF0C\u884C\u5185\u53EA\u7528 `\u4EE3\u7801` \u548C **\u52A0\u7C97**\u3002\u8981\u5F15\u7528\u522B\u5904\u5C31\u5199 `\u6587\u4EF6:\u884C\u53F7`\u3002\n- \u7528\u7528\u6237\u7684\u8BED\u8A00\u5199 note\u3002\n\n## \u90A3\u51E0\u884C\u5DF2\u7ECF\u88AB\u5360\u7528\u65F6\n\n\u5982\u679C\u8FD9\u4E9B\u884C\u5DF2\u7ECF\u843D\u5728**\u67D0\u5F20\u5361\u7247\u91CC**\uFF0C\u8C03\u7528\u4F1A\u88AB\u62D2\uFF0C\u62D2\u7EDD\u4FE1\u606F\u91CC\u4F1A\u5199\u660E\u662F\u54EA\u4E00\u5F20\uFF08id\u3001\u884C\u53F7\u3001\u5B83\u5F00\u5934\u7684\u8BDD\uFF09\u3002\u8FD9\u4E0D\u662F\u9519\u8BEF\uFF0C\u662F\"\u8FD9\u91CC\u5DF2\u7ECF\u6709\u8BDD\u8BF4\u4E86\"\uFF1A\n\n- \u6362\u4E00\u5904\u884C\u53F7\uFF1B\u6216\u8005\n- \u628A\u8FD9\u4EF6\u4E8B\u5199\u8FDB\u4F60\u7684\u56DE\u590D\u91CC\uFF0C\u4E0D\u8981\u8BD5\u56FE\u786C\u585E\u8FDB\u90A3\u5F20\u5361\uFF1A\u90A3\u5F20\u5361\u7684\u5BF9\u8BDD\u5C5E\u4E8E\u5199\u5B83\u7684\u4EBA\uFF08\u53EF\u80FD\u662F\u7528\u6237\uFF0C\u4E5F\u53EF\u80FD\u662F\u4F60\u65E9\u5148\u5199\u7684\uFF09\u3002\u5982\u679C\u7528\u6237\u60F3\u5728\u90A3\u5F20\u5361\u4E0A\u7EE7\u7EED\u804A\uFF0C\u4ED6\u4F1A\u5728\u5361\u7247\u91CC\u56DE\u590D\u4F60\uFF0C\u90A3\u65F6\u4F60\u4F1A\u6536\u5230 `[\u8BC4\u8BBA]`\uFF0C\u6309 `dsh-diff-approval-comment` \u7684\u89C4\u77E9\u56DE\u7B54\u5373\u53EF\u3002\n\n**\u4E0D\u8981**\u5728\u56DE\u590D\u91CC\u5047\u88C5\u5DF2\u7ECF\u6279\u6CE8\u6210\u529F\u2014\u2014\u5DE5\u5177\u8FD4\u56DE\u7684\u662F\"refused: ...\"\u5C31\u8BF4\u660E\u6CA1\u6709\u5361\u7247\u88AB\u521B\u5EFA\u3002\n";
20
20
  /** One runtime skill contribution, in the shape `ctx.skills.register` takes. */
21
21
  export interface AnnotateSkillRegistration {
22
22
  /** Kebab-case identity the agent loads by. */
@@ -46,6 +46,13 @@ export interface AnnotateToolArgs {
46
46
  endLine?: number | undefined;
47
47
  /** What the card says. Kept short: the card is drawn line by line beside the code. */
48
48
  note: string;
49
+ /**
50
+ * Optional class of annotation — the same id for every annotation of one kind, a different one for the
51
+ * next. The panel draws a coloured round dot from it (see `category-color.ts`), so an agent's several
52
+ * passes over the same review are tellable apart at a glance. Opaque: hashed for the colour and shown
53
+ * back to the reader as written. Trimmed, and cut to 64 characters.
54
+ */
55
+ category?: string | undefined;
49
56
  /** Optional guard: the exact text the caller believes those lines hold (newline-joined). */
50
57
  quote?: string | undefined;
51
58
  }
@@ -90,6 +97,10 @@ export declare const ANNOTATE_TOOL_PARAMETERS: {
90
97
  readonly type: "string";
91
98
  readonly description: string;
92
99
  };
100
+ readonly category: {
101
+ readonly type: "string";
102
+ readonly description: string;
103
+ };
93
104
  };
94
105
  };
95
106
  /**
@@ -43,6 +43,26 @@ export declare const MAX_ANNOTATION_LINES = 60;
43
43
  * own reply to the user, which is not measured in code rows.
44
44
  */
45
45
  export declare const MAX_ANNOTATION_CHARS = 1000;
46
+ /**
47
+ * The most characters a category id may carry.
48
+ *
49
+ * The id is a grouping key, not prose: it is hashed for a colour and shown back in the mark's own label,
50
+ * so anything past this is noise the reader would never see. Longer ids are TRUNCATED rather than
51
+ * refused (see {@link normalizeCategory}).
52
+ */
53
+ export declare const MAX_ANNOTATION_CATEGORY_CHARS = 64;
54
+ /**
55
+ * The category id as it is stored: trimmed, and cut to {@link MAX_ANNOTATION_CATEGORY_CHARS}.
56
+ *
57
+ * TRUNCATED rather than refused: the id is only ever hashed into a colour and echoed in the mark's label,
58
+ * so an over-long one still groups its annotations consistently — every call of that class is cut in the
59
+ * same place — while refusing would fail an entire annotation over a cosmetic detail. Absent, empty and
60
+ * whitespace-only all mean the same thing: no class, so no dot (see `CommentRecord.category`).
61
+ *
62
+ * @param value - the id the caller passed, if any.
63
+ * @returns the id to store, or `undefined` when there is none.
64
+ */
65
+ export declare function normalizeCategory(value: string | undefined): string | undefined;
46
66
  /** What the agent asked for, once the tool layer has resolved which pending entry it means. */
47
67
  export interface AnnotationRequest {
48
68
  /** The session the annotation belongs to, i.e. the one whose panel will draw it. */
@@ -58,6 +78,14 @@ export interface AnnotationRequest {
58
78
  endLine?: number | undefined;
59
79
  /** The annotation itself: the card's first turn, written by the agent. */
60
80
  note: string;
81
+ /**
82
+ * Optional class of annotation: the same id for every annotation of one kind, a different one for the
83
+ * next. Opaque to the host and to the panel — hashed into a colour and shown back to the reader in the
84
+ * mark's label — so an agent annotating several passes can be told apart at a glance. Normalised by
85
+ * {@link normalizeCategory}: trimmed, empty means absent, cut to
86
+ * {@link MAX_ANNOTATION_CATEGORY_CHARS}.
87
+ */
88
+ category?: string | undefined;
61
89
  /**
62
90
  * Optional guard: the text the caller believes those lines read, newline-joined.
63
91
  *
@@ -22,15 +22,12 @@ import type { VisibleLines } from './windowed-highlight.ts';
22
22
  * floor is not just a drag limit, it is the width at which the footer is still itself.
23
23
  */
24
24
  export declare const MIN_LIST_WIDTH_PX = 260;
25
- /** Normalize a path for comparison: forward slashes, no trailing slash. */
26
- export declare function normalizeDiffPath(p: string): string;
27
- /** Whether a produced-file chip path and a pending file path refer to the same
28
- * file, tolerant of separator style (\\ vs /) and of a workspace-relative vs
29
- * absolute form. `chipPath` is typically the harness's workspace-relative
30
- * forward-slash path; `filePath` is the host's absolute native-separator path.
31
- * Matching is case-insensitive so a Windows drive/segment case difference does
32
- * not miss the file the user clicked. */
33
- export declare function diffPathsMatch(chipPath: string, filePath: string, workspacePath: string | undefined): boolean;
25
+ /**
26
+ * Path comparison, re-exported from its own module so every existing importer keeps working: the panel's
27
+ * own jump, the plugin's press bridge and the store reader all ask the same question, and they must not
28
+ * each carry their own answer (see `path-match.ts`).
29
+ */
30
+ export { diffPathsMatch, normalizeDiffPath } from './path-match.ts';
34
31
  /** The dsh shell's sidebar auto-collapse breakpoint (ui-layout columns.ts):
35
32
  * below it the sidebar auto-collapses, and the file list floats on the same
36
33
  * breakpoint so the two stay consistent. */
@@ -82,17 +79,27 @@ export interface PendingPanelDockProps {
82
79
  docked?: boolean;
83
80
  /** The element the docked panel portals its content into. */
84
81
  dockHost?: HTMLElement;
82
+ /**
83
+ * Whether this seat is SHOWING anything, and so whether it should read the host at all.
84
+ *
85
+ * A seat that is not on screen — a docked tab the reader has switched away from — draws nothing, so
86
+ * its poll reads a list nobody is looking at, once a second, for a session the reader may not even be
87
+ * in. `false` stops that read; the seat keeps what it last read and starts again the moment it is
88
+ * shown. Absent means "always showing", which is what the footer entry is: its badge is the reader's
89
+ * at-a-glance count, and a badge that never read would simply show nothing.
90
+ */
91
+ showing?: boolean;
92
+ /**
93
+ * Ask the host how many rows this session has, WITHOUT reading the list (`list-count`).
94
+ *
95
+ * This is what the tick asks while this seat has no surface on screen: the badge is the thing that has
96
+ * to keep working while the panel is shut, and the full read is what makes it slow (it ships every
97
+ * visible entry's whole old and new text). A seat that IS on screen keeps the full read, and so does a
98
+ * face that offers no counter at all — absent means "this face cannot count", which is today's
99
+ * behaviour: one full read per tick.
100
+ */
101
+ onRefreshCount?: ((sessionId: SessionId | undefined) => void) | undefined;
85
102
  }
86
- /**
87
- * Open the DSH settings dialog and switch to this plugin's section. The
88
- * settings shell keeps its open state and the active section id as
89
- * component-local viewing state with no cross-plugin service, so the dialog
90
- * is opened by clicking the sidebar's settings trigger and then the nav cell
91
- * for this section. `element.click()` still fires React's delegated click
92
- * handlers, reaching the same state transitions a user gesture would.
93
- * @param sectionLabel - the nav label of this plugin's settings section.
94
- */
95
- export declare function openSettingsSection(sectionLabel: string): void;
96
103
  /**
97
104
  * How much of the window the app itself occupies on each side of the conversation
98
105
  * — how far the floating panel has to start from an edge to leave that part
@@ -237,5 +244,4 @@ export declare function fittingItems(widths: readonly number[], available: numbe
237
244
  */
238
245
  export declare function inlineItemCount(widths: readonly number[], available: number, gap: number, overflowWidth: number): number;
239
246
  /** Render the pending-edit review panel and its unified footer action. */
240
- export declare function PendingPanel({ wide, useSessions, sessionId, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPreviewImage, onPasteReference, onCommentAdd, onCommentRemove, onCommentRemoveMany, onCommentAsk, onUndo, onRedo, onImportVcs, onRefreshVcs, onBrowse, onAddPath, onKeepAll, onRevertAll, onKeepMany, onRevertMany, onAckRedoCleared, onAckUndoNotice, collapseSidebar, t, docked, dockHost, onOpenDock, closeDock, useDock, }: PendingPanelProps): import("react").JSX.Element;
241
- export {};
247
+ export declare function PendingPanel({ wide, useSessions, sessionId, usePending, pendingView, showing, onRefresh, onRefreshCount, onMarkSeen, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPreviewImage, onPasteReference, onCommentAdd, onCommentRemove, onCommentRemoveMany, onCommentAsk, onCommentSeen, onUndo, onRedo, onImportVcs, onRefreshVcs, onBrowse, onAddPath, onKeepAll, onKeepMany, onRevertMany, onAckRedoCleared, onAckUndoNotice, collapseSidebar, t, docked, dockHost, onOpenDock, closeDock, useDock, onCheckUpdate, }: PendingPanelProps): import("react").JSX.Element;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The colour a comment's CATEGORY is drawn as: one round dot per class of annotation.
3
+ *
4
+ * An agent annotating several passes over the same review (a call-chain walk, then the findings, then a
5
+ * second round of questions) can pass the same `category` id for every annotation of one kind and a
6
+ * different id for the next — and the reader then sees at a glance which class each comment belongs to,
7
+ * without reading a word. The id itself is opaque here: this module never parses it, only hashes it.
8
+ *
9
+ * The mapping is a plain hash into a fixed palette, so it is the SAME colour on any host and after any
10
+ * reload, with nothing persisted beyond the id the record already carries. Two ids can collide on one
11
+ * colour — 12 buckets cannot promise otherwise — which is why the reader also gets the id in words
12
+ * (`title`/`aria-label`): colour is a fast cue, never the only one.
13
+ *
14
+ * @module dsh-diff-approval/src/client/category-color
15
+ */
16
+ /**
17
+ * The twelve colours, in the order the hash indexes them — and THE ORDER IS PART OF THE CONTRACT, because
18
+ * the index is the bucket (see `categoryColorIndex`).
19
+ *
20
+ * The SET was chosen by CIEDE2000, not by eye and not by hue angle: it is a coordinate-ascent result over
21
+ * twelve colour families, and its MINIMUM pairwise ΔE00 is **18.82** — owned by the light blue and the grey
22
+ * — with every entry between L* 42 and 70, so each reads as a mark on the panel's light and dark surfaces
23
+ * alike. An earlier palette looked well spaced on the hue wheel and was not: indigo `#6E56CF` against
24
+ * purple `#8E4EC6` sat 20° apart at the same lightness and chroma — ΔE00 **6.94** on a 3px mark — and a
25
+ * near-duplicate green `#57a751` would have passed a hue-angle floor at ΔE00 2.65.
26
+ *
27
+ * THE ORDER was then solved for SEPARATELY (2026-10-06), because the set's spacing says nothing about the
28
+ * spacing of NEIGHBOURING buckets: the array used to be a hue ramp, so two categories whose hashes landed
29
+ * on adjacent indices — 2 times out of 12, which is the reader's own pair at indices 7 and 8 — differed by
30
+ * as little as ΔE00 19.28. The sequence below is the bottleneck Hamiltonian path over those same twelve
31
+ * colours: the order that MAXIMISES the MINIMUM ΔE00 over the eleven consecutive pairs, proved optimal by
32
+ * a DP over (mask, last) in the scratch script that chose it. Its consecutive minimum is **32.7475** — the
33
+ * full value is 32.74748843826888, which is why the test's floor is 32.7474 and not the rounded figure —
34
+ * owned by the grey and the red, against 19.2835 for the shipped order, and the set itself is byte-identical,
35
+ * so the whole-palette floor above is still 18.82. `tests/category-color.client.spec.ts` asserts BOTH numbers
36
+ * (whole-set and consecutive) plus the L* band, so a thirteenth colour or a reshuffle fails a test rather
37
+ * than shipping.
38
+ *
39
+ * Two categories can still collide EXACTLY — twelve buckets cannot promise otherwise, and `alpha`/`beta` in
40
+ * the spec do — so the promise this order keeps is "adjacent buckets differ a lot", never "different ids
41
+ * always differ"; colour is a fast cue, and the id in the mark's own `title`/`aria-label` is the exact one.
42
+ */
43
+ export declare const CATEGORY_COLORS: readonly ["#7F888E", "#C33D41", "#6A5CA4", "#7AAB83", "#B8A3CA", "#1D6F66", "#DC54B9", "#80A5EB", "#8D711B", "#13A9BF", "#577F11", "#C19784"];
44
+ /**
45
+ * Which palette entry a category id maps to: FNV-1a (32-bit) over the id's UTF-16 code units, mod 12.
46
+ *
47
+ * FNV-1a because it is four lines, has no dependencies, and spreads uuid-shaped ids (the reader's own
48
+ * suggestion: "passing a uuid per call") well enough that a handful of categories rarely collide. It is
49
+ * pinned by a test with a fixed id, so changing the hash is a visible decision rather than a silent
50
+ * recolouring of every existing annotation.
51
+ *
52
+ * @param category - the category id, as it was stored (already trimmed and capped by the tool rule).
53
+ * @returns the index into {@link CATEGORY_COLORS}, 0..11.
54
+ */
55
+ export declare function categoryColorIndex(category: string): number;
56
+ /**
57
+ * The colour one category is drawn as.
58
+ *
59
+ * @param category - the category id.
60
+ * @returns a `#RRGGBB` string from {@link CATEGORY_COLORS}.
61
+ */
62
+ export declare function categoryColor(category: string): string;
@@ -9,13 +9,6 @@
9
9
  * @module dsh-diff-approval/client/chords
10
10
  */
11
11
  import type { Translator } from './locales.ts';
12
- /**
13
- * One stored chord as a hint renders it: modifiers as written, arrow keys as
14
- * glyphs (`Ctrl+ArrowUp` → `Ctrl+↑`).
15
- * @param chord - the stored chord.
16
- * @returns the hint text; `''` for an unbound action.
17
- */
18
- export declare function chordHint(chord: string): string;
19
12
  /**
20
13
  * One action's chord as a hint.
21
14
  * @param action - the keybinding action id (see `DEFAULT_KEYBINDINGS`).
@@ -31,19 +24,79 @@ export declare function chordLabel(action: string): string;
31
24
  * @returns the label, with ` (chord)` appended when one is configured.
32
25
  */
33
26
  export declare function withChord(label: string, action: string): string;
27
+ /** One chord in both the forms a tooltip needs, read from a single setting so the two cannot drift. */
28
+ export interface ChordShortcut {
29
+ /**
30
+ * The keycaps, in order, with a literal `'+'` between the parts: the shell renders one `<kbd>` per
31
+ * entry and groups a combination into a single keycap when the array carries a separator (see the
32
+ * primitives' `ShortcutKeys`).
33
+ */
34
+ keys: string[];
35
+ /** The `aria-keyshortcuts` value: the same chord spelled in DOM key names. */
36
+ aria: string;
37
+ }
38
+ /**
39
+ * One action's shortcut, as a tooltip's `shortcutKeys` and the anchor's `aria-keyshortcuts`.
40
+ * @param action - the keybinding action id (see `DEFAULT_KEYBINDINGS`).
41
+ * @returns the two forms, or `undefined` when the action is unbound.
42
+ */
43
+ export declare function shortcutOf(action: string): ChordShortcut | undefined;
44
+ /**
45
+ * The quick-summon chord: its own setting rather than one of `DEFAULT_KEYBINDINGS`, since it is the
46
+ * one chord the panel is opened BY rather than one it answers inside.
47
+ * @returns the two forms, or `undefined` when the chord is unbound.
48
+ */
49
+ export declare function summonShortcut(): ChordShortcut | undefined;
50
+ /**
51
+ * Escape alone: the key the INNERMOST dismissible answers to (the search bar, a dialog), which no
52
+ * panel chord stands behind — the quick-summon chord closes the panel, not the bar inside it.
53
+ * @returns the keycaps and the aria form.
54
+ */
55
+ export declare function escapeShortcut(): ChordShortcut;
56
+ /**
57
+ * The panel's close button: Escape always, plus the quick-summon chord while one is bound.
58
+ *
59
+ * This is the one place the shell's one-chord model needs a judgment: these are two WAYS out, not a
60
+ * sequence, so they stay two keycaps (`['Esc', 'Ctrl+D']`) and two space-separated aria shortcuts —
61
+ * grouping them into one cap with separators would read as "press Esc, then Ctrl+D".
62
+ * @returns the keycaps and the aria form.
63
+ */
64
+ export declare function closeShortcut(): ChordShortcut;
65
+ /** What one tooltip site hands the shell, decided here so that no call site ever branches. */
66
+ export interface TooltipChord {
67
+ /**
68
+ * The label for the shell's `Tooltip`: the action's own name where the shell draws keycaps, and the
69
+ * label this plugin spelled before the primitives' 0.1.7-rc.2 — chord glued in — where it cannot.
70
+ */
71
+ label: string;
72
+ /** The keycaps to pass, or `undefined` when there is no chord or this host cannot draw one. */
73
+ shortcutKeys: readonly string[] | undefined;
74
+ /** The anchor's `aria-keyshortcuts`: plain text, and the same on every host. */
75
+ aria: string | undefined;
76
+ }
77
+ /**
78
+ * A tooltip for one action's chord.
79
+ * @param label - the translated action label.
80
+ * @param action - the keybinding action id, or `undefined` for a control that has no chord at all.
81
+ * @returns the label, keycaps and aria; an unbound or absent action keeps the plain label.
82
+ */
83
+ export declare function actionTooltip(label: string, action: string | undefined): TooltipChord;
84
+ /**
85
+ * The entry buttons that open the panel (the session header's, the footer badge): what it holds, and
86
+ * the chord that does the same. With the chord unbound the plain label is the whole hint.
87
+ * @param t - the panel's translator.
88
+ * @returns the label, keycaps and aria.
89
+ */
90
+ export declare function summonTooltip(t: Translator): TooltipChord;
34
91
  /**
35
- * How the panel's close button names its two ways out: Escape, and the
36
- * quick-summon chord when the user still has one bound. Unbinding the chord
37
- * leaves Escape as the only answer, so the hint then says just that.
92
+ * The panel's close button: Escape, plus the quick-summon chord while one is bound.
38
93
  * @param t - the panel's translator.
39
- * @returns the tooltip label.
94
+ * @returns the label, keycaps and aria.
40
95
  */
41
- export declare function closeHint(t: Translator): string;
96
+ export declare function closeTooltip(t: Translator): TooltipChord;
42
97
  /**
43
- * How an entry button names what it opens: the pending-changes panel, plus the
44
- * chord that does the same. With the chord unbound the plain label is the whole
45
- * hint — never an empty parenthetical.
98
+ * A control only Escape dismisses — the search bar — which no panel chord stands behind.
46
99
  * @param t - the panel's translator.
47
- * @returns the tooltip label.
100
+ * @returns the label, keycaps and aria.
48
101
  */
49
- export declare function summonHint(t: Translator): string;
102
+ export declare function escapeTooltip(t: Translator): TooltipChord;
@@ -127,6 +127,13 @@ export interface Discussion {
127
127
  quoteWrap?: boolean;
128
128
  /** How many older messages the row cap left out of the render. */
129
129
  hidden?: number;
130
+ /**
131
+ * Something the reader has not looked at yet arrived in this thread — an agent's own annotation, or
132
+ * an answer to one of its questions — so the card wears the dot. Host truth, carried through from
133
+ * the stored record (see `CommentRecord.unseen`): the block draws it and the card's own visibility
134
+ * is what asks the host to take it down.
135
+ */
136
+ unseen?: boolean;
130
137
  }
131
138
  /** Rows a folded block occupies: its header line. */
132
139
  export declare const DISCUSSION_HEADER_ROWS = 1;
@@ -14,7 +14,8 @@
14
14
  */
15
15
  import type { ReactNode } from 'react';
16
16
  import type { HostObservable, PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
17
- import type { PendingDiffSnapshot } from './slots.ts';
17
+ import type { SessionId } from '@deepseek-ai/dsh-client-connection/client';
18
+ import type { PendingDiffSnapshot, PendingViewHooks } from './slots.ts';
18
19
  /** The tab type's `kind`: what `openTab` names. */
19
20
  export declare const DIFF_DOCK_KIND = "diff-approval";
20
21
  /** The registration's `id`: the key its body and title register under. The
@@ -120,11 +121,15 @@ type TabInfoHook = () => {
120
121
  readonly visible: boolean;
121
122
  };
122
123
  };
123
- export interface DiffDockBodyProps extends PropsLocale<'diff-approval'> {
124
+ export interface DiffDockBodyProps extends PropsLocale<'diff-approval'>, PendingViewHooks {
124
125
  /** The seat's own tab hook (the sidebar framework injects it). */
125
126
  readonly useTabInfo?: TabInfoHook;
126
- /** This plugin's pending store hook, for the chip's count. */
127
+ /** This plugin's pending store hook, for the chip's count where no per-session reader reaches it. */
127
128
  readonly usePending?: (select: (snapshot: PendingDiffSnapshot) => unknown) => unknown;
129
+ /** The session seat, when this host composes one into the tab (see `session-seat.ts`). */
130
+ readonly useSessions?: ((select: (state: unknown) => unknown) => unknown) | undefined;
131
+ /** The session this dock tab belongs to, when the shell composes one. */
132
+ readonly sessionId?: SessionId | undefined;
128
133
  /** Whether the panel renders as the docked body (set by the tab seat's face). */
129
134
  readonly docked?: boolean;
130
135
  /** Report this body's visibility to the dock state (see {@link DockFace}). */
@@ -24,6 +24,7 @@
24
24
  * @module dsh-diff-approval/client/dsh-icons
25
25
  */
26
26
  import * as primitives from '@deepseek-ai/dsh-client-ui-primitives';
27
+ import type { ReactElement } from 'react';
27
28
  /** The pending-changes glyph: the sidebar's badge and the header entry carry it. */
28
29
  export declare const IconListPenOutline16: ({ size, className }: primitives.IconProps) => import("react").JSX.Element;
29
30
  /** The list's fold chevrons. */
@@ -56,5 +57,42 @@ export declare const IconSettingsOutline16: ({ size, className }: primitives.Ico
56
57
  * Re-exported so one module names everything this plugin takes from the shell's primitives: these
57
58
  * names have survived both releases, and a caller has no reason to reach past this file.
58
59
  */
59
- export { Menu, Toast, Tooltip, writeClipboard } from '@deepseek-ai/dsh-client-ui-primitives';
60
+ export { Menu, Toast, writeClipboard } from '@deepseek-ai/dsh-client-ui-primitives';
60
61
  export type { MenuEntry } from '@deepseek-ai/dsh-client-ui-primitives';
62
+ /** The tooltip props this plugin uses, including the one the installed types do not know yet. */
63
+ export interface ShellTooltipProps {
64
+ label: string;
65
+ side?: 'right' | 'bottom' | 'top' | undefined;
66
+ delayMs?: number | undefined;
67
+ maxWidth?: number | undefined;
68
+ disabled?: boolean | undefined;
69
+ /**
70
+ * The keycaps the bubble renders AFTER its label, one `<kbd>` per entry, with a literal `'+'`
71
+ * between the parts so the shell groups a combination into a single keycap. `undefined` (or an
72
+ * empty array) renders no keycaps at all — which is what an unbound action passes.
73
+ */
74
+ shortcutKeys?: readonly string[] | undefined;
75
+ children: ReactElement;
76
+ }
77
+ /**
78
+ * The primitives' `Tooltip`, typed with the props above.
79
+ *
80
+ * `shortcutKeys` arrived in the primitives' 0.1.7-rc.2 — the release the host runs — while what this
81
+ * repo COMPILES against is 0.1.0-rc.6, whose `Tooltip.d.ts` predates it. Passing the prop at a call
82
+ * site is therefore a type error even though the running component accepts it (and an older one simply
83
+ * ignores an unknown prop). The cast lives here, once, at the same boundary this module already uses
84
+ * to bridge shell versions, rather than at every call site.
85
+ */
86
+ export declare const Tooltip: (props: ShellTooltipProps) => ReactElement;
87
+ /**
88
+ * Whether the running shell can draw a shortcut beside a tooltip's label.
89
+ *
90
+ * `ShortcutKeys` and the `Tooltip.shortcutKeys` prop shipped together in the primitives'
91
+ * **0.1.7-rc.2**: across all 24 installed versions this plugin is tested against, the component is
92
+ * absent from every release up to and including 0.1.7-rc.1 (`lib/index.js` does not contain the name
93
+ * at all, and `Tooltip.d.ts` takes no `shortcutKeys`) and present from 0.1.7-rc.2 on (`function
94
+ * ShortcutKeys(...)`, exported, and `shortcutKeys?: readonly string[]` on `Tooltip`) — the same
95
+ * release the prop arrived in, so the two can never disagree. An older host ignores an unknown prop
96
+ * silently, which is why a caller must not rely on the prop alone (see `chords.ts`).
97
+ */
98
+ export declare const SHELL_DRAWS_SHORTCUTS: boolean;
@@ -20,14 +20,15 @@
20
20
  import type { ReactNode } from 'react';
21
21
  import type { HostObservable, InjectFace, PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
22
22
  import type { SessionId } from '@deepseek-ai/dsh-client-connection/client';
23
- import type { PendingDiffSnapshot } from './slots.ts';
23
+ import type { PendingDiffSnapshot, PendingViewHooks } from './slots.ts';
24
24
  import type { DockSnapshot } from './dock.tsx';
25
- /** What the header entry reads from this plugin's own face: the two observables.
26
- * Everything else it needs (the button's own click) goes through the window
27
- * events, so the entry never holds a copy of the panel's state. */
28
- export interface HeaderEntryFace {
25
+ /** What the header entry reads from this plugin's own face: the two observables, and the per-session
26
+ * view reader (`pendingView`) that keeps its count on ITS session. Everything else it needs (the
27
+ * button's own click) goes through the window events, so the entry never holds a copy of the panel's
28
+ * state. */
29
+ export interface HeaderEntryFace extends PendingViewHooks {
29
30
  hooks: {
30
- /** Live pending-diff snapshot: the count on the button. */
31
+ /** Live pending-diff snapshot: the fallback count for a face with no per-session reader. */
31
32
  pending: HostObservable<PendingDiffSnapshot>;
32
33
  /** The dock's state, absent in a build without a right sidebar. */
33
34
  dock?: HostObservable<DockSnapshot>;
@@ -71,4 +72,4 @@ export type DiffApprovalHeaderEntryProps = InjectFace<HeaderEntryFace> & HeaderE
71
72
  * @param props - the bound hooks, the session seat, and the translator.
72
73
  * @returns the icon button, with the pending count while there is one.
73
74
  */
74
- export declare function DiffApprovalHeaderEntry({ usePending, useSessions, useDock, sessionId, t }: DiffApprovalHeaderEntryProps): ReactNode;
75
+ export declare function DiffApprovalHeaderEntry({ usePending, useSessions, useDock, pendingView, sessionId, t }: DiffApprovalHeaderEntryProps): ReactNode;
@@ -14,7 +14,6 @@ export declare const zh: {
14
14
  'panel.tab.pending': string;
15
15
  'panel.tab.comments': string;
16
16
  'panel.commentsEmpty': string;
17
- 'panel.commentOutdated': string;
18
17
  'panel.aria': string;
19
18
  'panel.stats': string;
20
19
  'panel.blockPosition': string;
@@ -23,12 +22,22 @@ export declare const zh: {
23
22
  'panel.blockSingle': string;
24
23
  'chip.openDefault': string;
25
24
  'chip.reviewInPanel': string;
25
+ 'chip.copyPath': string;
26
+ 'chip.about': string;
27
+ 'chip.about.title': string;
28
+ 'panel.confirmFileTitle': string;
29
+ 'panel.batchConfirmTitle': string;
30
+ 'chip.about.body': string;
31
+ 'chip.about.ok': string;
32
+ 'update.chip': string;
33
+ 'update.body': string;
34
+ 'update.npm': string;
35
+ 'update.github': string;
36
+ 'update.dismiss': string;
26
37
  'chip.gone': string;
27
38
  'panel.fileNotPending': string;
28
39
  'panel.selectHint': string;
29
40
  'panel.searchPlaceholder': string;
30
- 'panel.missing': string;
31
- 'panel.missingHint': string;
32
41
  'panel.externalChanged': string;
33
42
  'panel.dismiss': string;
34
43
  'panel.pasteOnCopy': string;
@@ -76,6 +85,8 @@ export declare const zh: {
76
85
  'settings.commentDesc': string;
77
86
  'settings.diffView': string;
78
87
  'settings.diffViewDesc': string;
88
+ 'settings.chipMenu': string;
89
+ 'settings.chipMenu.help': string;
79
90
  'settings.diffPreview': string;
80
91
  'panel.keyDesc': string;
81
92
  'panel.shortcutNone': string;
@@ -98,26 +109,29 @@ export declare const zh: {
98
109
  'panel.key.coverRight': string;
99
110
  'panel.key.coverTop': string;
100
111
  'settings.tabLabel': string;
101
- 'row.create': string;
102
112
  'row.failed': string;
113
+ 'panel.unseen': string;
114
+ 'panel.commentCategory': string;
103
115
  'row.dismiss': string;
104
116
  'row.keepListed': string;
105
117
  'row.keepRemove': string;
106
118
  'row.revertRemove': string;
119
+ 'row.deleteRemove': string;
107
120
  'panel.batchKeepAsk': string;
108
121
  'panel.batchKeepRemoveAsk': string;
109
122
  'panel.batchRevertAsk': string;
110
123
  'panel.batchRevertRemoveAsk': string;
111
124
  'panel.batchKeepAllAsk': string;
112
125
  'panel.batchRevertAllAsk': string;
126
+ 'panel.batchRevertAllDeletedAsk': string;
113
127
  'panel.batchCloseAsk': string;
114
128
  'panel.batchDeletes': string;
115
- 'panel.batchAndMore': string;
129
+ 'panel.batchDeletesList': string;
116
130
  'panel.batchGo': string;
117
131
  'panel.removeOneAsk': string;
118
132
  'panel.removeCommentsOne': string;
119
133
  'panel.removeCommentsMany': string;
120
- 'panel.removeCommentsMore': string;
134
+ 'panel.batchCommentsList': string;
121
135
  'row.added': string;
122
136
  'row.removed': string;
123
137
  'action.keep': string;
@@ -232,6 +246,7 @@ export declare const zh: {
232
246
  'panel.addNoEntries': string;
233
247
  'panel.addMissing': string;
234
248
  'panel.addOutside': string;
249
+ 'panel.addOtherSession': string;
235
250
  'panel.addNotAFile': string;
236
251
  'panel.addFailed': string;
237
252
  'action.cancel': string;
@@ -263,7 +278,6 @@ export declare const en: {
263
278
  'panel.tab.pending': string;
264
279
  'panel.tab.comments': string;
265
280
  'panel.commentsEmpty': string;
266
- 'panel.commentOutdated': string;
267
281
  'panel.aria': string;
268
282
  'panel.stats': string;
269
283
  'panel.blockPosition': string;
@@ -272,12 +286,22 @@ export declare const en: {
272
286
  'panel.blockSingle': string;
273
287
  'chip.openDefault': string;
274
288
  'chip.reviewInPanel': string;
289
+ 'chip.copyPath': string;
290
+ 'chip.about': string;
291
+ 'chip.about.title': string;
292
+ 'panel.confirmFileTitle': string;
293
+ 'panel.batchConfirmTitle': string;
294
+ 'chip.about.body': string;
295
+ 'chip.about.ok': string;
296
+ 'update.chip': string;
297
+ 'update.body': string;
298
+ 'update.npm': string;
299
+ 'update.github': string;
300
+ 'update.dismiss': string;
275
301
  'chip.gone': string;
276
302
  'panel.fileNotPending': string;
277
303
  'panel.selectHint': string;
278
304
  'panel.searchPlaceholder': string;
279
- 'panel.missing': string;
280
- 'panel.missingHint': string;
281
305
  'panel.externalChanged': string;
282
306
  'panel.dismiss': string;
283
307
  'panel.pasteOnCopy': string;
@@ -325,6 +349,8 @@ export declare const en: {
325
349
  'settings.commentDesc': string;
326
350
  'settings.diffView': string;
327
351
  'settings.diffViewDesc': string;
352
+ 'settings.chipMenu': string;
353
+ 'settings.chipMenu.help': string;
328
354
  'settings.diffPreview': string;
329
355
  'panel.keyDesc': string;
330
356
  'panel.shortcutNone': string;
@@ -347,26 +373,29 @@ export declare const en: {
347
373
  'panel.key.coverRight': string;
348
374
  'panel.key.coverTop': string;
349
375
  'settings.tabLabel': string;
350
- 'row.create': string;
351
376
  'row.failed': string;
377
+ 'panel.unseen': string;
378
+ 'panel.commentCategory': string;
352
379
  'row.dismiss': string;
353
380
  'row.keepListed': string;
354
381
  'row.keepRemove': string;
355
382
  'row.revertRemove': string;
383
+ 'row.deleteRemove': string;
356
384
  'panel.batchKeepAsk': string;
357
385
  'panel.batchKeepRemoveAsk': string;
358
386
  'panel.batchRevertAsk': string;
359
387
  'panel.batchRevertRemoveAsk': string;
360
388
  'panel.batchKeepAllAsk': string;
361
389
  'panel.batchRevertAllAsk': string;
390
+ 'panel.batchRevertAllDeletedAsk': string;
362
391
  'panel.batchCloseAsk': string;
363
392
  'panel.batchDeletes': string;
364
- 'panel.batchAndMore': string;
393
+ 'panel.batchDeletesList': string;
365
394
  'panel.batchGo': string;
366
395
  'panel.removeOneAsk': string;
367
396
  'panel.removeCommentsOne': string;
368
397
  'panel.removeCommentsMany': string;
369
- 'panel.removeCommentsMore': string;
398
+ 'panel.batchCommentsList': string;
370
399
  'row.added': string;
371
400
  'row.removed': string;
372
401
  'action.keep': string;
@@ -481,6 +510,7 @@ export declare const en: {
481
510
  'panel.addNoEntries': string;
482
511
  'panel.addMissing': string;
483
512
  'panel.addOutside': string;
513
+ 'panel.addOtherSession': string;
484
514
  'panel.addNotAFile': string;
485
515
  'panel.addFailed': string;
486
516
  'action.cancel': string;