dsh-plugin-dev-kb 1.8.0 → 1.8.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.
Files changed (229) hide show
  1. package/CHANGELOG.md +186 -178
  2. package/README.en.md +172 -172
  3. package/README.md +183 -183
  4. package/kb/INDEX.md +236 -234
  5. package/kb/README.md +88 -88
  6. package/kb/extra/AGENTS.md +77 -77
  7. package/kb/extra/deepseek-llm-api-wire-extensions.md +162 -162
  8. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +162 -162
  9. package/kb/extra/defensive-patterns/package-surface.md +233 -232
  10. package/kb/extra/defensive-patterns/package-surface.zh.md +233 -232
  11. package/kb/extra/defensive-patterns/remote-and-api.md +117 -117
  12. package/kb/extra/defensive-patterns/remote-and-api.zh.md +117 -117
  13. package/kb/extra/development.md +221 -221
  14. package/kb/extra/development.zh.md +228 -228
  15. package/kb/extra/event-producer-consumer.md +133 -123
  16. package/kb/extra/event-producer-consumer.zh.md +135 -125
  17. package/kb/extra/module-graph.md +1961 -1888
  18. package/kb/extra/module-graph.zh.md +1963 -1890
  19. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.md +60 -0
  20. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.zh.md +60 -0
  21. package/kb/extra/persistence-changes/README.md +92 -92
  22. package/kb/extra/persistence-changes/README.zh.md +92 -92
  23. package/kb/extra/persistence-changes/historical-formats/README.md +75 -75
  24. package/kb/extra/persistence-changes/historical-formats/README.zh.md +75 -75
  25. package/kb/extra/persistence-changes/releases/README.md +103 -103
  26. package/kb/extra/persistence-changes/releases/README.zh.md +103 -103
  27. package/kb/extra/rescope.md +55 -55
  28. package/kb/extra/rescope.zh.md +55 -55
  29. package/kb/extra/subsystems/boot.md +631 -621
  30. package/kb/extra/subsystems/boot.zh.md +631 -621
  31. package/kb/extra/subsystems/computer-use.md +179 -137
  32. package/kb/extra/subsystems/computer-use.zh.md +179 -137
  33. package/kb/extra/subsystems/extensions.md +387 -384
  34. package/kb/extra/subsystems/extensions.zh.md +387 -384
  35. package/kb/extra/subsystems/feedback.md +418 -400
  36. package/kb/extra/subsystems/feedback.zh.md +418 -400
  37. package/kb/extra/subsystems/forge.md +2169 -1226
  38. package/kb/extra/subsystems/forge.zh.md +2171 -1226
  39. package/kb/extra/subsystems/liveshare.md +167 -158
  40. package/kb/extra/subsystems/liveshare.zh.md +167 -158
  41. package/kb/extra/subsystems/mcp.md +237 -234
  42. package/kb/extra/subsystems/mcp.zh.md +237 -234
  43. package/kb/extra/subsystems/office-kit.md +122 -0
  44. package/kb/extra/subsystems/office-kit.zh.md +122 -0
  45. package/kb/extra/subsystems/working-directory.md +95 -64
  46. package/kb/extra/subsystems/working-directory.zh.md +95 -64
  47. package/kb/extra/subsystems/worktrees.md +187 -127
  48. package/kb/extra/subsystems/worktrees.zh.md +187 -127
  49. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.md +21 -21
  50. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.zh.md +21 -21
  51. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.md +18 -0
  52. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.zh.md +18 -0
  53. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.md +18 -0
  54. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.zh.md +18 -0
  55. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.md +34 -0
  56. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.zh.md +34 -0
  57. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.md +49 -0
  58. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.zh.md +49 -0
  59. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.md +36 -0
  60. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.zh.md +36 -0
  61. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.md +26 -0
  62. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.zh.md +26 -0
  63. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.md +22 -0
  64. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.zh.md +22 -0
  65. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.md +21 -0
  66. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.zh.md +21 -0
  67. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.md +23 -0
  68. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.zh.md +23 -0
  69. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.md +20 -0
  70. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.zh.md +20 -0
  71. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.md +18 -0
  72. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.zh.md +18 -0
  73. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md +23 -0
  74. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md +23 -0
  75. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.md +35 -0
  76. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.zh.md +35 -0
  77. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.md +26 -0
  78. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.zh.md +26 -0
  79. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.md +26 -0
  80. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.zh.md +26 -0
  81. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.md +19 -0
  82. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.zh.md +19 -0
  83. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.md +26 -0
  84. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.zh.md +26 -0
  85. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.md +22 -0
  86. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.zh.md +22 -0
  87. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.md +25 -0
  88. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.zh.md +25 -0
  89. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.md +48 -0
  90. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.zh.md +48 -0
  91. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.md +45 -0
  92. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.zh.md +45 -0
  93. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.md +19 -0
  94. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.zh.md +19 -0
  95. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.md +17 -0
  96. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.zh.md +17 -0
  97. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.md +27 -0
  98. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.zh.md +27 -0
  99. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.md +20 -0
  100. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.zh.md +20 -0
  101. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.md +19 -0
  102. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.zh.md +19 -0
  103. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.md +18 -0
  104. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.zh.md +18 -0
  105. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.md +41 -0
  106. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.zh.md +41 -0
  107. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.md +21 -0
  108. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.zh.md +21 -0
  109. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.md +29 -0
  110. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.zh.md +29 -0
  111. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.md +25 -0
  112. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.zh.md +25 -0
  113. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.md +31 -0
  114. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.zh.md +31 -0
  115. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.md +24 -0
  116. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.zh.md +24 -0
  117. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.md +24 -0
  118. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.zh.md +24 -0
  119. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.md +19 -0
  120. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.zh.md +19 -0
  121. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.md +15 -0
  122. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.zh.md +15 -0
  123. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.md +28 -0
  124. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.zh.md +28 -0
  125. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.md +36 -0
  126. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.zh.md +36 -0
  127. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.md +22 -0
  128. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.zh.md +22 -0
  129. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.md +31 -0
  130. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.zh.md +31 -0
  131. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.md +18 -0
  132. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.zh.md +18 -0
  133. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.md +30 -0
  134. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.zh.md +30 -0
  135. package/kb/extra/web-styling.md +57 -57
  136. package/kb/extra/web-styling.zh.md +57 -57
  137. package/kb/meta/search-index.json +4508 -3980
  138. package/kb/meta/source.json +18 -18
  139. package/kb/site/develop/practice/llm-adapter.md +192 -192
  140. package/kb/site/en/develop/practice/llm-adapter.md +192 -192
  141. package/kb/site/en/guide/desktop-uninstall-cleanup.md +63 -0
  142. package/kb/site/en/guide/plugin-market.md +153 -151
  143. package/kb/site/en/guide/providers.md +234 -234
  144. package/kb/site/en/guide/quickstart.md +35 -34
  145. package/kb/site/en/reference/capability-seams.md +789 -767
  146. package/kb/site/en/reference/config-catalog.md +5432 -5128
  147. package/kb/site/en/reference/cookbook/adding-a-package.md +175 -175
  148. package/kb/site/en/reference/cookbook/adding-a-tool.md +105 -104
  149. package/kb/site/en/reference/cookbook/extension-cookbook.md +178 -135
  150. package/kb/site/en/reference/cordis-api/context.md +373 -369
  151. package/kb/site/en/reference/cordis-api/fiber.md +457 -433
  152. package/kb/site/en/reference/cordis-api/inherited.md +44 -44
  153. package/kb/site/en/reference/cordis-api/service.md +118 -107
  154. package/kb/site/en/reference/experimental-persistence-catalog.md +36 -23
  155. package/kb/site/en/reference/index.md +174 -174
  156. package/kb/site/en/reference/persistence-catalog.md +9453 -9432
  157. package/kb/site/en/reference/subsystems/compaction.md +288 -288
  158. package/kb/site/en/reference/subsystems/core.md +1172 -1171
  159. package/kb/site/en/reference/subsystems/credentials.md +526 -497
  160. package/kb/site/en/reference/subsystems/filesystem.md +708 -708
  161. package/kb/site/en/reference/subsystems/index.md +82 -82
  162. package/kb/site/en/reference/subsystems/llm-streaming.md +1290 -1288
  163. package/kb/site/en/reference/subsystems/lsp.md +230 -206
  164. package/kb/site/en/reference/subsystems/persistence.md +451 -432
  165. package/kb/site/en/reference/subsystems/plan.md +91 -91
  166. package/kb/site/en/reference/subsystems/ptc-runtime.md +295 -261
  167. package/kb/site/en/reference/subsystems/sandbox.md +250 -232
  168. package/kb/site/en/reference/subsystems/session-query.md +525 -515
  169. package/kb/site/en/reference/subsystems/session-reference.md +231 -229
  170. package/kb/site/en/reference/subsystems/session.md +1478 -1431
  171. package/kb/site/en/reference/subsystems/sidebar-right.md +165 -165
  172. package/kb/site/en/reference/subsystems/skills.md +356 -356
  173. package/kb/site/en/reference/subsystems/slots.md +235 -231
  174. package/kb/site/en/reference/subsystems/terminal.md +188 -188
  175. package/kb/site/en/reference/subsystems/tools.md +902 -891
  176. package/kb/site/en/reference/subsystems/user-questions.md +330 -327
  177. package/kb/site/en/reference/subsystems/web-client.md +161 -104
  178. package/kb/site/en/reference/subsystems/web-server.md +434 -351
  179. package/kb/site/en/reference/subsystems/web.md +268 -268
  180. package/kb/site/en/reference/subsystems/workflow.md +287 -282
  181. package/kb/site/en/reference/subsystems/workspace.md +743 -651
  182. package/kb/site/en/reference/tool-catalog.md +2867 -2704
  183. package/kb/site/guide/desktop-uninstall-cleanup.md +63 -0
  184. package/kb/site/guide/plugin-market.md +153 -151
  185. package/kb/site/guide/providers.md +234 -234
  186. package/kb/site/guide/quickstart.md +35 -34
  187. package/kb/site/reference/capability-seams.md +789 -767
  188. package/kb/site/reference/config-catalog.md +5432 -5128
  189. package/kb/site/reference/cookbook/adding-a-package.md +175 -175
  190. package/kb/site/reference/cookbook/adding-a-tool.md +107 -106
  191. package/kb/site/reference/cookbook/extension-cookbook.md +182 -139
  192. package/kb/site/reference/cordis-api/context.md +373 -369
  193. package/kb/site/reference/cordis-api/fiber.md +459 -435
  194. package/kb/site/reference/cordis-api/inherited.md +44 -44
  195. package/kb/site/reference/cordis-api/service.md +118 -107
  196. package/kb/site/reference/experimental-persistence-catalog.md +36 -23
  197. package/kb/site/reference/index.md +178 -178
  198. package/kb/site/reference/persistence-catalog.md +9453 -9432
  199. package/kb/site/reference/subsystems/compaction.md +288 -288
  200. package/kb/site/reference/subsystems/core.md +1184 -1183
  201. package/kb/site/reference/subsystems/credentials.md +526 -497
  202. package/kb/site/reference/subsystems/filesystem.md +708 -708
  203. package/kb/site/reference/subsystems/index.md +82 -82
  204. package/kb/site/reference/subsystems/llm-streaming.md +1296 -1294
  205. package/kb/site/reference/subsystems/lsp.md +230 -206
  206. package/kb/site/reference/subsystems/persistence.md +451 -432
  207. package/kb/site/reference/subsystems/plan.md +91 -91
  208. package/kb/site/reference/subsystems/ptc-runtime.md +295 -261
  209. package/kb/site/reference/subsystems/sandbox.md +250 -232
  210. package/kb/site/reference/subsystems/session-query.md +525 -515
  211. package/kb/site/reference/subsystems/session-reference.md +231 -229
  212. package/kb/site/reference/subsystems/session.md +1482 -1435
  213. package/kb/site/reference/subsystems/sidebar-right.md +165 -165
  214. package/kb/site/reference/subsystems/skills.md +356 -356
  215. package/kb/site/reference/subsystems/slots.md +239 -235
  216. package/kb/site/reference/subsystems/terminal.md +188 -188
  217. package/kb/site/reference/subsystems/tools.md +902 -891
  218. package/kb/site/reference/subsystems/user-questions.md +330 -327
  219. package/kb/site/reference/subsystems/web-client.md +161 -104
  220. package/kb/site/reference/subsystems/web-server.md +434 -351
  221. package/kb/site/reference/subsystems/web.md +268 -268
  222. package/kb/site/reference/subsystems/workflow.md +287 -282
  223. package/kb/site/reference/subsystems/workspace.md +743 -651
  224. package/kb/site/reference/tool-catalog.md +2872 -2709
  225. package/lib/index.js +359 -359
  226. package/package.json +68 -68
  227. package/skills/dsh-plugin-dev-kb.md +71 -70
  228. package/kb/extra/subsystems/office-to-pdf.md +0 -87
  229. package/kb/extra/subsystems/office-to-pdf.zh.md +0 -87
@@ -1,400 +1,418 @@
1
- # Message Feedback
2
-
3
- English | [中文](feedback.zh.md)
4
-
5
- [`@deepseek-ai/dsh-message-feedback`](../../packages/feedback/message-feedback) owns editable feedback for individual assistant messages. The canonical Session log stores `feedback/message-put` and `feedback/message-delete`; the immutable Session-level remark remains `feedback/record`, owned by [`@deepseek-ai/dsh-command-feedback`](../../packages/feedback/command-feedback) together with the `FeedbackCategory` taxonomy both kinds of feedback file under. All three are log-only events that never enter model context.
6
-
7
- Source: [`packages/feedback/message-feedback/src/types.ts`](../../packages/feedback/message-feedback/src/types.ts)
8
-
9
- ## Public types
10
-
11
- ```ts type-equiv
12
- /** Opaque compare-and-set token for one exact feedback item revision. */
13
- type MessageFeedbackVersion = Branded<'MessageFeedbackVersion'>
14
- ```
15
-
16
- ```ts type-equiv
17
- /** The human's overall judgment of one assistant message. */
18
- type MessageFeedbackRating = 'positive' | 'negative'
19
- ```
20
-
21
- ```ts type-equiv
22
- /** One current feedback value and its opaque mutation token. */
23
- interface MessageFeedbackItem {
24
- /** Stable identity of the assistant message inside the owning Session. */
25
- readonly messageId: MessageId
26
- /** Overall positive or negative judgment. */
27
- readonly rating: MessageFeedbackRating
28
- /** Optional explanation, preserved verbatim after validation. */
29
- readonly note?: string
30
- /** Category the human filed the judgment under. */
31
- readonly category?: FeedbackCategory
32
- /** Equality-only token replaced by every material create or update. */
33
- readonly version: MessageFeedbackVersion
34
- /** Host-assigned creation time in Unix epoch milliseconds. */
35
- readonly createdAt: number
36
- /** Host-assigned time of the most recent material update. */
37
- readonly updatedAt: number
38
- }
39
- ```
40
-
41
- ```ts type-equiv
42
- /** A material creation or edit, retaining its complete current value. */
43
- interface MessageFeedbackPut {
44
- /** Owning Session; inherited feedback in a fork belongs to its parent. */
45
- readonly sessionId: SessionId
46
- /** Value after this mutation, including the original creation time. */
47
- readonly item: MessageFeedbackItem
48
- }
49
- ```
50
-
51
- ```ts type-equiv
52
- /** A material deletion of one current feedback item. */
53
- interface MessageFeedbackDelete {
54
- /** Session that owns the deleted feedback. */
55
- readonly sessionId: SessionId
56
- /** Message whose feedback was removed. */
57
- readonly messageId: MessageId
58
- }
59
- ```
60
-
61
- ```ts type-equiv
62
- /** Read all message feedback belonging to one persisted Session lifecycle. */
63
- interface MessageFeedbackListRequest {
64
- /** Session whose feedback events should be read. */
65
- readonly sessionId: SessionId
66
- }
67
- ```
68
-
69
- ```ts type-equiv
70
- /** Current feedback values for one Session, in first-creation order. */
71
- interface MessageFeedbackListValue {
72
- /** Fresh immutable item snapshots. */
73
- readonly items: readonly MessageFeedbackItem[]
74
- }
75
- ```
76
-
77
- ```ts type-equiv
78
- /** Create or replace feedback for one assistant message. */
79
- interface MessageFeedbackPutRequest {
80
- /** Persisted Session that owns the target message. */
81
- readonly sessionId: SessionId
82
- /** Target assistant-message identity. */
83
- readonly messageId: MessageId
84
- /** Desired overall judgment. */
85
- readonly rating: MessageFeedbackRating
86
- /** Optional non-blank explanation. */
87
- readonly note?: string
88
- /** Optional category; absent keeps the item uncategorized. */
89
- readonly category?: FeedbackCategory
90
- /** Observed item version, or `null` to require that no item exists. */
91
- readonly ifVersion: MessageFeedbackVersion | null
92
- }
93
- ```
94
-
95
- ```ts type-equiv
96
- /** Delete feedback for one message after observing its current version. */
97
- interface MessageFeedbackDeleteRequest {
98
- /** Session that owns the feedback. */
99
- readonly sessionId: SessionId
100
- /** Message whose feedback should be absent after this operation. */
101
- readonly messageId: MessageId
102
- /** Observed item version; ignored when the item is already absent. */
103
- readonly ifVersion: MessageFeedbackVersion
104
- }
105
- ```
106
-
107
- ```ts type-equiv
108
- /** Idempotent deletion acknowledgement. */
109
- interface MessageFeedbackDeleteValue {
110
- /** Stable postcondition shared by the first deletion and every retry. */
111
- readonly absent: true
112
- }
113
- ```
114
-
115
- ```ts type-equiv
116
- /** No persisted Session header exists for the requested id. */
117
- interface MessageFeedbackSessionNotFound {
118
- readonly code: 'session-not-found'
119
- readonly sessionId: SessionId
120
- }
121
- ```
122
-
123
- ```ts type-equiv
124
- /** The id does not name a derived, append-origin assistant message. */
125
- interface MessageFeedbackTargetNotFound {
126
- readonly code: 'target-not-found'
127
- readonly sessionId: SessionId
128
- readonly messageId: MessageId
129
- }
130
- ```
131
-
132
- ```ts type-equiv
133
- /** A material mutation did not match the addressed item's current version. */
134
- interface MessageFeedbackVersionConflict {
135
- readonly code: 'version-conflict'
136
- /** Authoritative current item, or `null` when it does not exist. */
137
- readonly current: MessageFeedbackItem | null
138
- }
139
- ```
140
-
141
- ```ts type-equiv
142
- /** A supplied note contains no non-whitespace character. */
143
- interface MessageFeedbackNoteBlank {
144
- readonly code: 'note-blank'
145
- }
146
- ```
147
-
148
- ```ts type-equiv
149
- /** A supplied note exceeds the configured UTF-8 byte limit. */
150
- interface MessageFeedbackNoteTooLarge {
151
- readonly code: 'note-too-large'
152
- readonly maxBytes: number
153
- readonly actualBytes: number
154
- }
155
- ```
156
-
157
- ```ts type-equiv
158
- /** Failures shared by the public message-feedback operations. */
159
- type MessageFeedbackFailure =
160
- | MessageFeedbackSessionNotFound
161
- | MessageFeedbackTargetNotFound
162
- | MessageFeedbackVersionConflict
163
- | MessageFeedbackNoteBlank
164
- | MessageFeedbackNoteTooLarge
165
- ```
166
-
167
- ```ts type-equiv
168
- /** Successful public operation result. */
169
- interface MessageFeedbackSuccess<T> {
170
- readonly ok: true
171
- readonly value: T
172
- }
173
- ```
174
-
175
- ```ts type-equiv
176
- /** Rejected public operation result with a stable business failure. */
177
- interface MessageFeedbackRejected<E extends MessageFeedbackFailure> {
178
- readonly ok: false
179
- readonly error: E
180
- }
181
- ```
182
-
183
- ```ts type-equiv
184
- /** Result returned by the message-feedback `list` operation. */
185
- type MessageFeedbackListResult =
186
- | MessageFeedbackSuccess<MessageFeedbackListValue>
187
- | MessageFeedbackRejected<MessageFeedbackSessionNotFound>
188
- ```
189
-
190
- ```ts type-equiv
191
- /** Result returned by the message-feedback `put` operation. */
192
- type MessageFeedbackPutResult =
193
- | MessageFeedbackSuccess<MessageFeedbackItem>
194
- | MessageFeedbackRejected<
195
- | MessageFeedbackSessionNotFound
196
- | MessageFeedbackTargetNotFound
197
- | MessageFeedbackVersionConflict
198
- | MessageFeedbackNoteBlank
199
- | MessageFeedbackNoteTooLarge
200
- >
201
- ```
202
-
203
- ```ts type-equiv
204
- /** Result returned by the message-feedback `delete` operation. */
205
- type MessageFeedbackDeleteResult =
206
- | MessageFeedbackSuccess<MessageFeedbackDeleteValue>
207
- | MessageFeedbackRejected<MessageFeedbackSessionNotFound | MessageFeedbackVersionConflict>
208
- ```
209
-
210
- ## Session feedback types
211
-
212
- Source: [`packages/feedback/command-feedback/src/types.ts`](../../packages/feedback/command-feedback/src/types.ts)
213
-
214
- ```ts type-equiv
215
- /** One of the fixed feedback categories; the ids are durable log vocabulary. */
216
- type FeedbackCategory =
217
- | 'task-result'
218
- | 'instruction-following'
219
- | 'product-interaction'
220
- | 'service-stability'
221
- | 'resource-cost'
222
- | 'security-privacy-permission'
223
- | 'other'
224
- ```
225
-
226
- ```ts type-equiv
227
- /**
228
- * One recorded human remark about a Session. Both members are optional: a
229
- * submission with neither still records that the human asked for the
230
- * Session to be reviewed, which is what authorizes log delivery.
231
- */
232
- interface FeedbackRecord {
233
- /** Free-text remark with surrounding whitespace removed; never empty when present. */
234
- readonly text?: string
235
- /** Category the human filed the remark under. */
236
- readonly category?: FeedbackCategory
237
- }
238
- ```
239
-
240
- ```ts type-equiv
241
- /** Record one Session-level remark through the Host Remote. */
242
- interface SessionFeedbackRecordRequest {
243
- /** Live Session the remark describes. */
244
- readonly sessionId: SessionId
245
- /** Free-text remark; blank text is recorded as absent. */
246
- readonly text?: string
247
- /** Category the human filed the remark under. */
248
- readonly category?: FeedbackCategory
249
- }
250
- ```
251
-
252
- ```ts type-equiv
253
- /** Stable postcondition of a recorded remark. */
254
- interface SessionFeedbackRecordValue {
255
- /** The remark is appended to the Session log; flushing follows the Session's own schedule. */
256
- readonly recorded: true
257
- }
258
- ```
259
-
260
- ```ts type-equiv
261
- /** No live Session carries the requested id. */
262
- interface SessionFeedbackSessionNotFound {
263
- readonly code: 'session-not-found'
264
- readonly sessionId: SessionId
265
- }
266
- ```
267
-
268
- ```ts type-equiv
269
- /** Result returned by the `sessionFeedback.record` operation. */
270
- type SessionFeedbackRecordResult =
271
- | { readonly ok: true; readonly value: SessionFeedbackRecordValue }
272
- | { readonly ok: false; readonly error: SessionFeedbackSessionNotFound }
273
- ```
274
-
275
- ## Data and concurrency
276
-
277
- Current items are folded from canonical feedback events whose payload `sessionId` matches the owning Session. Each item carries a positive or negative rating, an optional note, an optional category, Host-assigned `createdAt`/`updatedAt` timestamps, and its own opaque version. Versions are compared only for equality and only against the addressed message; callers do not order or synthesize them.
278
-
279
- `put` uses strict optimistic concurrency: every request for an existing item must match its current `ifVersion`, including a no-op (a put repeating the stored rating, note, and category). A conflict returns the authoritative current item (or `null`), so a caller can reconcile a lost response or a concurrent edit without another read. Deleting an already absent item succeeds. A per-Session queue serializes reads and mutations; cold mutations hold a persistence write handle across read, comparison, append, and flush. Matching no-ops append no event.
280
-
281
- ## Target and lifecycle authority
282
-
283
- A live owner's in-memory log supplies the target Session observation directly; cold reads use a `SessionPersistence.open(id, 'read')` handle, while mutations use a write handle. Neither path constructs a Session or Agent. A `stat(id)` preflight classifies definite absence; a read failure for a Session `stat` confirmed propagates as infrastructure failure. `put` accepts only a non-empty, append-origin `assistant/message` with the requested `MessageId`; replacement-origin, usage-only empty, and non-assistant records are not feedback targets.
284
-
285
- Fork seeds can contain parent feedback events, but their payload retains the parent `sessionId`, so they do not become current feedback for the child. Deleting an item appends a tombstone; earlier ratings and notes remain in the log.
286
-
287
- ## Persistence and Remote contract
288
-
289
- Successful message-feedback mutations await canonical persistence: live operations append through the owning Session and require a participating `ctx.sessions.flush` listener; cold operations append and flush through their write handle. Persistence failures propagate rather than reporting success. `maxNoteBytes` is required and bounds note text by UTF-8 bytes; the Web Host composition sets `8192`. The package publishes the Host `messageFeedback.list`, `messageFeedback.put`, and `messageFeedback.delete` unary Remote contract through `TypertRemoteService` and `@Remote`; `command-feedback` publishes `sessionFeedback.record` the same way for Session-level remarks on live Sessions. The generated Cordis API below is the method-level authority.
290
-
291
- Plugin disposal closes operation admission and drains accepted per-Session queue work.
292
-
293
- By default, [`session-log-deepseek`](../../packages/session/session-log-deepseek/README.md) carries feedback as part of the ordinary `dsh_session_log` suffix on subsequent eligible DeepSeek requests; a composition disables it with `enabled: false`. Recording feedback does not trigger an LLM request or a separate `dsh_feedback` upload. For non-DeepSeek routes, the [OTel backend](../../packages/session/session-telemetry-otel/README.md) can release the canonical prefix through recorded feedback. The command acknowledgement confirms recording and identifies the Session and anonymous user; it reports neither telemetry policy nor delivery.
294
-
295
- ## Web surface
296
-
297
- [`@deepseek-ai/dsh-client-ui-message-feedback`](../../packages/client/ui-message-feedback) is the browser consumer. `@deepseek-ai/dsh-api-remotes` mounts the generated `messageFeedback` and `sessionFeedback` contributions, so the plugin calls `ctx.remote.messageFeedback` and `ctx.remote.sessionFeedback` and never touches the transport.
298
-
299
- The controls are the `feedback` entry (order 10) of the `conversation.chat.assistant-actions` list slot, which `ui-conversation` declares and renders inside the finalized assistant message's IconActions row. `AssistantMessageNode` carries the optional `messageId` from the `assistant/message` event. The field is absent on interruption-frozen partials, and the render site skips the slot when it is absent. The strip renders once per turn, on the closing assistant message: the Host accepts every append-origin step message as a target, but earlier steps of a multi-step turn render tool rows rather than a rateable body, so the UI exposes a narrower set than the Host contract allows.
300
-
301
- One `MessageFeedbackController` per Session backs every message control in that Session: a single `list` read seeds the whole transcript, deferred to first hover or focus rather than fired on mount. Each mutation sends the version that controller last observed as `ifVersion`; a `version-conflict` reply carries the authoritative item, so the controller reconciles from the reply instead of refetching. Mutations serialize per Session so a queued operation compares against the committed version. The injected `retract` operation rechecks the committed rating inside that queue and becomes a no-op after a concurrent change, so stale UI cannot bypass the dialog by recording a bare rating. A `connection/reset` refreshes only Sessions already read.
302
-
303
- Either unrecorded rating opens the Session's feedback dialog, the `feedback-dialog` entry of `conversation.input.overlay`: the shared Modal card with seven category chips and a detail box. Submit puts the selected judgment carrying the chosen category and the trimmed description, or neither; success closes the dialog and shows the acknowledgement toast, while failure keeps the dialog and draft open and shows a warning toast. The same dialog opens for the Session from a bare `/feedback` — a decoration `ui-commands` routes as an `action` — and then records through `sessionFeedback.record`; `/feedback <text>` keeps the Host command path. Clicking a recorded rating retracts it without opening the dialog.
304
-
305
- ## Boundaries and limitations
306
-
307
- - The operation queue is process-local; cold writer exclusion relies on the selected persistence provider.
308
- - Deletion removes the current item, not earlier note text from the append-only log or an already delivered suffix.
309
- - A request in the narrow interval after live detach but before the persistence catalog materializes the header can receive `session-not-found`; callers retry after retirement materialization.
310
- - Cold requests read the complete log; the service has no item-count or aggregate-byte cap. `maxNoteBytes` bounds only each note.
311
- - The Host contract records no authenticated actor or audit identity and therefore assumes a trusted caller boundary.
312
- - The Web controls appear in the chat view only. The trajectory and waterfall views render no feedback entry even though their assistant nodes carry the same `messageId`.
313
- - The Web controller does not consume feedback log events, so a second tab's rating becomes visible on reconnect or on the next conflict reply rather than immediately.
314
- - The dialog does not pre-check `maxNoteBytes`; an oversized description for a message fails on submit with `note-too-large` rather than while typing. A Session remark has no size bound, as the `/feedback` command never had one.
315
- - `sessionFeedback.record` serves live Sessions only and answers `session-not-found` otherwise; the dialog reports that failure when its Session retires while it is open.
316
-
317
- <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
318
-
319
- <a id="cordis-surface"></a>
320
-
321
- ## Cordis API
322
-
323
- Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
324
-
325
- <a id="ctxmessagefeedback--messagefeedbackservice"></a>
326
-
327
- ### `ctx.messageFeedback` — `MessageFeedbackService`
328
-
329
- Session-log service; cold operations never construct a Session or Agent.
330
-
331
- ```ts cordis-catalog
332
- /**
333
- * Read current feedback from the canonical log.
334
- * @param request - Session to inspect.
335
- * @returns immutable items or a definite persistence miss.
336
- */
337
- @Remote('list') list(request: MessageFeedbackListRequest): Promise<MessageFeedbackListResult>
338
-
339
- /**
340
- * Create or replace feedback after checking its current version.
341
- * Matching no-ops retain the version and append no event.
342
- * @param request - Target, desired value, and observed item version.
343
- * @returns the durable item or an explicit business failure.
344
- */
345
- @Remote('put') put(request: MessageFeedbackPutRequest): Promise<MessageFeedbackPutResult>
346
-
347
- /**
348
- * Delete one item after checking its version; absence succeeds without an event.
349
- * @param request - Session, message, and observed item version.
350
- * @returns the stable absent postcondition or an explicit failure.
351
- */
352
- @Remote('delete') delete(request: MessageFeedbackDeleteRequest): Promise<MessageFeedbackDeleteResult>
353
- ```
354
-
355
- Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
356
-
357
- <a id="ctxsessionfeedback--sessionfeedbackservice"></a>
358
-
359
- ### `ctx.sessionFeedback` — `SessionFeedbackService`
360
-
361
- Host Remote through which a product surface records a Session-level remark.
362
-
363
- ```ts cordis-catalog
364
- /**
365
- * Record one remark on a live Session.
366
- * @param request - target Session plus the optional text and category.
367
- * @returns the recorded postcondition, or `session-not-found` when no live
368
- * Session carries the id.
369
- */
370
- @Remote('record') record(request: SessionFeedbackRecordRequest): Promise<SessionFeedbackRecordResult>
371
- ```
372
-
373
- Source: [`packages/feedback/command-feedback/src/index.ts`](../../packages/feedback/command-feedback/src/index.ts)
374
-
375
- <a id="feedback-events"></a>
376
-
377
- ### `feedback/*` events
378
-
379
- <a id="feedbackcommitted--parallel"></a>
380
-
381
- #### `feedback/committed` — parallel
382
-
383
- Observe a durable cold feedback mutation without publishing a live Session. Observers run before write ownership is released and must not await another message-feedback operation for this Session. The payload is borrowed read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
384
-
385
- ```ts cordis-catalog
386
- /**
387
- * Observe a durable cold feedback mutation without publishing a live Session.
388
- * Observers run before write ownership is released and must not await
389
- * another message-feedback operation for this Session. The payload is borrowed
390
- * read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
391
- * @param inspection - committed canonical prefix, including the feedback as its last event.
392
- * @mode parallel
393
- */
394
- 'feedback/committed'(inspection: SessionInspection): void
395
- ```
396
-
397
- Types: [SessionInspection](persistence.md)
398
-
399
- Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
400
- <!-- END GENERATED cordis-surface -->
1
+ # Message Feedback
2
+
3
+ English | [中文](feedback.zh.md)
4
+
5
+ [`@deepseek-ai/dsh-message-feedback`](../../packages/feedback/message-feedback) owns editable feedback for individual assistant messages. The canonical Session log stores `feedback/message-put` and `feedback/message-delete`; the immutable Session-level remark remains `feedback/record`, owned by [`@deepseek-ai/dsh-command-feedback`](../../packages/feedback/command-feedback) together with the `FeedbackCategory` taxonomy both kinds of feedback file under. All three are log-only events that never enter model context.
6
+
7
+ Source: [`packages/feedback/message-feedback/src/types.ts`](../../packages/feedback/message-feedback/src/types.ts)
8
+
9
+ ## Public types
10
+
11
+ ```ts type-equiv
12
+ /** Opaque compare-and-set token for one exact feedback item revision. */
13
+ type MessageFeedbackVersion = Branded<'MessageFeedbackVersion'>
14
+ ```
15
+
16
+ ```ts type-equiv
17
+ /** The human's overall judgment of one assistant message. */
18
+ type MessageFeedbackRating = 'positive' | 'negative'
19
+ ```
20
+
21
+ ```ts type-equiv
22
+ /** One current feedback value and its opaque mutation token. */
23
+ interface MessageFeedbackItem {
24
+ /** Stable identity of the assistant message inside the owning Session. */
25
+ readonly messageId: MessageId
26
+ /** Overall positive or negative judgment. */
27
+ readonly rating: MessageFeedbackRating
28
+ /** Optional explanation, preserved verbatim after validation. */
29
+ readonly note?: string
30
+ /** Category the human filed the judgment under. */
31
+ readonly category?: FeedbackCategory
32
+ /** Equality-only token replaced by every material create or update. */
33
+ readonly version: MessageFeedbackVersion
34
+ /** Host-assigned creation time in Unix epoch milliseconds. */
35
+ readonly createdAt: number
36
+ /** Host-assigned time of the most recent material update. */
37
+ readonly updatedAt: number
38
+ }
39
+ ```
40
+
41
+ ```ts type-equiv
42
+ /** A material creation or edit, retaining its complete current value. */
43
+ interface MessageFeedbackPut {
44
+ /** Owning Session; inherited feedback in a fork belongs to its parent. */
45
+ readonly sessionId: SessionId
46
+ /** Value after this mutation, including the original creation time. */
47
+ readonly item: MessageFeedbackItem
48
+ }
49
+ ```
50
+
51
+ ```ts type-equiv
52
+ /** A material deletion of one current feedback item. */
53
+ interface MessageFeedbackDelete {
54
+ /** Session that owns the deleted feedback. */
55
+ readonly sessionId: SessionId
56
+ /** Message whose feedback was removed. */
57
+ readonly messageId: MessageId
58
+ }
59
+ ```
60
+
61
+ ```ts type-equiv
62
+ /** Read all message feedback belonging to one persisted Session lifecycle. */
63
+ interface MessageFeedbackListRequest {
64
+ /** Session whose feedback events should be read. */
65
+ readonly sessionId: SessionId
66
+ }
67
+ ```
68
+
69
+ ```ts type-equiv
70
+ /** Current feedback values for one Session, in first-creation order. */
71
+ interface MessageFeedbackListValue {
72
+ /** Fresh immutable item snapshots. */
73
+ readonly items: readonly MessageFeedbackItem[]
74
+ }
75
+ ```
76
+
77
+ ```ts type-equiv
78
+ /** Create or replace feedback for one assistant message. */
79
+ interface MessageFeedbackPutRequest {
80
+ /** Persisted Session that owns the target message. */
81
+ readonly sessionId: SessionId
82
+ /** Target assistant-message identity. */
83
+ readonly messageId: MessageId
84
+ /** Desired overall judgment. */
85
+ readonly rating: MessageFeedbackRating
86
+ /** Optional non-blank explanation. */
87
+ readonly note?: string
88
+ /** Optional category; absent keeps the item uncategorized. */
89
+ readonly category?: FeedbackCategory
90
+ /** Observed item version, or `null` to require that no item exists. */
91
+ readonly ifVersion: MessageFeedbackVersion | null
92
+ }
93
+ ```
94
+
95
+ ```ts type-equiv
96
+ /** Delete feedback for one message after observing its current version. */
97
+ interface MessageFeedbackDeleteRequest {
98
+ /** Session that owns the feedback. */
99
+ readonly sessionId: SessionId
100
+ /** Message whose feedback should be absent after this operation. */
101
+ readonly messageId: MessageId
102
+ /** Observed item version; ignored when the item is already absent. */
103
+ readonly ifVersion: MessageFeedbackVersion
104
+ }
105
+ ```
106
+
107
+ ```ts type-equiv
108
+ /** Idempotent deletion acknowledgement. */
109
+ interface MessageFeedbackDeleteValue {
110
+ /** Stable postcondition shared by the first deletion and every retry. */
111
+ readonly absent: true
112
+ }
113
+ ```
114
+
115
+ ```ts type-equiv
116
+ /** No persisted Session header exists for the requested id. */
117
+ interface MessageFeedbackSessionNotFound {
118
+ readonly code: 'session-not-found'
119
+ readonly sessionId: SessionId
120
+ }
121
+ ```
122
+
123
+ ```ts type-equiv
124
+ /** The id does not name a derived, append-origin assistant message. */
125
+ interface MessageFeedbackTargetNotFound {
126
+ readonly code: 'target-not-found'
127
+ readonly sessionId: SessionId
128
+ readonly messageId: MessageId
129
+ }
130
+ ```
131
+
132
+ ```ts type-equiv
133
+ /** A material mutation did not match the addressed item's current version. */
134
+ interface MessageFeedbackVersionConflict {
135
+ readonly code: 'version-conflict'
136
+ /** Authoritative current item, or `null` when it does not exist. */
137
+ readonly current: MessageFeedbackItem | null
138
+ }
139
+ ```
140
+
141
+ ```ts type-equiv
142
+ /** A supplied note contains no non-whitespace character. */
143
+ interface MessageFeedbackNoteBlank {
144
+ readonly code: 'note-blank'
145
+ }
146
+ ```
147
+
148
+ ```ts type-equiv
149
+ /** A supplied note exceeds the configured UTF-8 byte limit. */
150
+ interface MessageFeedbackNoteTooLarge {
151
+ readonly code: 'note-too-large'
152
+ readonly maxBytes: number
153
+ readonly actualBytes: number
154
+ }
155
+ ```
156
+
157
+ ```ts type-equiv
158
+ /** Failures shared by the public message-feedback operations. */
159
+ type MessageFeedbackFailure =
160
+ | MessageFeedbackSessionNotFound
161
+ | MessageFeedbackTargetNotFound
162
+ | MessageFeedbackVersionConflict
163
+ | MessageFeedbackNoteBlank
164
+ | MessageFeedbackNoteTooLarge
165
+ ```
166
+
167
+ ```ts type-equiv
168
+ /** Successful public operation result. */
169
+ interface MessageFeedbackSuccess<T> {
170
+ readonly ok: true
171
+ readonly value: T
172
+ }
173
+ ```
174
+
175
+ ```ts type-equiv
176
+ /** Rejected public operation result with a stable business failure. */
177
+ interface MessageFeedbackRejected<E extends MessageFeedbackFailure> {
178
+ readonly ok: false
179
+ readonly error: E
180
+ }
181
+ ```
182
+
183
+ ```ts type-equiv
184
+ /** Result returned by the message-feedback `list` operation. */
185
+ type MessageFeedbackListResult =
186
+ | MessageFeedbackSuccess<MessageFeedbackListValue>
187
+ | MessageFeedbackRejected<MessageFeedbackSessionNotFound>
188
+ ```
189
+
190
+ ```ts type-equiv
191
+ /** Result returned by the message-feedback `put` operation. */
192
+ type MessageFeedbackPutResult =
193
+ | MessageFeedbackSuccess<MessageFeedbackItem>
194
+ | MessageFeedbackRejected<
195
+ | MessageFeedbackSessionNotFound
196
+ | MessageFeedbackTargetNotFound
197
+ | MessageFeedbackVersionConflict
198
+ | MessageFeedbackNoteBlank
199
+ | MessageFeedbackNoteTooLarge
200
+ >
201
+ ```
202
+
203
+ ```ts type-equiv
204
+ /** Result returned by the message-feedback `delete` operation. */
205
+ type MessageFeedbackDeleteResult =
206
+ | MessageFeedbackSuccess<MessageFeedbackDeleteValue>
207
+ | MessageFeedbackRejected<MessageFeedbackSessionNotFound | MessageFeedbackVersionConflict>
208
+ ```
209
+
210
+ ## Session feedback types
211
+
212
+ Source: [`packages/feedback/command-feedback/src/types.ts`](../../packages/feedback/command-feedback/src/types.ts)
213
+
214
+ ```ts type-equiv
215
+ /** One of the fixed feedback categories; the ids are durable log vocabulary. */
216
+ type FeedbackCategory =
217
+ | 'task-result'
218
+ | 'instruction-following'
219
+ | 'product-interaction'
220
+ | 'service-stability'
221
+ | 'resource-cost'
222
+ | 'security-privacy-permission'
223
+ | 'other'
224
+ ```
225
+
226
+ ```ts type-equiv
227
+ /**
228
+ * One recorded human remark about a Session. Both members are optional: a
229
+ * submission with neither still records that the human asked for the
230
+ * Session to be reviewed, which is what authorizes log delivery.
231
+ */
232
+ interface FeedbackRecord {
233
+ /** Free-text remark with surrounding whitespace removed; never empty when present. */
234
+ readonly text?: string
235
+ /** Category the human filed the remark under. */
236
+ readonly category?: FeedbackCategory
237
+ }
238
+ ```
239
+
240
+ ```ts type-equiv
241
+ /** Record one Session-level remark through the Host Remote. */
242
+ interface SessionFeedbackRecordRequest {
243
+ /** Live Session the remark describes. */
244
+ readonly sessionId: SessionId
245
+ /** Free-text remark; blank text is recorded as absent. */
246
+ readonly text?: string
247
+ /** Category the human filed the remark under. */
248
+ readonly category?: FeedbackCategory
249
+ }
250
+ ```
251
+
252
+ ```ts type-equiv
253
+ /** Stable postcondition of a recorded remark. */
254
+ interface SessionFeedbackRecordValue {
255
+ /** The remark is appended to the Session log; flushing follows the Session's own schedule. */
256
+ readonly recorded: true
257
+ }
258
+ ```
259
+
260
+ ```ts type-equiv
261
+ /** No live Session carries the requested id. */
262
+ interface SessionFeedbackSessionNotFound {
263
+ readonly code: 'session-not-found'
264
+ readonly sessionId: SessionId
265
+ }
266
+ ```
267
+
268
+ ```ts type-equiv
269
+ /** Result returned by the `sessionFeedback.record` operation. */
270
+ type SessionFeedbackRecordResult =
271
+ | { readonly ok: true; readonly value: SessionFeedbackRecordValue }
272
+ | { readonly ok: false; readonly error: SessionFeedbackSessionNotFound }
273
+ ```
274
+
275
+ ## Data and concurrency
276
+
277
+ Current items are folded from canonical feedback events whose payload `sessionId` matches the owning Session. Each item carries a positive or negative rating, an optional note, an optional category, Host-assigned `createdAt`/`updatedAt` timestamps, and its own opaque version. Versions are compared only for equality and only against the addressed message; callers do not order or synthesize them.
278
+
279
+ `put` uses strict optimistic concurrency: every request for an existing item must match its current `ifVersion`, including a no-op (a put repeating the stored rating, note, and category). A conflict returns the authoritative current item (or `null`), so a caller can reconcile a lost response or a concurrent edit without another read. Deleting an already absent item succeeds. A per-Session queue serializes reads and mutations; cold mutations hold a persistence write handle across read, comparison, append, and flush. Matching no-ops append no event.
280
+
281
+ ## Target and lifecycle authority
282
+
283
+ A live owner's in-memory log supplies the target Session observation directly; cold reads use a `SessionPersistence.open(id, 'read')` handle, while mutations use a write handle. Neither path constructs a Session or Agent. A `stat(id)` preflight classifies definite absence; a read failure for a Session `stat` confirmed propagates as infrastructure failure. `put` accepts only a non-empty, append-origin `assistant/message` with the requested `MessageId`; replacement-origin, usage-only empty, and non-assistant records are not feedback targets.
284
+
285
+ Fork seeds can contain parent feedback events, but their payload retains the parent `sessionId`, so they do not become current feedback for the child. Deleting an item appends a tombstone; earlier ratings and notes remain in the log.
286
+
287
+ ## Persistence and Remote contract
288
+
289
+ Successful message-feedback mutations await canonical persistence: live operations append through the owning Session and require a participating `ctx.sessions.flush` listener; cold operations append and flush through their write handle. Persistence failures propagate rather than reporting success. `maxNoteBytes` is required and bounds note text by UTF-8 bytes; the Web Host composition sets `8192`. The package publishes the Host `messageFeedback.list`, `messageFeedback.put`, and `messageFeedback.delete` unary Remote contract through `TypertRemoteService` and `@Remote`; `command-feedback` publishes `sessionFeedback.record` the same way for Session-level remarks on live Sessions. The generated Cordis API below is the method-level authority.
290
+
291
+ Plugin disposal closes operation admission and drains accepted per-Session queue work.
292
+
293
+ By default, [`session-log-deepseek`](../../packages/session/session-log-deepseek/README.md) carries feedback as part of the ordinary `dsh_session_log` suffix on subsequent eligible DeepSeek requests; a composition disables it with `enabled: false`. Recording feedback does not trigger an LLM request or a separate `dsh_feedback` upload. For non-DeepSeek routes, the [OTel backend](../../packages/session/session-telemetry-otel/README.md) can release the canonical prefix through recorded feedback. The command acknowledgement confirms recording and identifies the Session and anonymous user; it reports neither telemetry policy nor delivery.
294
+
295
+ ## Web surface
296
+
297
+ [`@deepseek-ai/dsh-client-ui-message-feedback`](../../packages/client/ui-message-feedback) is the browser consumer. `@deepseek-ai/dsh-api-remotes` mounts the generated `messageFeedback` and `sessionFeedback` contributions, so the plugin calls `ctx.remote.messageFeedback` and `ctx.remote.sessionFeedback` and never touches the transport.
298
+
299
+ The controls are the `feedback` entry (order 10) of the `conversation.chat.assistant-actions` list slot, which `ui-conversation` declares and renders inside the finalized assistant message's IconActions row. `AssistantMessageNode` carries the optional `messageId` from the `assistant/message` event. The field is absent on interruption-frozen partials, and the render site skips the slot when it is absent. The strip renders once per turn, on the closing assistant message: the Host accepts every append-origin step message as a target, but earlier steps of a multi-step turn render tool rows rather than a rateable body, so the UI exposes a narrower set than the Host contract allows.
300
+
301
+ One `MessageFeedbackController` per Session backs every message control in that Session: a single `list` read seeds the whole transcript, deferred to first hover or focus rather than fired on mount. Each mutation sends the version that controller last observed as `ifVersion`; a `version-conflict` reply carries the authoritative item, so the controller reconciles from the reply instead of refetching. Mutations serialize per Session so a queued operation compares against the committed version. The injected `retract` operation rechecks the committed rating inside that queue and becomes a no-op after a concurrent change, so stale UI cannot bypass the dialog by recording a bare rating. A `connection/reset` refreshes only Sessions already read.
302
+
303
+ Either unrecorded rating opens the Session's feedback dialog, the `feedback-dialog` entry of `conversation.input.overlay`: the shared Modal card with seven category chips and a detail box. Submit puts the selected judgment carrying the chosen category and the trimmed description, or neither; success closes the dialog and shows the acknowledgement toast, while failure keeps the dialog and draft open and shows a warning toast. The same dialog opens for the Session from a bare `/feedback` — a decoration `ui-commands` routes as an `action` — and then records through `sessionFeedback.record`; `/feedback <text>` keeps the Host command path. Clicking a recorded rating retracts it without opening the dialog.
304
+
305
+ ## Boundaries and limitations
306
+
307
+ - The operation queue is process-local; cold writer exclusion relies on the selected persistence provider.
308
+ - Deletion removes the current item, not earlier note text from the append-only log or an already delivered suffix.
309
+ - A request in the narrow interval after live detach but before the persistence catalog materializes the header can receive `session-not-found`; callers retry after retirement materialization.
310
+ - Cold requests read the complete log; the service has no item-count or aggregate-byte cap. `maxNoteBytes` bounds only each note.
311
+ - The Host contract records no authenticated actor or audit identity and therefore assumes a trusted caller boundary.
312
+ - The Web controls appear in the chat view only. The trajectory and waterfall views render no feedback entry even though their assistant nodes carry the same `messageId`.
313
+ - The Web controller does not consume feedback log events, so a second tab's rating becomes visible on reconnect or on the next conflict reply rather than immediately.
314
+ - The dialog does not pre-check `maxNoteBytes`; an oversized description for a message fails on submit with `note-too-large` rather than while typing. A Session remark has no size bound, as the `/feedback` command never had one.
315
+ - `sessionFeedback.record` serves live Sessions only and answers `session-not-found` otherwise; the dialog reports that failure when its Session retires while it is open.
316
+
317
+ ## Feedback in exported Session logs
318
+
319
+ This section is for consumers that select rated Sessions from exported logs. The [OTel backend](../../packages/session/session-telemetry-otel/README.md#use-this-package) owns the record fields and the feedback that releases a log prefix; the [session-telemetry subsystem](session-telemetry.md) owns deduplication, and [the redact waterfall](session-telemetry.md#session-telemetryrecord--waterfall) owns how exported `data` can differ from the canonical log. The feedback-specific `data` fields are:
320
+
321
+ | Event | Target | `data` | Meaning |
322
+ |---|---|---|---|
323
+ | `feedback/record` | Whole Session | `text?`, `category?` | One immutable remark. `/feedback <text>` records only `text`; the Web dialog records the selected `category` and the entered `text`, each optional; a record with neither field is valid. |
324
+ | `feedback/message-put` | One assistant message | `sessionId`, and `item` with `messageId`, `rating`, `note?`, `category?`, `version`, `createdAt`, `updatedAt` | Complete current value after a creation or edit |
325
+ | `feedback/message-delete` | One assistant message | `sessionId`, `messageId` | Retraction of the current value |
326
+
327
+ Derive feedback with these rules:
328
+
329
+ 1. When counting a Session's own feedback, exclude feedback events whose `seq` is below `session.seed_length`, which only seeded Sessions carry, and `feedback/message-*` events whose `data.sessionId` differs from the record's `sessionId`. Keep every other event, including the inherited prefix, for the rules below.
330
+ 2. Group `feedback/message-put` by `data.item.messageId` and `feedback/message-delete` by `data.messageId` within one Session; the event with the highest `seq` is the current value, and a `feedback/message-delete` there means no current feedback. Earlier puts remain as edit history.
331
+ 3. The rated reply is the append-origin `assistant/message` whose `data.message.id` equals `data.item.messageId`; in a seeded Session it can lie in the inherited prefix. Its `data.turn` identifies the turn, and the events up to it reproduce the conversation state.
332
+
333
+ The services and events record no actor. Host plugins and runtime extensions can call `sessionFeedback.record` and `messageFeedback.put` or append these events directly, and Client plugins can call the same Remotes, so exported feedback fields can contain plugin-written state. Each appended feedback event of the Session itself also authorizes the release of the prefix that ends at it. Text content does not establish who wrote a value; recognition rules for specific plugins belong to the consumer's tooling.
334
+
335
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
336
+
337
+ <a id="cordis-surface"></a>
338
+
339
+ ## Cordis API
340
+
341
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
342
+
343
+ <a id="ctxmessagefeedback--messagefeedbackservice"></a>
344
+
345
+ ### `ctx.messageFeedback` — `MessageFeedbackService`
346
+
347
+ Session-log service; cold operations never construct a Session or Agent.
348
+
349
+ ```ts cordis-catalog
350
+ /**
351
+ * Read current feedback from the canonical log.
352
+ * @param request - Session to inspect.
353
+ * @returns immutable items or a definite persistence miss.
354
+ */
355
+ @Remote('list') list(request: MessageFeedbackListRequest): Promise<MessageFeedbackListResult>
356
+
357
+ /**
358
+ * Create or replace feedback after checking its current version.
359
+ * Matching no-ops retain the version and append no event.
360
+ * @param request - Target, desired value, and observed item version.
361
+ * @returns the durable item or an explicit business failure.
362
+ */
363
+ @Remote('put') put(request: MessageFeedbackPutRequest): Promise<MessageFeedbackPutResult>
364
+
365
+ /**
366
+ * Delete one item after checking its version; absence succeeds without an event.
367
+ * @param request - Session, message, and observed item version.
368
+ * @returns the stable absent postcondition or an explicit failure.
369
+ */
370
+ @Remote('delete') delete(request: MessageFeedbackDeleteRequest): Promise<MessageFeedbackDeleteResult>
371
+ ```
372
+
373
+ Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
374
+
375
+ <a id="ctxsessionfeedback--sessionfeedbackservice"></a>
376
+
377
+ ### `ctx.sessionFeedback` — `SessionFeedbackService`
378
+
379
+ Host Remote through which a product surface records a Session-level remark.
380
+
381
+ ```ts cordis-catalog
382
+ /**
383
+ * Record one remark on a live Session.
384
+ * @param request - target Session plus the optional text and category.
385
+ * @returns the recorded postcondition, or `session-not-found` when no live
386
+ * Session carries the id.
387
+ */
388
+ @Remote('record') record(request: SessionFeedbackRecordRequest): Promise<SessionFeedbackRecordResult>
389
+ ```
390
+
391
+ Source: [`packages/feedback/command-feedback/src/index.ts`](../../packages/feedback/command-feedback/src/index.ts)
392
+
393
+ <a id="feedback-events"></a>
394
+
395
+ ### `feedback/*` events
396
+
397
+ <a id="feedbackcommitted--parallel"></a>
398
+
399
+ #### `feedback/committed` — parallel
400
+
401
+ Observe a durable cold feedback mutation without publishing a live Session. Observers run before write ownership is released and must not await another message-feedback operation for this Session. The payload is borrowed read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
402
+
403
+ ```ts cordis-catalog
404
+ /**
405
+ * Observe a durable cold feedback mutation without publishing a live Session.
406
+ * Observers run before write ownership is released and must not await
407
+ * another message-feedback operation for this Session. The payload is borrowed
408
+ * read-only; deep-clone it before transferring ownership (for example, to Session.fromRestore).
409
+ * @param inspection - committed canonical prefix, including the feedback as its last event.
410
+ * @mode parallel
411
+ */
412
+ 'feedback/committed'(inspection: SessionInspection): void
413
+ ```
414
+
415
+ Types: [SessionInspection](persistence.md)
416
+
417
+ Source: [`packages/feedback/message-feedback/src/index.ts`](../../packages/feedback/message-feedback/src/index.ts)
418
+ <!-- END GENERATED cordis-surface -->