@deepseek-ai/dsh-message-feedback 0.1.3-alpha.2 → 0.1.5-alpha.2
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.i18n.yaml +2 -2
- package/README.md +5 -5
- package/README.zh.md +5 -5
- package/lib/index.js +4 -1
- package/lib/typert.host.js +14 -5
- package/lib/typert.remote-client.js +8 -3
- package/lib/types/index.js +5 -1
- package/lib/types/types.d.ts +5 -0
- package/package.json +15 -13
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/feedback/message-feedback/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 4e75d167fe39c96002b32def24f447efdbc2be70
|
|
6
|
+
README.zh.md: 0c21e26f9a4ffa40ce29412c652029d3af4e9fe0
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Canonical Session-log ratings and notes for finalized assistant messages."
|
|
2
|
+
description: "Canonical Session-log ratings, categories, and notes for finalized assistant messages."
|
|
3
3
|
kind: "package-reference"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
This service records positive or negative ratings and optional verbatim notes for finalized assistant messages. The canonical Session log owns every creation, edit, and deletion; `list`, `put`, and `delete` expose current feedback without constructing or waking an Agent. Feedback is log-only and does not enter model history.
|
|
12
|
+
This service records positive or negative ratings, an optional category from the fixed feedback taxonomy, and optional verbatim notes for finalized assistant messages. The canonical Session log owns every creation, edit, and deletion; `list`, `put`, and `delete` expose current feedback without constructing or waking an Agent. Feedback is log-only and does not enter model history.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -30,17 +30,17 @@ Mount `dsh-message-feedback` alongside `sessions` and `sessionPersistence`. It n
|
|
|
30
30
|
|---|---|---|
|
|
31
31
|
| `maxNoteBytes` | required | Positive safe-integer maximum UTF-8 bytes in one optional note. |
|
|
32
32
|
|
|
33
|
-
A supplied note must contain a non-whitespace character and fit the configured byte limit. Blank notes return `note-blank`; oversized notes return `note-too-large`. Accepted text is preserved exactly, including surrounding whitespace. Omitting a note clears it. Note validation precedes Session lookup.
|
|
33
|
+
A supplied note must contain a non-whitespace character and fit the configured byte limit. Blank notes return `note-blank`; oversized notes return `note-too-large`. Accepted text is preserved exactly, including surrounding whitespace. Omitting a note clears it. Note validation precedes Session lookup. A supplied category must be one of the [fixed feedback categories](../command-feedback/README.md#the-web-feedback-dialog); the Remote schema rejects any other value, and omitting the category clears it.
|
|
34
34
|
|
|
35
35
|
### Reading and changing feedback
|
|
36
36
|
|
|
37
37
|
| Operation | Request | Success | Business failures |
|
|
38
38
|
|---|---|---|---|
|
|
39
39
|
| `list` | Session id | Current items in creation order | Session not found |
|
|
40
|
-
| `put` | Session, message, rating, optional note, expected version | Current item | Session or target not found, version conflict, invalid note |
|
|
40
|
+
| `put` | Session, message, rating, optional note, optional category, expected version | Current item | Session or target not found, version conflict, invalid note |
|
|
41
41
|
| `delete` | Session, message, expected version | Item absent | Session not found, version conflict |
|
|
42
42
|
|
|
43
|
-
Create with `ifVersion: null`; edit or delete with the returned version. Stale mutations return `version-conflict` and the current item. Each material put mints a fresh token and preserves the original creation time. A
|
|
43
|
+
Create with `ifVersion: null`; edit or delete with the returned version. Stale mutations return `version-conflict` and the current item. Each material put mints a fresh token and preserves the original creation time. A put that repeats the stored rating, note, and category is a no-op: it returns the same item without appending an event. Deleting an absent item succeeds regardless of the supplied version, without appending an event. Recreating a deleted item starts a new creation time and ordering position.
|
|
44
44
|
|
|
45
45
|
Targets must be non-empty assistant messages produced by append-origin events. User messages, empty assistant placeholders, and replacement-origin messages return `target-not-found`. Feedback survives restart; a fork starts without owned feedback even when its inherited prefix contains parent feedback.
|
|
46
46
|
|
package/README.zh.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "在权威 Session 日志中保存已完成 assistant
|
|
2
|
+
description: "在权威 Session 日志中保存已完成 assistant 消息的评分、分类与备注。"
|
|
3
3
|
kind: "package-reference"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ kind: "package-reference"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
本服务为已完成的 assistant
|
|
12
|
+
本服务为已完成的 assistant 消息记录好评、差评、固定反馈分类表中的可选分类,以及可选的原样备注。每次创建、编辑和删除都由权威 Session 日志保存;`list`、`put` 和 `delete` 提供当前反馈,不会构造或唤醒 Agent。反馈仅写入日志,不进入模型历史。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -30,17 +30,17 @@ kind: "package-reference"
|
|
|
30
30
|
|---|---|---|
|
|
31
31
|
| `maxNoteBytes` | 必填 | 单条可选备注的 UTF-8 字节上限,必须为正安全整数。 |
|
|
32
32
|
|
|
33
|
-
提交的备注必须包含非空白字符,且不超过配置的字节上限。空白备注返回 `note-blank`;过长备注返回 `note-too-large`。通过校验的文本会完整保留,包括首尾空白。省略备注会清除它。备注校验先于 Session
|
|
33
|
+
提交的备注必须包含非空白字符,且不超过配置的字节上限。空白备注返回 `note-blank`;过长备注返回 `note-too-large`。通过校验的文本会完整保留,包括首尾空白。省略备注会清除它。备注校验先于 Session 查找。提交的分类必须是[固定反馈分类](../command-feedback/README.zh.md#the-web-feedback-dialog)之一;Remote schema 拒绝其他值,省略分类会清除它。
|
|
34
34
|
|
|
35
35
|
### 读取与修改反馈
|
|
36
36
|
|
|
37
37
|
| 操作 | 请求 | 成功 | 业务失败 |
|
|
38
38
|
|---|---|---|---|
|
|
39
39
|
| `list` | Session id | 按创建顺序返回当前条目 | Session 不存在 |
|
|
40
|
-
| `put` | Session
|
|
40
|
+
| `put` | Session、消息、评分、可选备注、可选分类、预期版本 | 当前条目 | Session 或目标不存在、版本冲突、备注无效 |
|
|
41
41
|
| `delete` | Session、消息、预期版本 | 条目不存在 | Session 不存在、版本冲突 |
|
|
42
42
|
|
|
43
|
-
创建时传入 `ifVersion: null`;编辑或删除时使用返回的版本。陈旧修改返回 `version-conflict` 及当前条目。每次实质 put 都生成新 token
|
|
43
|
+
创建时传入 `ifVersion: null`;编辑或删除时使用返回的版本。陈旧修改返回 `version-conflict` 及当前条目。每次实质 put 都生成新 token,并保留原始创建时间。重复已存评分、备注与分类的 put 是无变化操作:返回相同条目,不追加事件。删除不存在的条目始终成功,不受所传版本影响,也不追加事件。重新创建已删除条目会产生新的创建时间和排序位置。
|
|
44
44
|
|
|
45
45
|
目标必须是由 append 来源事件产生的非空 assistant 消息。用户消息、空 assistant 占位及 replacement 来源消息返回 `target-not-found`。反馈跨重启保留;fork 即使继承了包含父会话反馈的前缀,也从没有自有反馈开始。
|
|
46
46
|
|
package/lib/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
4
4
|
import { Service } from "@deepseek-ai/cordis";
|
|
5
5
|
import s from "@deepseek-ai/schemastery";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import { FEEDBACK_CATEGORIES } from "@deepseek-ai/dsh-command-feedback";
|
|
7
8
|
import { SessionSeq } from "@deepseek-ai/dsh-session/types";
|
|
8
9
|
import { deriveEventMessage, isAppendSurfaceEvent } from "@deepseek-ai/dsh-session/surface";
|
|
9
10
|
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
@@ -55,6 +56,7 @@ const itemSchema = z.object({
|
|
|
55
56
|
messageId: z.string().min(1),
|
|
56
57
|
rating: z.enum(["positive", "negative"]),
|
|
57
58
|
note: z.string().refine((note) => note.trim().length > 0).optional(),
|
|
59
|
+
category: z.enum(FEEDBACK_CATEGORIES).optional(),
|
|
58
60
|
version: z.uuid(),
|
|
59
61
|
createdAt: timestamp,
|
|
60
62
|
updatedAt: timestamp
|
|
@@ -199,7 +201,7 @@ let MessageFeedbackService = (() => {
|
|
|
199
201
|
});
|
|
200
202
|
const existing = items.find((item) => item.messageId === request.messageId);
|
|
201
203
|
if (request.ifVersion !== (existing?.version ?? null)) return rejected(this.versionConflict(existing ?? null));
|
|
202
|
-
if (existing !== void 0 && existing.rating === request.rating && existing.note === note.value) {
|
|
204
|
+
if (existing !== void 0 && existing.rating === request.rating && existing.note === note.value && existing.category === request.category) {
|
|
203
205
|
await append();
|
|
204
206
|
return success(snapshotItem(existing));
|
|
205
207
|
}
|
|
@@ -208,6 +210,7 @@ let MessageFeedbackService = (() => {
|
|
|
208
210
|
messageId: request.messageId,
|
|
209
211
|
rating: request.rating,
|
|
210
212
|
...note.value === void 0 ? {} : { note: note.value },
|
|
213
|
+
...request.category === void 0 ? {} : { category: request.category },
|
|
211
214
|
version: randomUUID(),
|
|
212
215
|
createdAt: existing?.createdAt ?? now,
|
|
213
216
|
updatedAt: existing === void 0 ? now : Math.max(now, existing.updatedAt)
|
package/lib/typert.host.js
CHANGED
|
@@ -22,6 +22,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_delete_result$schema = z
|
|
|
22
22
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
23
23
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
24
24
|
'note': z.string().readonly().optional(),
|
|
25
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
25
26
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
26
27
|
'createdAt': z.number().readonly(),
|
|
27
28
|
'updatedAt': z.number().readonly(),
|
|
@@ -38,6 +39,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_list_result$schema = z.u
|
|
|
38
39
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
39
40
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
40
41
|
'note': z.string().readonly().optional(),
|
|
42
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
41
43
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
42
44
|
'createdAt': z.number().readonly(),
|
|
43
45
|
'updatedAt': z.number().readonly(),
|
|
@@ -55,6 +57,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_put_parameter_0$schema =
|
|
|
55
57
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
56
58
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
57
59
|
'note': z.string().readonly().optional(),
|
|
60
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
58
61
|
'ifVersion': z.union([z.literal(null), z.intersection(z.string(), z.unknown())]).readonly(),
|
|
59
62
|
})
|
|
60
63
|
const _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema = z.union([z.object({
|
|
@@ -63,6 +66,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema = z.un
|
|
|
63
66
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
64
67
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
65
68
|
'note': z.string().readonly().optional(),
|
|
69
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
66
70
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
67
71
|
'createdAt': z.number().readonly(),
|
|
68
72
|
'updatedAt': z.number().readonly(),
|
|
@@ -82,6 +86,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema = z.un
|
|
|
82
86
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
83
87
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
84
88
|
'note': z.string().readonly().optional(),
|
|
89
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
85
90
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
86
91
|
'createdAt': z.number().readonly(),
|
|
87
92
|
'updatedAt': z.number().readonly(),
|
|
@@ -124,7 +129,7 @@ export const TYPERT = {
|
|
|
124
129
|
typeSymbol: '@deepseek-ai/dsh-message-feedback/types#MessageFeedbackDeleteResult',
|
|
125
130
|
schema: _deepseek_ai_dsh_message_feedback_messageFeedback_delete_result$schema,
|
|
126
131
|
},
|
|
127
|
-
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":
|
|
132
|
+
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":207,"column":3},
|
|
128
133
|
},
|
|
129
134
|
{
|
|
130
135
|
id: '@deepseek-ai/dsh-message-feedback#messageFeedback/list',
|
|
@@ -149,7 +154,7 @@ export const TYPERT = {
|
|
|
149
154
|
typeSymbol: '@deepseek-ai/dsh-message-feedback/types#MessageFeedbackListResult',
|
|
150
155
|
schema: _deepseek_ai_dsh_message_feedback_messageFeedback_list_result$schema,
|
|
151
156
|
},
|
|
152
|
-
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":
|
|
157
|
+
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":155,"column":3},
|
|
153
158
|
},
|
|
154
159
|
{
|
|
155
160
|
id: '@deepseek-ai/dsh-message-feedback#messageFeedback/put',
|
|
@@ -174,7 +179,7 @@ export const TYPERT = {
|
|
|
174
179
|
typeSymbol: '@deepseek-ai/dsh-message-feedback/types#MessageFeedbackPutResult',
|
|
175
180
|
schema: _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema,
|
|
176
181
|
},
|
|
177
|
-
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":
|
|
182
|
+
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":167,"column":3},
|
|
178
183
|
},
|
|
179
184
|
],
|
|
180
185
|
model: {
|
|
@@ -214,6 +219,10 @@ export const TYPERT = {
|
|
|
214
219
|
"name": "Branded",
|
|
215
220
|
"declaration": "export type Branded<B extends string> = string & { readonly [BRAND]: B; };"
|
|
216
221
|
},
|
|
222
|
+
{
|
|
223
|
+
"name": "FeedbackCategory",
|
|
224
|
+
"declaration": "export type FeedbackCategory = 'task-result' | 'instruction-following' | 'product-interaction' | 'service-stability' | 'resource-cost' | 'security-privacy-permission' | 'other';"
|
|
225
|
+
},
|
|
217
226
|
{
|
|
218
227
|
"name": "MessageFeedbackDeleteRequest",
|
|
219
228
|
"declaration": "export interface MessageFeedbackDeleteRequest {\n readonly sessionId: SessionId;\n readonly messageId: MessageId;\n readonly ifVersion: MessageFeedbackVersion;\n}"
|
|
@@ -232,7 +241,7 @@ export const TYPERT = {
|
|
|
232
241
|
},
|
|
233
242
|
{
|
|
234
243
|
"name": "MessageFeedbackItem",
|
|
235
|
-
"declaration": "export interface MessageFeedbackItem {\n readonly messageId: MessageId;\n readonly rating: MessageFeedbackRating;\n readonly note?: string;\n readonly version: MessageFeedbackVersion;\n readonly createdAt: number;\n readonly updatedAt: number;\n}"
|
|
244
|
+
"declaration": "export interface MessageFeedbackItem {\n readonly messageId: MessageId;\n readonly rating: MessageFeedbackRating;\n readonly note?: string;\n readonly category?: FeedbackCategory;\n readonly version: MessageFeedbackVersion;\n readonly createdAt: number;\n readonly updatedAt: number;\n}"
|
|
236
245
|
},
|
|
237
246
|
{
|
|
238
247
|
"name": "MessageFeedbackListRequest",
|
|
@@ -256,7 +265,7 @@ export const TYPERT = {
|
|
|
256
265
|
},
|
|
257
266
|
{
|
|
258
267
|
"name": "MessageFeedbackPutRequest",
|
|
259
|
-
"declaration": "export interface MessageFeedbackPutRequest {\n readonly sessionId: SessionId;\n readonly messageId: MessageId;\n readonly rating: MessageFeedbackRating;\n readonly note?: string;\n readonly ifVersion: MessageFeedbackVersion | null;\n}"
|
|
268
|
+
"declaration": "export interface MessageFeedbackPutRequest {\n readonly sessionId: SessionId;\n readonly messageId: MessageId;\n readonly rating: MessageFeedbackRating;\n readonly note?: string;\n readonly category?: FeedbackCategory;\n readonly ifVersion: MessageFeedbackVersion | null;\n}"
|
|
260
269
|
},
|
|
261
270
|
{
|
|
262
271
|
"name": "MessageFeedbackPutResult",
|
|
@@ -22,6 +22,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_delete_result$schema = z
|
|
|
22
22
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
23
23
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
24
24
|
'note': z.string().readonly().optional(),
|
|
25
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
25
26
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
26
27
|
'createdAt': z.number().readonly(),
|
|
27
28
|
'updatedAt': z.number().readonly(),
|
|
@@ -38,6 +39,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_list_result$schema = z.u
|
|
|
38
39
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
39
40
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
40
41
|
'note': z.string().readonly().optional(),
|
|
42
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
41
43
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
42
44
|
'createdAt': z.number().readonly(),
|
|
43
45
|
'updatedAt': z.number().readonly(),
|
|
@@ -55,6 +57,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_put_parameter_0$schema =
|
|
|
55
57
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
56
58
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
57
59
|
'note': z.string().readonly().optional(),
|
|
60
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
58
61
|
'ifVersion': z.union([z.literal(null), z.intersection(z.string(), z.unknown())]).readonly(),
|
|
59
62
|
})
|
|
60
63
|
const _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema = z.union([z.object({
|
|
@@ -63,6 +66,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema = z.un
|
|
|
63
66
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
64
67
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
65
68
|
'note': z.string().readonly().optional(),
|
|
69
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
66
70
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
67
71
|
'createdAt': z.number().readonly(),
|
|
68
72
|
'updatedAt': z.number().readonly(),
|
|
@@ -82,6 +86,7 @@ const _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema = z.un
|
|
|
82
86
|
'messageId': z.intersection(z.string(), z.unknown()).readonly(),
|
|
83
87
|
'rating': z.union([z.literal("positive"), z.literal("negative")]).readonly(),
|
|
84
88
|
'note': z.string().readonly().optional(),
|
|
89
|
+
'category': z.union([z.literal("other"), z.literal("task-result"), z.literal("instruction-following"), z.literal("product-interaction"), z.literal("service-stability"), z.literal("resource-cost"), z.literal("security-privacy-permission")]).readonly().optional(),
|
|
85
90
|
'version': z.intersection(z.string(), z.unknown()).readonly(),
|
|
86
91
|
'createdAt': z.number().readonly(),
|
|
87
92
|
'updatedAt': z.number().readonly(),
|
|
@@ -121,7 +126,7 @@ export const TYPERT_REMOTE = {
|
|
|
121
126
|
typeSymbol: '@deepseek-ai/dsh-message-feedback/types#MessageFeedbackDeleteResult',
|
|
122
127
|
schema: _deepseek_ai_dsh_message_feedback_messageFeedback_delete_result$schema,
|
|
123
128
|
},
|
|
124
|
-
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":
|
|
129
|
+
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":207,"column":3},
|
|
125
130
|
},
|
|
126
131
|
{
|
|
127
132
|
id: '@deepseek-ai/dsh-message-feedback#messageFeedback/list',
|
|
@@ -146,7 +151,7 @@ export const TYPERT_REMOTE = {
|
|
|
146
151
|
typeSymbol: '@deepseek-ai/dsh-message-feedback/types#MessageFeedbackListResult',
|
|
147
152
|
schema: _deepseek_ai_dsh_message_feedback_messageFeedback_list_result$schema,
|
|
148
153
|
},
|
|
149
|
-
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":
|
|
154
|
+
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":155,"column":3},
|
|
150
155
|
},
|
|
151
156
|
{
|
|
152
157
|
id: '@deepseek-ai/dsh-message-feedback#messageFeedback/put',
|
|
@@ -171,7 +176,7 @@ export const TYPERT_REMOTE = {
|
|
|
171
176
|
typeSymbol: '@deepseek-ai/dsh-message-feedback/types#MessageFeedbackPutResult',
|
|
172
177
|
schema: _deepseek_ai_dsh_message_feedback_messageFeedback_put_result$schema,
|
|
173
178
|
},
|
|
174
|
-
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":
|
|
179
|
+
sourceLocation: {"file":"packages/feedback/message-feedback/src/index.ts","line":167,"column":3},
|
|
175
180
|
},
|
|
176
181
|
],
|
|
177
182
|
}
|
package/lib/types/index.js
CHANGED
|
@@ -42,6 +42,7 @@ import { isDeepStrictEqual } from 'node:util';
|
|
|
42
42
|
import { Service } from '@deepseek-ai/cordis';
|
|
43
43
|
import s from '@deepseek-ai/schemastery';
|
|
44
44
|
import { z } from 'zod';
|
|
45
|
+
import { FEEDBACK_CATEGORIES } from '@deepseek-ai/dsh-command-feedback';
|
|
45
46
|
import { SessionSeq } from '@deepseek-ai/dsh-session/types';
|
|
46
47
|
import { deriveEventMessage, isAppendSurfaceEvent } from '@deepseek-ai/dsh-session/surface';
|
|
47
48
|
import { TypertRemoteService, Remote } from '@deepseek-ai/dsh-typert-protocol';
|
|
@@ -50,6 +51,7 @@ const itemSchema = z.object({
|
|
|
50
51
|
messageId: z.string().min(1),
|
|
51
52
|
rating: z.enum(['positive', 'negative']),
|
|
52
53
|
note: z.string().refine(note => note.trim().length > 0).optional(),
|
|
54
|
+
category: z.enum(FEEDBACK_CATEGORIES).optional(),
|
|
53
55
|
version: z.uuid(),
|
|
54
56
|
createdAt: timestamp,
|
|
55
57
|
updatedAt: timestamp,
|
|
@@ -160,7 +162,8 @@ let MessageFeedbackService = (() => {
|
|
|
160
162
|
if (request.ifVersion !== (existing?.version ?? null)) {
|
|
161
163
|
return rejected(this.versionConflict(existing ?? null));
|
|
162
164
|
}
|
|
163
|
-
if (existing !== undefined && existing.rating === request.rating && existing.note === note.value
|
|
165
|
+
if (existing !== undefined && existing.rating === request.rating && existing.note === note.value
|
|
166
|
+
&& existing.category === request.category) {
|
|
164
167
|
await append();
|
|
165
168
|
return success(snapshotItem(existing));
|
|
166
169
|
}
|
|
@@ -169,6 +172,7 @@ let MessageFeedbackService = (() => {
|
|
|
169
172
|
messageId: request.messageId,
|
|
170
173
|
rating: request.rating,
|
|
171
174
|
...(note.value === undefined ? {} : { note: note.value }),
|
|
175
|
+
...(request.category === undefined ? {} : { category: request.category }),
|
|
172
176
|
version: randomUUID(),
|
|
173
177
|
createdAt: existing?.createdAt ?? now,
|
|
174
178
|
updatedAt: existing === undefined ? now : Math.max(now, existing.updatedAt),
|
package/lib/types/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
8
8
|
import type { MessageId } from '@deepseek-ai/dsh-llm/brand';
|
|
9
9
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
10
|
+
import type { FeedbackCategory } from '@deepseek-ai/dsh-command-feedback/types';
|
|
10
11
|
/** Opaque compare-and-set token for one exact feedback item revision. */
|
|
11
12
|
export type MessageFeedbackVersion = Branded<'MessageFeedbackVersion'>;
|
|
12
13
|
/** The human's overall judgment of one assistant message. */
|
|
@@ -19,6 +20,8 @@ export interface MessageFeedbackItem {
|
|
|
19
20
|
readonly rating: MessageFeedbackRating;
|
|
20
21
|
/** Optional explanation, preserved verbatim after validation. */
|
|
21
22
|
readonly note?: string;
|
|
23
|
+
/** Category the human filed a negative judgment under. */
|
|
24
|
+
readonly category?: FeedbackCategory;
|
|
22
25
|
/** Equality-only token replaced by every material create or update. */
|
|
23
26
|
readonly version: MessageFeedbackVersion;
|
|
24
27
|
/** Host-assigned creation time in Unix epoch milliseconds. */
|
|
@@ -68,6 +71,8 @@ export interface MessageFeedbackPutRequest {
|
|
|
68
71
|
readonly rating: MessageFeedbackRating;
|
|
69
72
|
/** Optional non-blank explanation. */
|
|
70
73
|
readonly note?: string;
|
|
74
|
+
/** Optional category; absent keeps the item uncategorized. */
|
|
75
|
+
readonly category?: FeedbackCategory;
|
|
71
76
|
/** Observed item version, or `null` to require that no item exists. */
|
|
72
77
|
readonly ifVersion: MessageFeedbackVersion | null;
|
|
73
78
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-message-feedback",
|
|
3
3
|
"description": "Canonical Session-log ratings and notes for finalized assistant messages",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -44,12 +44,13 @@
|
|
|
44
44
|
],
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@deepseek-ai/dsh-
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
50
|
-
"@deepseek-ai/dsh-session
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/cordis": "^4.0.2"
|
|
47
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-alpha.2",
|
|
48
|
+
"@deepseek-ai/dsh-brand": "^0.1.5-alpha.2",
|
|
49
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.5-alpha.2",
|
|
50
|
+
"@deepseek-ai/dsh-session": "^0.1.5-alpha.2",
|
|
51
|
+
"@deepseek-ai/dsh-command-feedback": "^0.1.5-alpha.2",
|
|
52
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
53
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.2"
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"zod": "^4.4.3",
|
|
@@ -58,12 +59,13 @@
|
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@deepseek-ai/cordis-plugin-include": "^1.0.7",
|
|
60
61
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
62
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-session": "^0.1.5-alpha.2",
|
|
64
|
+
"@deepseek-ai/dsh-brand": "^0.1.5-alpha.2",
|
|
65
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.5-alpha.2",
|
|
66
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-alpha.2",
|
|
65
67
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
66
|
-
"@deepseek-ai/dsh-
|
|
67
|
-
"@deepseek-ai/dsh-session-persistence": "^0.1.
|
|
68
|
+
"@deepseek-ai/dsh-command-feedback": "^0.1.5-alpha.2",
|
|
69
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.5-alpha.2"
|
|
68
70
|
}
|
|
69
71
|
}
|