dsh-diff-approval 0.29.0 → 0.29.1

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/README.md CHANGED
@@ -97,3 +97,11 @@ pnpm run fonts:plan # what a page actually downloads, by how many hanzi it show
97
97
  ```
98
98
 
99
99
  The bundled font is [JetBrains Maple Mono](https://github.com/SpaceTimee/Fusion-JetBrainsMapleMono) (SIL OFL 1.1), subset and sliced by `scripts/fonts` — see [`assets/fonts/README.md`](assets/fonts/README.md) for the pipeline, the licence and what the slices cost.
100
+
101
+ A `file:` profile install copies what the package's `files` list named *at install time*, so a checkout whose list grew needs a refresh before the host can hand the new files out:
102
+
103
+ ```sh
104
+ npx @deepseek-ai/dsh plugin --profile web install # then restart `dsh web`
105
+ ```
106
+
107
+ Only the client half reloads on its own (its bundle is watched), so a client change shows up on a page refresh while a host-half change — like the route that serves the font — waits for the restart.
package/README.zh.md CHANGED
@@ -97,3 +97,11 @@ pnpm run fonts:plan # 页面上出现多少汉字时实际会下载多少
97
97
  ```
98
98
 
99
99
  内置字体是 [JetBrains Maple Mono](https://github.com/SpaceTimee/Fusion-JetBrainsMapleMono)(SIL OFL 1.1),由 `scripts/fonts` 子集化并切片——流水线、许可证与各切片的体积见 [`assets/fonts/README.md`](assets/fonts/README.md)。
100
+
101
+ `file:` 方式安装的 profile 只复制**安装当时** `files` 列出的文件,所以本地 checkout 后来新增的文件(如 `assets/fonts`)必须先刷新安装,宿主才拿得到:
102
+
103
+ ```sh
104
+ npx @deepseek-ai/dsh plugin --profile web install # 然后重启 `dsh web`
105
+ ```
106
+
107
+ 客户端那半会自己热更新(它的 bundle 被监听),所以客户端改动刷新页面即可;宿主那半的改动(例如提供字体的这条路由)要等重启才生效。
package/lib/client.js CHANGED
@@ -31,272 +31,272 @@ window.__ModuleLoader__.load({
31
31
  document.head.appendChild(tag);
32
32
  }
33
33
  var PendingPanel_module_css_default = {
34
- "gotoLayerRight": "F1KBNa_gotoLayerRight",
35
- "addButton": "F1KBNa_addButton",
34
+ "gotoHost": "F1KBNa_gotoHost",
35
+ "chip": "F1KBNa_chip",
36
+ "splitRdel": "F1KBNa_splitRdel",
37
+ "discussionCode": "F1KBNa_discussionCode",
38
+ "diffActions": "F1KBNa_diffActions",
39
+ "missing": "F1KBNa_missing",
40
+ "quoteLines": "F1KBNa_quoteLines",
41
+ "divergedHint": "F1KBNa_divergedHint",
42
+ "gotoBox": "F1KBNa_gotoBox",
43
+ "searchBar": "F1KBNa_searchBar",
44
+ "headerActions": "F1KBNa_headerActions",
45
+ "listTitle": "F1KBNa_listTitle",
46
+ "actionError": "F1KBNa_actionError",
47
+ "missingHint": "F1KBNa_missingHint",
48
+ "splitCols": "F1KBNa_splitCols",
49
+ "noteCentered": "F1KBNa_noteCentered",
50
+ "listFold": "F1KBNa_listFold",
51
+ "fileListShrink": "F1KBNa_fileListShrink",
52
+ "gotoBackdrop": "F1KBNa_gotoBackdrop",
53
+ "toggle": "F1KBNa_toggle",
54
+ "diff": "F1KBNa_diff",
55
+ "tree": "F1KBNa_tree",
56
+ "searchToggle": "F1KBNa_searchToggle",
57
+ "layer": "F1KBNa_layer",
58
+ "quoteSplitTable": "F1KBNa_quoteSplitTable",
36
59
  "colorPickerPanel": "F1KBNa_colorPickerPanel",
37
- "diffPreviewTitle": "F1KBNa_diffPreviewTitle",
38
- "discussionNote": "F1KBNa_discussionNote",
39
- "rowFailed": "F1KBNa_rowFailed",
40
- "pickerForm": "F1KBNa_pickerForm",
41
- "dockHost": "F1KBNa_dockHost",
42
- "floatResizeHandle": "F1KBNa_floatResizeHandle",
43
- "noticeButton": "F1KBNa_noticeButton",
44
- "notice": "F1KBNa_notice",
60
+ "splitSealedLeft": "F1KBNa_splitSealedLeft",
61
+ "addButton": "F1KBNa_addButton",
62
+ "threadFontProbe": "F1KBNa_threadFontProbe",
63
+ "commentGroup": "F1KBNa_commentGroup",
64
+ "colorPickerChevron": "F1KBNa_colorPickerChevron",
65
+ "gutter": "F1KBNa_gutter",
66
+ "pickerName": "F1KBNa_pickerName",
67
+ "discussionInput": "F1KBNa_discussionInput",
45
68
  "splitCol": "F1KBNa_splitCol",
46
- "layer": "F1KBNa_layer",
47
- "colorSwatch": "F1KBNa_colorSwatch",
48
- "mdPreviewBody": "F1KBNa_mdPreviewBody",
49
- "divider": "F1KBNa_divider",
50
- "splitRoot": "F1KBNa_splitRoot",
51
- "markerSplitDel": "F1KBNa_markerSplitDel",
52
- "discussionCode": "F1KBNa_discussionCode",
53
- "group": "F1KBNa_group",
54
- "badge": "F1KBNa_badge",
55
- "quoteSplitSide": "F1KBNa_quoteSplitSide",
69
+ "settingsRowText": "F1KBNa_settingsRowText",
70
+ "overviewRuler": "F1KBNa_overviewRuler",
71
+ "discussionAnswer": "F1KBNa_discussionAnswer",
72
+ "panelDocked": "F1KBNa_panelDocked",
73
+ "panelFailureRetry": "F1KBNa_panelFailureRetry",
74
+ "searchInput": "F1KBNa_searchInput",
75
+ "colorPickerInput": "F1KBNa_colorPickerInput",
76
+ "pickerCheck": "F1KBNa_pickerCheck",
56
77
  "splitHScrollFill": "F1KBNa_splitHScrollFill",
57
- "fileListFloatClosing": "F1KBNa_fileListFloatClosing",
58
- "bulkActions": "F1KBNa_bulkActions",
59
- "settingsRow": "F1KBNa_settingsRow",
60
- "discussionHead": "F1KBNa_discussionHead",
61
- "rowDiscussed": "F1KBNa_rowDiscussed",
62
- "listTabs": "F1KBNa_listTabs",
78
+ "title": "F1KBNa_title",
79
+ "addPath": "F1KBNa_addPath",
80
+ "discussionRow": "F1KBNa_discussionRow",
63
81
  "quoteLine": "F1KBNa_quoteLine",
64
- "split": "F1KBNa_split",
65
- "kindTag": "F1KBNa_kindTag",
66
- "gotoLayer": "F1KBNa_gotoLayer",
67
- "langLabel": "F1KBNa_langLabel",
68
- "tabCount": "F1KBNa_tabCount",
82
+ "intraAdd": "F1KBNa_intraAdd",
83
+ "settingsSelector": "F1KBNa_settingsSelector",
84
+ "fileList": "F1KBNa_fileList",
85
+ "gotoLayerRight": "F1KBNa_gotoLayerRight",
86
+ "stepperValue": "F1KBNa_stepperValue",
87
+ "badge": "F1KBNa_badge",
88
+ "diffBody": "F1KBNa_diffBody",
69
89
  "groupHead": "F1KBNa_groupHead",
70
- "presentationSelect": "F1KBNa_presentationSelect",
71
- "searchToggleOn": "F1KBNa_searchToggleOn",
72
- "overviewRuler": "F1KBNa_overviewRuler",
73
- "coverNotice": "F1KBNa_coverNotice",
74
- "flexSpacer": "F1KBNa_flexSpacer",
75
- "panelDocked": "F1KBNa_panelDocked",
76
- "action": "F1KBNa_action",
77
- "discussionDot": "F1KBNa_discussionDot",
78
- "splitDiscussions": "F1KBNa_splitDiscussions",
79
- "settingsRowText": "F1KBNa_settingsRowText",
80
- "discussionSend": "F1KBNa_discussionSend",
81
- "settingsGroupBody": "F1KBNa_settingsGroupBody",
90
+ "bulkActions": "F1KBNa_bulkActions",
91
+ "quoteText": "F1KBNa_quoteText",
92
+ "colorPickerTrigger": "F1KBNa_colorPickerTrigger",
93
+ "settingsRow": "F1KBNa_settingsRow",
94
+ "floatResizeHandle": "F1KBNa_floatResizeHandle",
82
95
  "discussionBody": "F1KBNa_discussionBody",
83
- "intraAdd": "F1KBNa_intraAdd",
84
- "splitHScroll": "F1KBNa_splitHScroll",
85
- "colorValue": "F1KBNa_colorValue",
86
- "tree": "F1KBNa_tree",
87
- "diffPreview": "F1KBNa_diffPreview",
88
- "missingHint": "F1KBNa_missingHint",
89
- "searchMatchCurrent": "F1KBNa_searchMatchCurrent",
90
- "diffFlashShake": "F1KBNa_diffFlashShake",
91
- "discussionPin": "F1KBNa_discussionPin",
92
- "quoteSplit": "F1KBNa_quoteSplit",
96
+ "notice": "F1KBNa_notice",
93
97
  "fileListKnobIn": "F1KBNa_fileListKnobIn",
94
- "stepperButton": "F1KBNa_stepperButton",
95
- "pickerIcon": "F1KBNa_pickerIcon",
96
- "kindHint": "F1KBNa_kindHint",
97
- "rowMenuAnchor": "F1KBNa_rowMenuAnchor",
98
- "splitSealedRight": "F1KBNa_splitSealedRight",
99
- "discussionSlack": "F1KBNa_discussionSlack",
100
- "splitRdel": "F1KBNa_splitRdel",
101
98
  "settingsGroupText": "F1KBNa_settingsGroupText",
102
- "importNote": "F1KBNa_importNote",
103
- "diffBodyWrap": "F1KBNa_diffBodyWrap",
104
- "pickerNote": "F1KBNa_pickerNote",
105
- "diffBodySplit": "F1KBNa_diffBodySplit",
106
- "coverButton": "F1KBNa_coverButton",
107
- "quoteDel": "F1KBNa_quoteDel",
108
- "listFold": "F1KBNa_listFold",
109
- "treeCaret": "F1KBNa_treeCaret",
110
- "mdPreviewDouble": "F1KBNa_mdPreviewDouble",
111
- "colorSv": "F1KBNa_colorSv",
112
- "commentHead": "F1KBNa_commentHead",
113
- "fileListKnob": "F1KBNa_fileListKnob",
114
- "confirmBackdrop": "F1KBNa_confirmBackdrop",
115
- "listScroll": "F1KBNa_listScroll",
116
- "diffFlashFade": "F1KBNa_diffFlashFade",
117
- "hint": "F1KBNa_hint",
118
- "actionQuietDisabled": "F1KBNa_actionQuietDisabled",
99
+ "splitRadd": "F1KBNa_splitRadd",
100
+ "settingsGroupHeader": "F1KBNa_settingsGroupHeader",
101
+ "toggleThumb": "F1KBNa_toggleThumb",
102
+ "markerDel": "F1KBNa_markerDel",
103
+ "states": "F1KBNa_states",
104
+ "colorSwatch": "F1KBNa_colorSwatch",
105
+ "diffFlashShake": "F1KBNa_diffFlashShake",
106
+ "row": "F1KBNa_row",
107
+ "noticeButton": "F1KBNa_noticeButton",
108
+ "settingsGroupBody": "F1KBNa_settingsGroupBody",
109
+ "searchMatchCurrent": "F1KBNa_searchMatchCurrent",
119
110
  "subline": "F1KBNa_subline",
120
- "gutter": "F1KBNa_gutter",
121
- "colorPicker": "F1KBNa_colorPicker",
122
- "colorPickerTrigger": "F1KBNa_colorPickerTrigger",
123
- "searchCount": "F1KBNa_searchCount",
124
- "splitDiscussion": "F1KBNa_splitDiscussion",
125
- "settingsSelector": "F1KBNa_settingsSelector",
126
- "discussionRangeWrap": "F1KBNa_discussionRangeWrap",
127
- "splitLadd": "F1KBNa_splitLadd",
128
- "stepper": "F1KBNa_stepper",
129
- "badgeLabel": "F1KBNa_badgeLabel",
130
- "commentRow": "F1KBNa_commentRow",
131
- "rowHead": "F1KBNa_rowHead",
132
- "colorPickerPreview": "F1KBNa_colorPickerPreview",
133
- "quoteText": "F1KBNa_quoteText",
134
- "expandExpanded": "F1KBNa_expandExpanded",
135
- "settingsRowLink": "F1KBNa_settingsRowLink",
136
- "markerAdd": "F1KBNa_markerAdd",
111
+ "treeRow": "F1KBNa_treeRow",
112
+ "pickerForm": "F1KBNa_pickerForm",
113
+ "discussionUser": "F1KBNa_discussionUser",
114
+ "rowPath": "F1KBNa_rowPath",
115
+ "discussionSlack": "F1KBNa_discussionSlack",
116
+ "discussionDot": "F1KBNa_discussionDot",
137
117
  "colorPickerInputRow": "F1KBNa_colorPickerInputRow",
138
- "discussionRow": "F1KBNa_discussionRow",
139
- "coverHost": "F1KBNa_coverHost",
140
- "stepperValue": "F1KBNa_stepperValue",
141
- "colorPickerPopover": "F1KBNa_colorPickerPopover",
142
- "colorHue": "F1KBNa_colorHue",
143
- "close": "F1KBNa_close",
144
- "mirrored": "F1KBNa_mirrored",
145
- "settingsRowTitle": "F1KBNa_settingsRowTitle",
146
- "coverNoticeCard": "F1KBNa_coverNoticeCard",
147
- "discussionCompose": "F1KBNa_discussionCompose",
148
- "confirmActions": "F1KBNa_confirmActions",
149
- "colorBackdrop": "F1KBNa_colorBackdrop",
150
- "readError": "F1KBNa_readError",
151
- "importButton": "F1KBNa_importButton",
152
- "coverCard": "F1KBNa_coverCard",
153
- "toggle": "F1KBNa_toggle",
154
- "noticeText": "F1KBNa_noticeText",
155
- "resizeHandle": "F1KBNa_resizeHandle",
156
- "note": "F1KBNa_note",
157
- "actionPrimary": "F1KBNa_actionPrimary",
158
- "coverNoticeText": "F1KBNa_coverNoticeText",
159
- "diffPreviewScroll": "F1KBNa_diffPreviewScroll",
118
+ "markerAdd": "F1KBNa_markerAdd",
119
+ "searchCount": "F1KBNa_searchCount",
120
+ "commentGroupName": "F1KBNa_commentGroupName",
121
+ "rows": "F1KBNa_rows",
122
+ "split": "F1KBNa_split",
160
123
  "settingsGroup": "F1KBNa_settingsGroup",
161
- "splitSealed": "F1KBNa_splitSealed",
162
- "footerButtons": "F1KBNa_footerButtons",
163
- "blockPosition": "F1KBNa_blockPosition",
164
- "pickerCard": "F1KBNa_pickerCard",
165
- "panelFailureText": "F1KBNa_panelFailureText",
166
- "discussionUser": "F1KBNa_discussionUser",
167
- "settingsRowDesc": "F1KBNa_settingsRowDesc",
168
- "delCount": "F1KBNa_delCount",
169
- "discussionInput": "F1KBNa_discussionInput",
170
- "overviewRulerSplit": "F1KBNa_overviewRulerSplit",
171
- "commentTitle": "F1KBNa_commentTitle",
124
+ "emptyActions": "F1KBNa_emptyActions",
125
+ "discussionDots": "F1KBNa_discussionDots",
126
+ "searchMatch": "F1KBNa_searchMatch",
127
+ "stepperButtonUp": "F1KBNa_stepperButtonUp",
128
+ "langLabel": "F1KBNa_langLabel",
129
+ "emptyState": "F1KBNa_emptyState",
130
+ "fileListFloatClosing": "F1KBNa_fileListFloatClosing",
131
+ "divider": "F1KBNa_divider",
132
+ "settingsGroupTitle": "F1KBNa_settingsGroupTitle",
133
+ "blockActions": "F1KBNa_blockActions",
134
+ "presentationHost": "F1KBNa_presentationHost",
135
+ "coverButton": "F1KBNa_coverButton",
136
+ "settingsGroupChevron": "F1KBNa_settingsGroupChevron",
137
+ "splitSealedRight": "F1KBNa_splitSealedRight",
138
+ "action": "F1KBNa_action",
139
+ "mdPreviewDouble": "F1KBNa_mdPreviewDouble",
140
+ "treeNote": "F1KBNa_treeNote",
172
141
  "code": "F1KBNa_code",
173
- "line": "F1KBNa_line",
174
- "gotoInput": "F1KBNa_gotoInput",
175
142
  "wrapActive": "F1KBNa_wrapActive",
176
- "iconAction": "F1KBNa_iconAction",
177
- "commentLost": "F1KBNa_commentLost",
178
- "mdPreviewFallback": "F1KBNa_mdPreviewFallback",
179
- "statusAction": "F1KBNa_statusAction",
180
- "settingsGroupHeader": "F1KBNa_settingsGroupHeader",
181
- "actionChord": "F1KBNa_actionChord",
182
- "listTitle": "F1KBNa_listTitle",
183
- "splitHScrollRow": "F1KBNa_splitHScrollRow",
143
+ "badgeLabel": "F1KBNa_badgeLabel",
144
+ "fileListFloat": "F1KBNa_fileListFloat",
184
145
  "colorHueCursor": "F1KBNa_colorHueCursor",
185
- "colorSvCursor": "F1KBNa_colorSvCursor",
186
- "quoteSplitTable": "F1KBNa_quoteSplitTable",
187
- "pickerInput": "F1KBNa_pickerInput",
146
+ "settingsGroupDesc": "F1KBNa_settingsGroupDesc",
147
+ "discussion": "F1KBNa_discussion",
148
+ "toggleOn": "F1KBNa_toggleOn",
149
+ "commentTitle": "F1KBNa_commentTitle",
150
+ "pickerTitle": "F1KBNa_pickerTitle",
151
+ "colorSv": "F1KBNa_colorSv",
152
+ "coverNoticeText": "F1KBNa_coverNoticeText",
153
+ "chipLabel": "F1KBNa_chipLabel",
154
+ "splitRoot": "F1KBNa_splitRoot",
155
+ "pickerCard": "F1KBNa_pickerCard",
156
+ "line": "F1KBNa_line",
157
+ "splitDiscussions": "F1KBNa_splitDiscussions",
158
+ "listTabs": "F1KBNa_listTabs",
159
+ "expandExpanded": "F1KBNa_expandExpanded",
160
+ "del": "F1KBNa_del",
161
+ "noticeText": "F1KBNa_noticeText",
188
162
  "panel": "F1KBNa_panel",
189
- "diff": "F1KBNa_diff",
190
- "gotoHost": "F1KBNa_gotoHost",
191
- "blockFlash": "F1KBNa_blockFlash",
192
- "rowMeta": "F1KBNa_rowMeta",
193
- "panelFailure": "F1KBNa_panelFailure",
194
- "stepperButtonUp": "F1KBNa_stepperButtonUp",
195
- "searchMatch": "F1KBNa_searchMatch",
196
- "overviewMarker": "F1KBNa_overviewMarker",
197
- "title": "F1KBNa_title",
198
- "lines": "F1KBNa_lines",
199
- "wrap": "F1KBNa_wrap",
163
+ "rowMenuAnchor": "F1KBNa_rowMenuAnchor",
200
164
  "add": "F1KBNa_add",
201
- "addPath": "F1KBNa_addPath",
202
- "coverNoticeFade": "F1KBNa_coverNoticeFade",
165
+ "splitHScroll": "F1KBNa_splitHScroll",
166
+ "commentLost": "F1KBNa_commentLost",
167
+ "searchToggleOn": "F1KBNa_searchToggleOn",
168
+ "mirrored": "F1KBNa_mirrored",
203
169
  "splitDivider": "F1KBNa_splitDivider",
204
- "splitLdel": "F1KBNa_splitLdel",
205
- "listHead": "F1KBNa_listHead",
206
- "divergedHint": "F1KBNa_divergedHint",
207
- "blockActionsDivider": "F1KBNa_blockActionsDivider",
208
- "quoteLines": "F1KBNa_quoteLines",
209
- "colorPickerChevron": "F1KBNa_colorPickerChevron",
210
- "mdPreviewSingle": "F1KBNa_mdPreviewSingle",
211
- "fileList": "F1KBNa_fileList",
212
- "commentLabel": "F1KBNa_commentLabel",
213
- "rowPath": "F1KBNa_rowPath",
214
- "listEmpty": "F1KBNa_listEmpty",
215
- "expand": "F1KBNa_expand",
170
+ "pickerIcon": "F1KBNa_pickerIcon",
171
+ "rowFailed": "F1KBNa_rowFailed",
172
+ "colorHue": "F1KBNa_colorHue",
173
+ "gotoLayer": "F1KBNa_gotoLayer",
216
174
  "blockFlashShake": "F1KBNa_blockFlashShake",
217
- "header": "F1KBNa_header",
218
- "commentGroupName": "F1KBNa_commentGroupName",
219
- "discussionAnswer": "F1KBNa_discussionAnswer",
220
- "mdPreviewWrap": "F1KBNa_mdPreviewWrap",
221
- "threadFontProbe": "F1KBNa_threadFontProbe",
222
- "splitCols": "F1KBNa_splitCols",
223
- "diffBody": "F1KBNa_diffBody",
224
- "panelFailureRetry": "F1KBNa_panelFailureRetry",
225
- "markerSplitAdd": "F1KBNa_markerSplitAdd",
226
- "confirmText": "F1KBNa_confirmText",
227
- "langSelect": "F1KBNa_langSelect",
228
- "pickerTitle": "F1KBNa_pickerTitle",
229
- "chip": "F1KBNa_chip",
175
+ "colorValue": "F1KBNa_colorValue",
176
+ "wrap": "F1KBNa_wrap",
177
+ "headerEntry": "F1KBNa_headerEntry",
178
+ "discussionRangeWrap": "F1KBNa_discussionRangeWrap",
179
+ "gotoInput": "F1KBNa_gotoInput",
180
+ "stepper": "F1KBNa_stepper",
181
+ "blockActionsDivider": "F1KBNa_blockActionsDivider",
182
+ "addCount": "F1KBNa_addCount",
183
+ "stepperButton": "F1KBNa_stepperButton",
184
+ "diffHeader": "F1KBNa_diffHeader",
185
+ "statusBar": "F1KBNa_statusBar",
186
+ "settingsRowLink": "F1KBNa_settingsRowLink",
187
+ "kindTag": "F1KBNa_kindTag",
188
+ "rail": "F1KBNa_rail",
230
189
  "gotoAction": "F1KBNa_gotoAction",
231
- "diffActions": "F1KBNa_diffActions",
232
- "blockActions": "F1KBNa_blockActions",
233
- "coverNoticeGlyph": "F1KBNa_coverNoticeGlyph",
190
+ "intraDel": "F1KBNa_intraDel",
191
+ "vSpacer": "F1KBNa_vSpacer",
192
+ "listHead": "F1KBNa_listHead",
193
+ "pickerClose": "F1KBNa_pickerClose",
234
194
  "discussionToggle": "F1KBNa_discussionToggle",
235
- "emptyState": "F1KBNa_emptyState",
236
- "chipLabel": "F1KBNa_chipLabel",
237
- "listTab": "F1KBNa_listTab",
238
- "emptyActions": "F1KBNa_emptyActions",
239
- "commentGroup": "F1KBNa_commentGroup",
240
- "coverPopover": "F1KBNa_coverPopover",
195
+ "settingsRowTitle": "F1KBNa_settingsRowTitle",
196
+ "rowDiscussed": "F1KBNa_rowDiscussed",
197
+ "header": "F1KBNa_header",
198
+ "actionQuietDisabled": "F1KBNa_actionQuietDisabled",
199
+ "discussionPin": "F1KBNa_discussionPin",
200
+ "pickerInput": "F1KBNa_pickerInput",
201
+ "diffPreviewScroll": "F1KBNa_diffPreviewScroll",
202
+ "importButton": "F1KBNa_importButton",
203
+ "diffPreview": "F1KBNa_diffPreview",
204
+ "discussionSend": "F1KBNa_discussionSend",
241
205
  "coverBackdrop": "F1KBNa_coverBackdrop",
242
- "treeName": "F1KBNa_treeName",
243
- "rows": "F1KBNa_rows",
244
- "mdPreviewContent": "F1KBNa_mdPreviewContent",
245
- "chipPresentation": "F1KBNa_chipPresentation",
246
- "splitSealedLeft": "F1KBNa_splitSealedLeft",
247
- "row": "F1KBNa_row",
248
- "settingsGroupChevron": "F1KBNa_settingsGroupChevron",
249
- "addCount": "F1KBNa_addCount",
250
- "vSpacer": "F1KBNa_vSpacer",
251
- "fileListShrink": "F1KBNa_fileListShrink",
252
- "statusBar": "F1KBNa_statusBar",
253
- "presentationHost": "F1KBNa_presentationHost",
254
- "searchBar": "F1KBNa_searchBar",
255
- "fileListFloat": "F1KBNa_fileListFloat",
256
- "context": "F1KBNa_context",
257
- "discussionRange": "F1KBNa_discussionRange",
258
- "headerActions": "F1KBNa_headerActions",
259
- "detailEmpty": "F1KBNa_detailEmpty",
206
+ "panelFailureText": "F1KBNa_panelFailureText",
207
+ "discussionNote": "F1KBNa_discussionNote",
208
+ "splitHScrollRow": "F1KBNa_splitHScrollRow",
209
+ "footerButtons": "F1KBNa_footerButtons",
210
+ "splitSealed": "F1KBNa_splitSealed",
211
+ "overviewMarker": "F1KBNa_overviewMarker",
212
+ "colorBackdrop": "F1KBNa_colorBackdrop",
213
+ "expand": "F1KBNa_expand",
260
214
  "quoteAdd": "F1KBNa_quoteAdd",
261
- "colorPickerInput": "F1KBNa_colorPickerInput",
262
- "intraDel": "F1KBNa_intraDel",
263
- "settingsGroupTitle": "F1KBNa_settingsGroupTitle",
264
- "rail": "F1KBNa_rail",
215
+ "resizeHandle": "F1KBNa_resizeHandle",
216
+ "note": "F1KBNa_note",
265
217
  "settingsReset": "F1KBNa_settingsReset",
266
- "detail": "F1KBNa_detail",
267
- "toggleThumb": "F1KBNa_toggleThumb",
268
- "pickerName": "F1KBNa_pickerName",
269
- "diffHeader": "F1KBNa_diffHeader",
270
- "quoteNoWrap": "F1KBNa_quoteNoWrap",
271
- "badgeCount": "F1KBNa_badgeCount",
272
- "quoteCode": "F1KBNa_quoteCode",
273
- "discussion": "F1KBNa_discussion",
274
- "diffStats": "F1KBNa_diffStats",
275
- "headerEntry": "F1KBNa_headerEntry",
276
- "gotoBackdrop": "F1KBNa_gotoBackdrop",
277
- "del": "F1KBNa_del",
278
- "pickerCheck": "F1KBNa_pickerCheck",
279
- "treeNote": "F1KBNa_treeNote",
280
- "searchInput": "F1KBNa_searchInput",
281
- "settingsGroupDesc": "F1KBNa_settingsGroupDesc",
282
- "toggleOn": "F1KBNa_toggleOn",
283
- "actionError": "F1KBNa_actionError",
284
- "commentTitleEmpty": "F1KBNa_commentTitleEmpty",
285
- "markerDel": "F1KBNa_markerDel",
286
- "discussionDots": "F1KBNa_discussionDots",
287
- "diffPath": "F1KBNa_diffPath",
288
- "treeRow": "F1KBNa_treeRow",
218
+ "blockPosition": "F1KBNa_blockPosition",
219
+ "listEmpty": "F1KBNa_listEmpty",
289
220
  "settingsPage": "F1KBNa_settingsPage",
221
+ "coverNotice": "F1KBNa_coverNotice",
222
+ "mdPreviewBody": "F1KBNa_mdPreviewBody",
223
+ "close": "F1KBNa_close",
224
+ "quoteDel": "F1KBNa_quoteDel",
225
+ "quoteSplitSide": "F1KBNa_quoteSplitSide",
226
+ "diffPath": "F1KBNa_diffPath",
227
+ "detailEmpty": "F1KBNa_detailEmpty",
228
+ "mdPreviewContent": "F1KBNa_mdPreviewContent",
229
+ "colorPickerPopover": "F1KBNa_colorPickerPopover",
230
+ "delCount": "F1KBNa_delCount",
231
+ "listTab": "F1KBNa_listTab",
232
+ "flexSpacer": "F1KBNa_flexSpacer",
233
+ "quoteNoWrap": "F1KBNa_quoteNoWrap",
234
+ "treeName": "F1KBNa_treeName",
235
+ "discussionRange": "F1KBNa_discussionRange",
236
+ "splitLdel": "F1KBNa_splitLdel",
290
237
  "confirmCard": "F1KBNa_confirmCard",
291
- "splitRadd": "F1KBNa_splitRadd",
238
+ "rowHead": "F1KBNa_rowHead",
239
+ "coverCard": "F1KBNa_coverCard",
240
+ "coverNoticeFade": "F1KBNa_coverNoticeFade",
241
+ "treeCaret": "F1KBNa_treeCaret",
242
+ "panelFailure": "F1KBNa_panelFailure",
243
+ "mdPreviewSingle": "F1KBNa_mdPreviewSingle",
244
+ "tabCount": "F1KBNa_tabCount",
245
+ "langSelect": "F1KBNa_langSelect",
246
+ "quoteSplit": "F1KBNa_quoteSplit",
247
+ "discussionCompose": "F1KBNa_discussionCompose",
248
+ "colorPicker": "F1KBNa_colorPicker",
249
+ "confirmText": "F1KBNa_confirmText",
250
+ "rowMeta": "F1KBNa_rowMeta",
251
+ "settingsRowDesc": "F1KBNa_settingsRowDesc",
252
+ "presentationSelect": "F1KBNa_presentationSelect",
253
+ "readError": "F1KBNa_readError",
254
+ "commentHead": "F1KBNa_commentHead",
255
+ "commentLabel": "F1KBNa_commentLabel",
256
+ "diffBodyWrap": "F1KBNa_diffBodyWrap",
257
+ "overviewRulerSplit": "F1KBNa_overviewRulerSplit",
258
+ "coverNoticeGlyph": "F1KBNa_coverNoticeGlyph",
259
+ "colorPickerPreview": "F1KBNa_colorPickerPreview",
260
+ "discussionHead": "F1KBNa_discussionHead",
292
261
  "headerEntryCount": "F1KBNa_headerEntryCount",
293
- "states": "F1KBNa_states",
294
- "noteCentered": "F1KBNa_noteCentered",
295
- "gotoBox": "F1KBNa_gotoBox",
296
- "searchToggle": "F1KBNa_searchToggle",
262
+ "quoteCode": "F1KBNa_quoteCode",
263
+ "lines": "F1KBNa_lines",
264
+ "group": "F1KBNa_group",
265
+ "mdPreviewWrap": "F1KBNa_mdPreviewWrap",
266
+ "badgeCount": "F1KBNa_badgeCount",
267
+ "colorSvCursor": "F1KBNa_colorSvCursor",
268
+ "pickerNote": "F1KBNa_pickerNote",
269
+ "actionChord": "F1KBNa_actionChord",
270
+ "coverHost": "F1KBNa_coverHost",
271
+ "dockHost": "F1KBNa_dockHost",
272
+ "splitLadd": "F1KBNa_splitLadd",
273
+ "commentTitleEmpty": "F1KBNa_commentTitleEmpty",
274
+ "confirmBackdrop": "F1KBNa_confirmBackdrop",
275
+ "hint": "F1KBNa_hint",
276
+ "diffStats": "F1KBNa_diffStats",
277
+ "blockFlash": "F1KBNa_blockFlash",
278
+ "diffFlashFade": "F1KBNa_diffFlashFade",
279
+ "chipPresentation": "F1KBNa_chipPresentation",
280
+ "markerSplitAdd": "F1KBNa_markerSplitAdd",
281
+ "statusAction": "F1KBNa_statusAction",
282
+ "context": "F1KBNa_context",
283
+ "listScroll": "F1KBNa_listScroll",
284
+ "iconAction": "F1KBNa_iconAction",
285
+ "importNote": "F1KBNa_importNote",
297
286
  "discussionCell": "F1KBNa_discussionCell",
298
- "pickerClose": "F1KBNa_pickerClose",
299
- "missing": "F1KBNa_missing"
287
+ "coverPopover": "F1KBNa_coverPopover",
288
+ "splitDiscussion": "F1KBNa_splitDiscussion",
289
+ "confirmActions": "F1KBNa_confirmActions",
290
+ "markerSplitDel": "F1KBNa_markerSplitDel",
291
+ "detail": "F1KBNa_detail",
292
+ "fileListKnob": "F1KBNa_fileListKnob",
293
+ "kindHint": "F1KBNa_kindHint",
294
+ "commentRow": "F1KBNa_commentRow",
295
+ "mdPreviewFallback": "F1KBNa_mdPreviewFallback",
296
+ "coverNoticeCard": "F1KBNa_coverNoticeCard",
297
+ "diffPreviewTitle": "F1KBNa_diffPreviewTitle",
298
+ "diffBodySplit": "F1KBNa_diffBodySplit",
299
+ "actionPrimary": "F1KBNa_actionPrimary"
300
300
  };
301
301
  //#endregion
302
302
  //#region lib/types/client/PathPicker.js
@@ -29751,6 +29751,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
29751
29751
  /** The manifest path, resolved against the document's own origin. */
29752
29752
  const MANIFEST_URL = `${FONT_ROUTE}/manifest.json`;
29753
29753
  /**
29754
+ * The class the panel puts on the code table, read from the stylesheet module
29755
+ * that defines it.
29756
+ *
29757
+ * A literal `.lines` selector is a no-op: the build prefixes every class in that
29758
+ * module (`Ay7oXG_lines`), so a rule naming the source name matches no element
29759
+ * and the font silently never applies. The module's own export is the one value
29760
+ * that cannot drift from what the panel renders.
29761
+ */
29762
+ const CODE_TABLE_CLASS = PendingPanel_module_css_default.lines ?? "";
29763
+ /**
29754
29764
  * The `@font-face` rules for every slice of every weight, followed by the one
29755
29765
  * rule that uses them: the code column.
29756
29766
  *
@@ -29758,28 +29768,41 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
29758
29768
  * font immediately, and swapping when the slices land only changes the column
29759
29769
  * width, never the row height that the virtual window and the jump math are
29760
29770
  * built on.
29771
+ *
29772
+ * @param slices - the manifest's slice list.
29773
+ * @param codeClass - the class the code table carries, defaulting to the one the
29774
+ * panel's stylesheet exports. It is a parameter so a test can pin the emitted
29775
+ * selector without importing the panel.
29761
29776
  */
29762
- function codeFontCss(slices) {
29777
+ function codeFontCss(slices, codeClass = CODE_TABLE_CLASS) {
29763
29778
  const rules = [];
29764
29779
  for (const face of FONT_FACES) for (const slice of slices) {
29765
29780
  if (slice.weight !== face.weight) continue;
29766
29781
  if (slice.file.indexOf(`${face.name}-`) !== 0) continue;
29767
29782
  rules.push(`@font-face{font-family:"${FONT_FAMILY}";src:url("${FONT_ROUTE}/${slice.file}") format("woff2");font-weight:${face.weight};font-style:normal;font-display:swap;unicode-range:${slice.unicodeRange}}`);
29768
29783
  }
29769
- rules.push(`.lines{font-family:${FONT_STACK}}`);
29784
+ if (codeClass !== "") rules.push(`.${codeClass}{font-family:${FONT_STACK}}`);
29770
29785
  return rules.join("\n");
29771
29786
  }
29772
29787
  /** The manifest, read once per page: the slices it lists never change under us. */
29773
29788
  let manifestPromise;
29789
+ /** Whether the one "the switch is on but the host serves no slices" line was written. */
29790
+ let reportedMissing = false;
29774
29791
  /** Fetch (or reuse) the slice list. Undefined when the host serves no slices. */
29775
29792
  function fetchSlices() {
29776
29793
  manifestPromise ??= (async () => {
29777
29794
  try {
29778
29795
  const response = await fetch(MANIFEST_URL, { credentials: "same-origin" });
29779
- if (!response.ok) return void 0;
29796
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
29780
29797
  const slices = (await response.json()).slices ?? [];
29781
- return slices.length > 0 ? slices : void 0;
29782
- } catch {
29798
+ if (slices.length === 0) throw new Error("the manifest lists no slices");
29799
+ return slices;
29800
+ } catch (error) {
29801
+ manifestPromise = void 0;
29802
+ if (!reportedMissing) {
29803
+ reportedMissing = true;
29804
+ console.warn(`diff-approval: the bundled code font is unavailable (${MANIFEST_URL})`, error);
29805
+ }
29783
29806
  return;
29784
29807
  }
29785
29808
  })();
@@ -29815,9 +29838,10 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
29815
29838
  }
29816
29839
  /**
29817
29840
  * Follow the preference for as long as the client lives: apply it now, and again
29818
- * whenever the Settings switch flips. Silent on every failure — a host without
29819
- * the slices (a source checkout that never ran the font build) simply keeps the
29820
- * system stack, which is what the panel did before this existed.
29841
+ * whenever the Settings switch flips. A host without the slices (a source
29842
+ * checkout that never ran the font build, or an install that arrived without
29843
+ * `assets/`) keeps the system stack, and says so once on the console: the
29844
+ * switch is on, so silence would read as "the font does nothing".
29821
29845
  *
29822
29846
  * @returns a disposer that stops following and removes the injected rules.
29823
29847
  */
package/lib/index.js CHANGED
@@ -3271,9 +3271,9 @@ function apply(ctx, config) {
3271
3271
  return typeof service.register === "function" ? service.register(ctx, DIFF_APPROVAL_CHANNEL, handle, { authority: "trusted-host" }) : service.rpc.handle(DIFF_APPROVAL_CHANNEL, handle, { authority: "trusted-host" });
3272
3272
  }, "diff-approval: review channel");
3273
3273
  ctx.effect(() => {
3274
- const route = fontRoute();
3274
+ const route = fontRoute((message) => ctx.logger.warn(message));
3275
3275
  const server = ctx.get("webServer");
3276
- if (route === void 0 || typeof server?.register !== "function") {
3276
+ if (typeof server?.register !== "function") {
3277
3277
  ctx.logger.debug("diff-approval: no web server, so the bundled code font is not served");
3278
3278
  return () => {};
3279
3279
  }
@@ -3420,38 +3420,79 @@ function openTargetOf(payload) {
3420
3420
  }
3421
3421
  /** The font slices the host is willing to serve, read once from the manifest. */
3422
3422
  let fontSlicesPromise;
3423
- /** Read `assets/fonts/manifest.json` next to the built bundle, once. */
3424
- function fontSlices() {
3425
- fontSlicesPromise ??= (async () => {
3426
- try {
3427
- const dir = fileURLToPath(new URL(FONT_ASSET_DIR, import.meta.url));
3428
- const text = await readFile(join(dir, "manifest.json"), "utf8");
3429
- const manifest = JSON.parse(text);
3430
- const slices = /* @__PURE__ */ new Map();
3431
- for (const slice of manifest.slices ?? []) slices.set(slice.file, slice);
3432
- return slices;
3433
- } catch {
3434
- return;
3435
- }
3436
- })();
3423
+ /** Read `assets/fonts/manifest.json` next to the built bundle. */
3424
+ async function loadFontSlices() {
3425
+ try {
3426
+ const dir = fileURLToPath(new URL(FONT_ASSET_DIR, import.meta.url));
3427
+ const text = await readFile(join(dir, "manifest.json"), "utf8");
3428
+ const manifest = JSON.parse(text);
3429
+ const slices = /* @__PURE__ */ new Map();
3430
+ for (const slice of manifest.slices ?? []) slices.set(slice.file, slice);
3431
+ return slices;
3432
+ } catch {
3433
+ return;
3434
+ }
3435
+ }
3436
+ /**
3437
+ * The manifest, cached for the life of the host — but only once it has been
3438
+ * read. A missing `assets/fonts` is deliberately not cached: a deployment that
3439
+ * puts the assets beside a running bundle (a profile reinstall after the
3440
+ * package's file list grew) starts serving slices on the next request instead
3441
+ * of needing a restart, at the cost of one failed read per request until then.
3442
+ */
3443
+ async function fontSlices() {
3444
+ if (fontSlicesPromise === void 0) {
3445
+ const pending = loadFontSlices();
3446
+ fontSlicesPromise = pending;
3447
+ const slices = await pending;
3448
+ if (slices === void 0) fontSlicesPromise = void 0;
3449
+ return slices;
3450
+ }
3437
3451
  return fontSlicesPromise;
3438
3452
  }
3439
3453
  /**
3454
+ * Drop the cached slice list, so the next request reads the manifest again.
3455
+ *
3456
+ * The cache exists so a served page costs one read, which makes it state that
3457
+ * outlives a test: tests that need the "no manifest" path call this between
3458
+ * cases. Nothing in the app calls it.
3459
+ */
3460
+ function resetFontSlicesForTests() {
3461
+ fontSlicesPromise = void 0;
3462
+ }
3463
+ /**
3440
3464
  * Answer one font request. Exported so the route's behaviour is testable
3441
- * without a listening server: only files the manifest lists are ever read, and
3442
- * everything else — including a path traversal attempt — is a 404.
3465
+ * without a listening server: the manifest itself is answered from the parsed
3466
+ * list, only files that list names are ever read, and everything else —
3467
+ * including a path traversal attempt — is a 404.
3443
3468
  *
3444
3469
  * @param req - the request, for its path.
3445
3470
  * @param res - the response, whose lifecycle this owns.
3471
+ * @param nominate - how to report a missing manifest, called at most once per
3472
+ * route by {@link fontRoute}. Without the manifest every slice is a 404, and
3473
+ * that is a deployment problem the reader cannot see from the panel: the
3474
+ * switch is on, the font is simply absent, and nothing else says why.
3446
3475
  */
3447
- async function serveFontSlice(req, res) {
3476
+ async function serveFontSlice(req, res, nominate) {
3448
3477
  const slices = await fontSlices();
3449
3478
  if (slices === void 0) {
3479
+ nominate?.(`diff-approval: no code-font manifest at ${join(fileURLToPath(new URL(FONT_ASSET_DIR, import.meta.url)), "manifest.json")}, so the bundled font cannot be served (reinstall the plugin so its assets arrive, then restart the host)`);
3450
3480
  res.statusCode = 404;
3451
3481
  res.end("font unavailable");
3452
3482
  return;
3453
3483
  }
3454
3484
  const name = decodeURIComponent((req.url ?? "").split("?")[0] ?? "").split("/").pop() ?? "";
3485
+ if (name === "manifest.json") {
3486
+ res.statusCode = 200;
3487
+ res.setHeader("content-type", "application/json; charset=utf-8");
3488
+ res.setHeader("cache-control", "no-store");
3489
+ res.end(JSON.stringify({ slices: [...slices.values()].map(({ file, unicodeRange, weight }) => ({
3490
+ file,
3491
+ unicodeRange,
3492
+ weight
3493
+ })) }));
3494
+ return;
3495
+ }
3455
3496
  const slice = slices.get(name);
3456
3497
  if (slice === void 0 || !/^[a-z]+-[a-z0-9-]*\.woff2$/.test(name)) {
3457
3498
  res.statusCode = 404;
@@ -3473,15 +3514,24 @@ async function serveFontSlice(req, res) {
3473
3514
  }
3474
3515
  }
3475
3516
  /**
3476
- * The route serving the bundled font, or undefined when the slices were never
3477
- * generated (a source checkout without the build step).
3517
+ * The route serving the bundled font.
3518
+ *
3519
+ * @param warn - where the once-per-route "no manifest beside the bundle" line
3520
+ * goes. It is the only signal a reader's switch gives when the deployment,
3521
+ * not the switch, is what is missing.
3522
+ * @returns the prefix route.
3478
3523
  */
3479
- function fontRoute() {
3524
+ function fontRoute(warn) {
3525
+ let reported = false;
3480
3526
  return {
3481
3527
  kind: "prefix",
3482
3528
  path: FONT_ROUTE,
3483
- handler: serveFontSlice
3529
+ handler: (req, res) => serveFontSlice(req, res, (message) => {
3530
+ if (reported) return;
3531
+ reported = true;
3532
+ warn(message);
3533
+ })
3484
3534
  };
3485
3535
  }
3486
3536
  //#endregion
3487
- export { COMMENT_SKILL_NAME, DIFF_APPROVAL_CHANNEL, PendingDiffStore, PendingPersistence, apply, defaultOpenPath, defaultStorageDir, inject, name, serveFontSlice };
3537
+ export { COMMENT_SKILL_NAME, DIFF_APPROVAL_CHANNEL, PendingDiffStore, PendingPersistence, apply, defaultOpenPath, defaultStorageDir, fontRoute, inject, name, resetFontSlicesForTests, serveFontSlice };
@@ -42,8 +42,13 @@ interface ListedSlice {
42
42
  * font immediately, and swapping when the slices land only changes the column
43
43
  * width, never the row height that the virtual window and the jump math are
44
44
  * built on.
45
+ *
46
+ * @param slices - the manifest's slice list.
47
+ * @param codeClass - the class the code table carries, defaulting to the one the
48
+ * panel's stylesheet exports. It is a parameter so a test can pin the emitted
49
+ * selector without importing the panel.
45
50
  */
46
- export declare function codeFontCss(slices: readonly ListedSlice[]): string;
51
+ export declare function codeFontCss(slices: readonly ListedSlice[], codeClass?: string): string;
47
52
  /**
48
53
  * Drop the cached slice list and the injected rules.
49
54
  *
@@ -54,9 +59,10 @@ export declare function codeFontCss(slices: readonly ListedSlice[]): string;
54
59
  export declare function resetCodeFontForTests(): void;
55
60
  /**
56
61
  * Follow the preference for as long as the client lives: apply it now, and again
57
- * whenever the Settings switch flips. Silent on every failure — a host without
58
- * the slices (a source checkout that never ran the font build) simply keeps the
59
- * system stack, which is what the panel did before this existed.
62
+ * whenever the Settings switch flips. A host without the slices (a source
63
+ * checkout that never ran the font build, or an install that arrived without
64
+ * `assets/`) keeps the system stack, and says so once on the console: the
65
+ * switch is on, so silence would read as "the font does nothing".
60
66
  *
61
67
  * @returns a disposer that stops following and removes the injected rules.
62
68
  */
@@ -84,12 +84,38 @@ interface WebServerResponse {
84
84
  setHeader(name: string, value: string): unknown;
85
85
  end(body?: Uint8Array | string): unknown;
86
86
  }
87
+ /**
88
+ * Drop the cached slice list, so the next request reads the manifest again.
89
+ *
90
+ * The cache exists so a served page costs one read, which makes it state that
91
+ * outlives a test: tests that need the "no manifest" path call this between
92
+ * cases. Nothing in the app calls it.
93
+ */
94
+ export declare function resetFontSlicesForTests(): void;
87
95
  /**
88
96
  * Answer one font request. Exported so the route's behaviour is testable
89
- * without a listening server: only files the manifest lists are ever read, and
90
- * everything else — including a path traversal attempt — is a 404.
97
+ * without a listening server: the manifest itself is answered from the parsed
98
+ * list, only files that list names are ever read, and everything else —
99
+ * including a path traversal attempt — is a 404.
91
100
  *
92
101
  * @param req - the request, for its path.
93
102
  * @param res - the response, whose lifecycle this owns.
103
+ * @param nominate - how to report a missing manifest, called at most once per
104
+ * route by {@link fontRoute}. Without the manifest every slice is a 404, and
105
+ * that is a deployment problem the reader cannot see from the panel: the
106
+ * switch is on, the font is simply absent, and nothing else says why.
107
+ */
108
+ export declare function serveFontSlice(req: WebServerRequest, res: WebServerResponse, nominate?: (message: string) => void): Promise<void>;
109
+ /**
110
+ * The route serving the bundled font.
111
+ *
112
+ * @param warn - where the once-per-route "no manifest beside the bundle" line
113
+ * goes. It is the only signal a reader's switch gives when the deployment,
114
+ * not the switch, is what is missing.
115
+ * @returns the prefix route.
94
116
  */
95
- export declare function serveFontSlice(req: WebServerRequest, res: WebServerResponse): Promise<void>;
117
+ export declare function fontRoute(warn: (message: string) => void): {
118
+ kind: 'prefix';
119
+ path: string;
120
+ handler: (req: WebServerRequest, res: WebServerResponse) => Promise<void>;
121
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-diff-approval",
3
- "version": "0.29.0",
3
+ "version": "0.29.1",
4
4
  "description": "DeepSeek Harness plugin: pending-edit review with whole-file diff and Keep/Revert",
5
5
  "packageManager": "pnpm@11.21.0",
6
6
  "author": "Wu Zhiwei",