dsh-response-effort 0.0.0-stage → 0.2.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 +145 -2
- package/cordis.patch.yml +6 -0
- package/dist/client.js +406 -0
- package/dist/client.js.map +7 -0
- package/dist/index.js +727 -0
- package/dist/index.js.map +7 -0
- package/dist/types/client/EffortBadge.d.ts +7 -0
- package/dist/types/client/EffortDock.d.ts +7 -0
- package/dist/types/client/index.d.ts +4 -0
- package/dist/types/client/locale.d.ts +32 -0
- package/dist/types/client/session-store.d.ts +37 -0
- package/dist/types/config.d.ts +38 -0
- package/dist/types/contracts.d.ts +59 -0
- package/dist/types/host/association.d.ts +29 -0
- package/dist/types/host/cache.d.ts +27 -0
- package/dist/types/host/call-context.d.ts +5 -0
- package/dist/types/host/fetch-tap.d.ts +32 -0
- package/dist/types/host/remote.d.ts +11 -0
- package/dist/types/host/sse-parser.d.ts +18 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/remote-contract.d.ts +4 -0
- package/package.json +93 -4
package/README.md
CHANGED
|
@@ -1,3 +1,146 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-response-effort
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在 DSH **输入框上方**及时查看每次匹配的 Responses SSE 返回的 `response.reasoning.effort`,展开查看逐次记录,并保留最终回复操作栏的消息标签。这是服务端报告值,不是对模型内部实际推理量的测量。
|
|
4
|
+
|
|
5
|
+
## 兼容范围
|
|
6
|
+
|
|
7
|
+
- 插件 `0.2.1`;DSH `0.2.0-rc.2`,Node.js 24+,Web 客户端。
|
|
8
|
+
- 仅 POST Responses SSE,读取 `response.completed`、`response.incomplete`、`response.failed`。
|
|
9
|
+
- 可用于通过 Responses 协议提供的任意模型,不限定 OpenAI 模型。
|
|
10
|
+
- 不支持 Chat Completions、Anthropic Messages、WebSocket、普通 JSON 响应。
|
|
11
|
+
- 不修改 DSH/pi-ai 文件、模型请求参数、上游 baseURL 或重试策略。
|
|
12
|
+
|
|
13
|
+
## 安装与配置
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm ci --ignore-scripts
|
|
17
|
+
npm run check
|
|
18
|
+
npm pack --ignore-scripts
|
|
19
|
+
# 将生成的 tgz 路径交给 DSH 原生管理器:
|
|
20
|
+
dsh plugin --profile web add /absolute/path/dsh-response-effort-0.2.0.tgz --ignore-scripts
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
bundle 默认 `enabled: false`、`targets: []`。安装后还需要在本插件配置中打开观测并明确白名单,例如:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
- id: response-effort
|
|
27
|
+
name: dsh-response-effort
|
|
28
|
+
config:
|
|
29
|
+
enabled: true
|
|
30
|
+
targets:
|
|
31
|
+
- provider: cpa
|
|
32
|
+
url: http://localhost:8317/v1/responses
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`url` 必须替换为该 provider 实际使用的完整 Responses 地址,不是仅填写 baseURL。允许 HTTP/HTTPS,禁止凭据、query、fragment;provider、POST 方法、请求 URL、响应 MIME 与最终响应 URL 必须匹配。变更端点后要同步白名单;未匹配不会被误标为“未返回”。
|
|
36
|
+
|
|
37
|
+
用原生插件管理器配置、禁用或移除本插件。**是否立即生效以管理器的 application 结果为准**;如果返回 `restart-required`,需要操作者重启 DSH,而不是只刷新页面。不应通过改模型协议来使插件命中。
|
|
38
|
+
|
|
39
|
+
0.2.0 的 Remote 快照增加必需的 `responses` 数组,Host/Client 必须一起升级;不支持新旧版本混用。插件重载会清空观测内存;没有历史数据回填。
|
|
40
|
+
|
|
41
|
+
## 输入框上方:逐次响应
|
|
42
|
+
|
|
43
|
+
原生位置为 `conversation.input.dock`,追加在待办、目标和队列之后,不替换原生内容。
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
最近响应:effort: high · 响应 #28 查看记录 ▾
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- 每条代表一次 SSE 请求的观测结果,不是其中每个 token 事件。
|
|
50
|
+
- 解析到合法终态后立即发布,**不等待消息提交或整轮任务完成**。若服务器只在终态返回 effort,就不能在请求刚开始时知道它。
|
|
51
|
+
- 摘要始终称“最近响应”,不是当前请求的设置。只有当前会话存在观测记录时显示;连接中、无记录、断线或订阅失败时完全隐藏,不占位。已捕获但未返回字段或无法确认的记录仍可查看。记录保留期间不因本轮结束而隐藏。
|
|
52
|
+
- 卡片采用与 goal 同类的紧凑行高、内缩宽度与主题配色;点击整行展开,清空后再次出现时恢复折叠。
|
|
53
|
+
- 默认折叠。展开按最近完成顺序查看响应编号、完成时间、effort、终态、provider/model;滚动区高度有界,每次可多展开 20 条。
|
|
54
|
+
- 编号是该会话当前内存段的响应序号;记录全部清空或被淘汰后重新编号,**不是整轮请求总数**。
|
|
55
|
+
- 失败重试、没有形成最终消息的响应和同一 attempt 的多个请求分别收录;使用本地 capture ID,不以可能重复的上游 response ID 去重。
|
|
56
|
+
- 只显示能归属到当前 sessionId 的观测;没有 sessionId 的辅助调用不显示,其他会话不会混入。
|
|
57
|
+
|
|
58
|
+
| 观测结果 | 状态栏 |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| 合法终态返回非空字符串 effort | `effort: max` 等原值 |
|
|
61
|
+
| 合法终态缺失该字段或为 null | `effort: 未返回` |
|
|
62
|
+
| 已开始观测但无终态、格式错误、旁路超时/超限 | `无法确认`,可查看原因 |
|
|
63
|
+
| 未命中白名单、不支持的协议、未观测或并发限额跳过 | 不产生逐次记录 |
|
|
64
|
+
| 尚无保留记录、连接中或订阅不可用 | 完全隐藏,不占位 |
|
|
65
|
+
|
|
66
|
+
因此这是**有界观测记录,不是完整网络审计日志**。工具自身的 HTTP 请求不在模型请求作用域中,不会计入。
|
|
67
|
+
|
|
68
|
+
## 最终回复下方:消息标签
|
|
69
|
+
|
|
70
|
+
保留 `conversation.chat.assistant-actions` 原生插槽:整轮结束后,最后一条有正文的 assistant 回复下方显示标签,跟随原生 hover/显隐规则。
|
|
71
|
+
|
|
72
|
+
消息标签只查询自身 messageId。没有可靠归属、观测未知或缓存已淘汰时不显示;不取整轮最大值,不拿最近请求值补缺。请求 high、响应 max 时展示 max,绝不使用请求参数猜值。
|
|
73
|
+
|
|
74
|
+
## 内存与隐私边界
|
|
75
|
+
|
|
76
|
+
- 不保存原始 SSE、prompt、回复正文、认证头或凭据;不向会话日志添加 effort。
|
|
77
|
+
- 不使用 localStorage、IndexedDB 或磁盘缓存。
|
|
78
|
+
- 消息映射与逐次记录是两个独立有界内存池,状态栏与消息标签共享每会话一个原生 Remote 订阅。
|
|
79
|
+
- 刷新/切换会话可取得尚未淘汰的条目;后端重启、插件关闭/卸载后清空。generation 隔离旧状态。
|
|
80
|
+
- 原生 attempt 身份由 Agent 实例生命周期隔离,不依赖上游 response ID 必须存在。
|
|
81
|
+
|
|
82
|
+
默认 `limits`:
|
|
83
|
+
|
|
84
|
+
| 配置 | 默认值 |
|
|
85
|
+
| --- | ---: |
|
|
86
|
+
| maxConcurrent | 8 |
|
|
87
|
+
| maxResponseBytes | 16777216 |
|
|
88
|
+
| maxEventBytes | 1048576 |
|
|
89
|
+
| maxObserveMs | 600000 |
|
|
90
|
+
| maxEffortChars | 256 |
|
|
91
|
+
| pendingMs | 120000 |
|
|
92
|
+
| maxEntries | 2000 |
|
|
93
|
+
| maxSessionEntries | 200 |
|
|
94
|
+
| ttlMs | 21600000 |
|
|
95
|
+
|
|
96
|
+
`maxEntries`、`maxSessionEntries`、`ttlMs` **分别应用于两个池**,即默认最多 2000 条消息映射加 2000 条响应记录,每会话各最多 200 条,绝对 TTL 6 小时。访问不延长 TTL;长期任务会淘汰旧记录。慢订阅者只保留最新快照,不积累无限更新队列。
|
|
97
|
+
|
|
98
|
+
所有限额必须是正安全整数;maxObserveMs 不超过 2147483647,maxEffortChars 不超过 4096,maxSessionEntries 不超过 10000,超出时拒绝加载。读取限额/超时只停止旁路,不取消主模型响应。待关联超时从原生 attempt 结算后计算;attempt 记录另受总数量限制。
|
|
99
|
+
|
|
100
|
+
## 技术限制
|
|
101
|
+
|
|
102
|
+
这是运行时 fetch 包装,不是官方 raw-SSE hook。SDK 如果改用已缓存 fetch、自定义 transport 或 WebSocket,可能绕过插件。升级 DSH 时应重新验收。多个 fetch 包装器共存时,卸载只恢复自己仍拥有的全局指针;留在其他包装器调用链里的旧包装器变为透传。
|
|
103
|
+
|
|
104
|
+
Responses 的 `reasoning.summary` 本版不采集。`reasoning_tokens` 为 0 不能用来否认响应报告的 effort。
|
|
105
|
+
|
|
106
|
+
## npm 发布(维护者)
|
|
107
|
+
|
|
108
|
+
npm 包 `dsh-response-effort` 为公开包;GitHub 源仓库保持私有。公开包包含构建产物、声明文件及当前构建生成的 source maps,并不对这些内容保密。
|
|
109
|
+
|
|
110
|
+
[发布工作流](.github/workflows/publish.yml)使用 GitHub-hosted runner、Node 24 与 npm 11.19.0,通过 OIDC 发布,不需要 `NPM_TOKEN` / `NODE_AUTH_TOKEN` secret。私有源仓库不支持 npm provenance,因此明确关闭 provenance;这不影响 OIDC 认证。
|
|
111
|
+
|
|
112
|
+
首次发布需要维护者 `npm login --auth-type=web` 并手动发布当前版本,之后在 npm 包 Settings → Trusted Publisher 绑定:
|
|
113
|
+
|
|
114
|
+
- Provider:GitHub Actions
|
|
115
|
+
- Organization or user:`lolkda`
|
|
116
|
+
- Repository:`dsh-response-effort`
|
|
117
|
+
- Workflow filename:`publish.yml`(不是完整路径)
|
|
118
|
+
- Environment name:留空
|
|
119
|
+
- Allowed actions:启用直接 `npm publish`(仅允许 staged publish 不够)
|
|
120
|
+
|
|
121
|
+
新建的 Trusted Publisher 必须在两天内完成首次成功发布。后续稳定版本发布:
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
npm version patch --no-git-tag-version
|
|
125
|
+
# 同步本文兼容版本及安装示例后,运行完整检查并提交版本变化。
|
|
126
|
+
npm run check
|
|
127
|
+
git add package.json package-lock.json README.md
|
|
128
|
+
git commit -m "Release <version>"
|
|
129
|
+
git tag "v$(node -p 'require("./package.json").version')"
|
|
130
|
+
git push origin main
|
|
131
|
+
git push origin "v$(node -p 'require("./package.json").version')"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
只有 `vX.Y.Z` 标签与包版本及锁文件一致时才发布;不支持通过此工作流发布 prerelease。工作流重新安装锁定依赖、完整检查、打包并验证文件白名单后,发布刚检查过的 tarball。已存在版本不能覆盖,失败时不会自动改版本或回退到长期 token。
|
|
135
|
+
|
|
136
|
+
Actions 中手动运行 **Publish npm** 仅执行检查和打包,绝不发布;日常主分支推送不会触发 npm 发布。首次初始化流程为手动发布 0.2.1、绑定 Trusted Publisher、仅升级发布版本至 0.2.2 后运行一次真实 OIDC 发布。
|
|
137
|
+
|
|
138
|
+
## 开发与验证
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
npm run check
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
包含类型检查、Host/Client 构建、测试与笔记门禁。测试使用合成 SSE;包括真实 pi-ai/OpenAI SDK、生产 AgentLoop、原生 Gateway/ClientRemoteService/SlotRegistry,以及状态栏展开、逐次更新、隔离、淘汰、重载和断线清理。测试通过不等于真实页面已验证,部署状态另行记录。
|
|
145
|
+
|
|
146
|
+
Client 复用宿主 React,只通过原生插槽、主题令牌和 locale 服务接入;不导入 Harness Client 的运行时代码。Remote 仅暴露经原生 Session lookup 的只读内存快照流,未新增模型工具或独立网络服务器。
|
package/cordis.patch.yml
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({id:"dsh-response-effort",factory(require){const module={exports:{}};const exports=module.exports;
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name2 in all)
|
|
9
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/client/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
apply: () => apply,
|
|
25
|
+
inject: () => inject,
|
|
26
|
+
name: () => name
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/contracts.ts
|
|
31
|
+
var DEFAULT_LIMITS = Object.freeze({
|
|
32
|
+
maxConcurrent: 8,
|
|
33
|
+
maxResponseBytes: 16 * 1024 * 1024,
|
|
34
|
+
maxEventBytes: 1024 * 1024,
|
|
35
|
+
maxObserveMs: 10 * 6e4,
|
|
36
|
+
maxEffortChars: 256,
|
|
37
|
+
pendingMs: 2 * 6e4,
|
|
38
|
+
maxEntries: 2e3,
|
|
39
|
+
maxSessionEntries: 200,
|
|
40
|
+
ttlMs: 6 * 60 * 6e4
|
|
41
|
+
});
|
|
42
|
+
function record(value) {
|
|
43
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/remote-contract.ts
|
|
47
|
+
function boundedText(value, max = 1024) {
|
|
48
|
+
return typeof value === "string" && value.length > 0 && value.length <= max;
|
|
49
|
+
}
|
|
50
|
+
var reasons = /* @__PURE__ */ new Set(["invalid-event", "invalid-effort", "event-limit", "byte-limit", "timeout", "interrupted", "stream-ended", "read-error", "ambiguous", "unavailable"]);
|
|
51
|
+
function observation(value) {
|
|
52
|
+
const data = record(value);
|
|
53
|
+
if (!data) throw new TypeError("Invalid effort observation");
|
|
54
|
+
if (data.kind === "unknown" && typeof data.reason === "string" && reasons.has(data.reason)) return { kind: "unknown", reason: data.reason };
|
|
55
|
+
if (data.terminal !== "completed" && data.terminal !== "incomplete" && data.terminal !== "failed") throw new TypeError("Invalid effort terminal");
|
|
56
|
+
const extra = boundedText(data.responseId, 512) ? { responseId: data.responseId } : {};
|
|
57
|
+
if (data.kind === "absent") return { kind: "absent", terminal: data.terminal, ...extra };
|
|
58
|
+
if (data.kind === "observed" && typeof data.effort === "string" && [...data.effort].length <= 4096 && data.effort.trim()) return { kind: "observed", terminal: data.terminal, effort: data.effort, ...extra };
|
|
59
|
+
throw new TypeError("Invalid effort observation");
|
|
60
|
+
}
|
|
61
|
+
function decodeSnapshot(value) {
|
|
62
|
+
const data = record(value);
|
|
63
|
+
if (!data || !boundedText(data.generation) || !Number.isSafeInteger(data.revision) || data.revision < 0 || !Array.isArray(data.items) || data.items.length > 1e4) throw new TypeError("Invalid effort snapshot");
|
|
64
|
+
const seen = /* @__PURE__ */ new Set();
|
|
65
|
+
const items = data.items.map((value2) => {
|
|
66
|
+
const item = record(value2);
|
|
67
|
+
if (!item || !boundedText(item.messageId) || !boundedText(item.provider) || !boundedText(item.model) || !Number.isFinite(item.observedAt) || seen.has(item.messageId)) throw new TypeError("Invalid effort item");
|
|
68
|
+
seen.add(item.messageId);
|
|
69
|
+
return { messageId: item.messageId, provider: item.provider, model: item.model, observedAt: item.observedAt, result: observation(item.result) };
|
|
70
|
+
});
|
|
71
|
+
if (!Array.isArray(data.responses) || data.responses.length > 1e4) throw new TypeError("Invalid effort responses");
|
|
72
|
+
const captures = /* @__PURE__ */ new Set();
|
|
73
|
+
const sequences = /* @__PURE__ */ new Set();
|
|
74
|
+
const responses = data.responses.map((value2) => {
|
|
75
|
+
const item = record(value2);
|
|
76
|
+
if (!item || !boundedText(item.captureId) || !boundedText(item.provider) || !boundedText(item.model) || !Number.isFinite(item.observedAt) || Math.abs(item.observedAt) > 864e13 || !Number.isSafeInteger(item.sequence) || item.sequence < 1 || captures.has(item.captureId) || sequences.has(item.sequence)) throw new TypeError("Invalid effort response");
|
|
77
|
+
captures.add(item.captureId);
|
|
78
|
+
sequences.add(item.sequence);
|
|
79
|
+
return {
|
|
80
|
+
captureId: item.captureId,
|
|
81
|
+
sequence: item.sequence,
|
|
82
|
+
provider: item.provider,
|
|
83
|
+
model: item.model,
|
|
84
|
+
observedAt: item.observedAt,
|
|
85
|
+
result: observation(item.result)
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
return { generation: data.generation, revision: data.revision, items, responses };
|
|
89
|
+
}
|
|
90
|
+
var sessionId = {
|
|
91
|
+
mode: "strict",
|
|
92
|
+
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
93
|
+
create: () => ({ parse(value) {
|
|
94
|
+
if (!boundedText(value)) throw new TypeError("Expected Session ID");
|
|
95
|
+
return value;
|
|
96
|
+
} })
|
|
97
|
+
};
|
|
98
|
+
var REMOTE = {
|
|
99
|
+
package: "dsh-response-effort",
|
|
100
|
+
descriptors: [{
|
|
101
|
+
id: "dsh-response-effort#responseEffort/watch",
|
|
102
|
+
service: "responseEffort",
|
|
103
|
+
namespace: "responseEffort",
|
|
104
|
+
method: "watch",
|
|
105
|
+
mode: "stream",
|
|
106
|
+
invocation: { kind: "direct" },
|
|
107
|
+
parameters: [{ name: "session", wire: "sessionId", source: "lookup", lookup: "session", codec: sessionId }],
|
|
108
|
+
cancellation: { parameter: "signal" },
|
|
109
|
+
result: { mode: "strict", typeSymbol: "dsh-response-effort#Snapshot", create: () => ({ parse: decodeSnapshot }) }
|
|
110
|
+
}]
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/client/EffortDock.tsx
|
|
114
|
+
var import_react = require("react");
|
|
115
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
116
|
+
var buttonStyle = {
|
|
117
|
+
font: "inherit",
|
|
118
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
119
|
+
background: "transparent",
|
|
120
|
+
border: 0,
|
|
121
|
+
padding: "2px 4px",
|
|
122
|
+
cursor: "pointer",
|
|
123
|
+
borderRadius: 4,
|
|
124
|
+
flexShrink: 0
|
|
125
|
+
};
|
|
126
|
+
var clipped = { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 };
|
|
127
|
+
function resultText(result, t) {
|
|
128
|
+
return result.kind === "observed" ? `effort: ${result.effort}` : result.kind === "absent" ? `effort: ${t("absent")}` : t("unknown");
|
|
129
|
+
}
|
|
130
|
+
function EffortDock({ responseSource, t }) {
|
|
131
|
+
const feed = (0, import_react.useSyncExternalStore)(responseSource.subscribe, responseSource.getSnapshot, responseSource.getSnapshot);
|
|
132
|
+
if (feed.status !== "ready" || feed.items.length === 0) return null;
|
|
133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DockView, { feed, t }, feed.generation);
|
|
134
|
+
}
|
|
135
|
+
function DockView({ feed, t }) {
|
|
136
|
+
const [expanded, setExpanded] = (0, import_react.useState)(false);
|
|
137
|
+
const [visible, setVisible] = (0, import_react.useState)(20);
|
|
138
|
+
const historyId = (0, import_react.useId)();
|
|
139
|
+
const latest = feed.items[0];
|
|
140
|
+
if (!latest) return null;
|
|
141
|
+
const summary = `${t("recent")}\uFF1A${resultText(latest.result, t)} \xB7 ${t("response", { sequence: latest.sequence })}`;
|
|
142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "data-response-effort-dock": "", "aria-label": t("recent"), style: {
|
|
143
|
+
boxSizing: "border-box",
|
|
144
|
+
minWidth: 0,
|
|
145
|
+
margin: "0 auto",
|
|
146
|
+
width: "calc(100% - 2 * var(--dsh-composer-side-clearance, 16px) - 4 * var(--dsh-composer-dock-inset, 4px))",
|
|
147
|
+
maxWidth: "calc(var(--dsh-composer-card-max-width, 800px) - 4 * var(--dsh-composer-dock-inset, 4px))",
|
|
148
|
+
borderRadius: 12,
|
|
149
|
+
fontSize: 13,
|
|
150
|
+
lineHeight: "20px",
|
|
151
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
152
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
153
|
+
boxShadow: "0 0 0 1px var(--dsw-alias-border-l1), 0 2px 8px var(--dsw-alias-border-l1)"
|
|
154
|
+
}, children: [
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
156
|
+
"button",
|
|
157
|
+
{
|
|
158
|
+
type: "button",
|
|
159
|
+
"aria-expanded": expanded,
|
|
160
|
+
"aria-controls": historyId,
|
|
161
|
+
"aria-label": t(expanded ? "hide" : "view"),
|
|
162
|
+
title: `${summary}
|
|
163
|
+
${t("explanation")}`,
|
|
164
|
+
style: {
|
|
165
|
+
...buttonStyle,
|
|
166
|
+
boxSizing: "border-box",
|
|
167
|
+
display: "flex",
|
|
168
|
+
alignItems: "center",
|
|
169
|
+
gap: 10,
|
|
170
|
+
width: "100%",
|
|
171
|
+
height: 36,
|
|
172
|
+
padding: "4px 8px 4px 12px",
|
|
173
|
+
borderRadius: 12,
|
|
174
|
+
textAlign: "left"
|
|
175
|
+
},
|
|
176
|
+
onClick: () => setExpanded((value) => !value),
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 12h4l3-8 4 16 3-8h4" }) }),
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { role: "status", "aria-live": "polite", "aria-atomic": "true", style: { ...clipped, flex: 1, color: "var(--dsw-alias-label-primary)" }, children: summary }),
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { "aria-hidden": "true", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0, transform: expanded ? "rotate(180deg)" : void 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m8 10 4 4 4-4" }) })
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
),
|
|
184
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { id: historyId, style: { padding: "0 12px 8px" }, children: [
|
|
185
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { "aria-label": t("view"), style: { listStyle: "none", margin: "6px 0", padding: 0, maxHeight: 224, overflowY: "auto" }, children: feed.items.slice(0, visible).map((item) => {
|
|
186
|
+
const value = resultText(item.result, t);
|
|
187
|
+
const status = item.result.kind === "unknown" ? t("unknownHint", { reason: item.result.reason }) : t(item.result.terminal);
|
|
188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { "data-response-capture": item.captureId, style: { padding: "5px 0", borderTop: "1px solid var(--dsw-alias-border-l1)" }, children: [
|
|
189
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "baseline", flexWrap: "wrap" }, children: [
|
|
190
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("response", { sequence: item.sequence }) }),
|
|
191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", { dateTime: new Date(item.observedAt).toISOString(), title: new Date(item.observedAt).toLocaleString(), children: new Date(item.observedAt).toLocaleTimeString() }),
|
|
192
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: `${value}
|
|
193
|
+
${status}
|
|
194
|
+
${t("explanation")}`, style: { ...clipped, flex: "1 1 80px", color: "var(--dsw-alias-label-primary)" }, children: value }),
|
|
195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { title: status, children: item.result.kind === "unknown" ? t("unknown") : t(item.result.terminal) })
|
|
196
|
+
] }),
|
|
197
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { title: `${item.provider} / ${item.model}`, style: clipped, children: [
|
|
198
|
+
item.provider,
|
|
199
|
+
" / ",
|
|
200
|
+
item.model
|
|
201
|
+
] })
|
|
202
|
+
] }, item.captureId);
|
|
203
|
+
}) }),
|
|
204
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }, children: [
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("count", { shown: Math.min(visible, feed.items.length), total: feed.items.length }) }),
|
|
206
|
+
visible < feed.items.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", style: buttonStyle, onClick: () => setVisible((value) => value + 20), children: t("more") })
|
|
207
|
+
] }),
|
|
208
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { margin: "4px 0 0", fontSize: 11 }, children: t("retention") })
|
|
209
|
+
] })
|
|
210
|
+
] });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/client/locale.ts
|
|
214
|
+
var NAMESPACE = "response-effort";
|
|
215
|
+
var en = {
|
|
216
|
+
recent: "Latest response",
|
|
217
|
+
response: "Response #{sequence}",
|
|
218
|
+
view: "View records",
|
|
219
|
+
hide: "Hide records",
|
|
220
|
+
empty: "No SSE observations available",
|
|
221
|
+
connecting: "Connecting to SSE observations\u2026",
|
|
222
|
+
unavailable: "SSE observations unavailable",
|
|
223
|
+
absent: "Not returned",
|
|
224
|
+
unknown: "Unconfirmed",
|
|
225
|
+
more: "Show more",
|
|
226
|
+
count: "{shown} / {total} retained records",
|
|
227
|
+
explanation: "Server-reported reasoning.effort, not measured reasoning. Updated when each matching SSE observation finishes; not the current request setting.",
|
|
228
|
+
retention: "Memory only; old records expire or are evicted. Numbers restart when this session has no retained records. Not a whole-turn request count.",
|
|
229
|
+
unknownHint: "No confirmed effort: {reason}",
|
|
230
|
+
completed: "Completed",
|
|
231
|
+
incomplete: "Incomplete",
|
|
232
|
+
failed: "Failed"
|
|
233
|
+
};
|
|
234
|
+
var zh = {
|
|
235
|
+
recent: "\u6700\u8FD1\u54CD\u5E94",
|
|
236
|
+
response: "\u54CD\u5E94 #{sequence}",
|
|
237
|
+
view: "\u67E5\u770B\u8BB0\u5F55",
|
|
238
|
+
hide: "\u6536\u8D77\u8BB0\u5F55",
|
|
239
|
+
empty: "\u6682\u65E0\u53EF\u7528\u7684 SSE \u89C2\u6D4B",
|
|
240
|
+
connecting: "\u6B63\u5728\u8FDE\u63A5 SSE \u89C2\u6D4B\u2026",
|
|
241
|
+
unavailable: "SSE \u89C2\u6D4B\u6682\u4E0D\u53EF\u7528",
|
|
242
|
+
absent: "\u672A\u8FD4\u56DE",
|
|
243
|
+
unknown: "\u65E0\u6CD5\u786E\u8BA4",
|
|
244
|
+
more: "\u67E5\u770B\u66F4\u591A",
|
|
245
|
+
count: "\u5DF2\u663E\u793A {shown} / {total} \u6761\u4FDD\u7559\u8BB0\u5F55",
|
|
246
|
+
explanation: "\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684 reasoning.effort\uFF0C\u4E0D\u662F\u6D4B\u5F97\u7684\u5B9E\u9645\u63A8\u7406\u91CF\u3002\u6BCF\u6B21\u5339\u914D\u7684 SSE \u89C2\u6D4B\u7ED3\u675F\u540E\u66F4\u65B0\uFF0C\u4E0D\u4EE3\u8868\u5F53\u524D\u8BF7\u6C42\u8BBE\u7F6E\u3002",
|
|
247
|
+
retention: "\u4EC5\u4FDD\u5B58\u5728\u5185\u5B58\uFF1B\u65E7\u8BB0\u5F55\u4F1A\u8FC7\u671F\u6216\u6DD8\u6C70\u3002\u4F1A\u8BDD\u8BB0\u5F55\u5168\u90E8\u6E05\u7A7A\u540E\u91CD\u65B0\u7F16\u53F7\uFF0C\u4E0D\u662F\u6574\u8F6E\u8BF7\u6C42\u603B\u6570\u3002",
|
|
248
|
+
unknownHint: "\u65E0\u6CD5\u786E\u8BA4 effort\uFF1A{reason}",
|
|
249
|
+
completed: "\u5DF2\u5B8C\u6210",
|
|
250
|
+
incomplete: "\u672A\u5B8C\u6210",
|
|
251
|
+
failed: "\u5931\u8D25"
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// src/client/EffortBadge.tsx
|
|
255
|
+
var import_react2 = require("react");
|
|
256
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
257
|
+
function EffortBadge({ messageId, effortSource }) {
|
|
258
|
+
const items = (0, import_react2.useSyncExternalStore)(effortSource.subscribe, effortSource.getSnapshot, effortSource.getSnapshot);
|
|
259
|
+
const observation2 = items.get(messageId)?.result;
|
|
260
|
+
if (!observation2 || observation2.kind === "unknown") return null;
|
|
261
|
+
const value = observation2.kind === "observed" ? observation2.effort : "\u672A\u8FD4\u56DE";
|
|
262
|
+
const explanation = observation2.kind === "observed" ? `\u670D\u52A1\u7AEF\u54CD\u5E94\u8FD4\u56DE\u7684 reasoning.effort\uFF1A${value}\u3002\u4E0D\u662F\u6D4B\u5F97\u7684\u5B9E\u9645\u63A8\u7406\u91CF\u3002` : "\u5DF2\u6536\u5230\u5B8C\u6574\u7684 Responses \u7EC8\u6001\uFF0C\u4F46\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE reasoning.effort\u3002";
|
|
263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
264
|
+
"span",
|
|
265
|
+
{
|
|
266
|
+
"data-response-effort": observation2.kind,
|
|
267
|
+
title: explanation,
|
|
268
|
+
"aria-label": `effort: ${value}\uFF1B${explanation}`,
|
|
269
|
+
style: { display: "inline-block", maxWidth: "14em", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: "12px", lineHeight: "20px", color: "var(--dsw-alias-label-tertiary, currentColor)", padding: "0 4px", verticalAlign: "middle" },
|
|
270
|
+
children: [
|
|
271
|
+
"effort: ",
|
|
272
|
+
value
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/client/session-store.ts
|
|
279
|
+
var EMPTY = /* @__PURE__ */ new Map();
|
|
280
|
+
var CONNECTING = Object.freeze({ status: "connecting", items: Object.freeze([]) });
|
|
281
|
+
var UNAVAILABLE = Object.freeze({ status: "unavailable", items: Object.freeze([]) });
|
|
282
|
+
var EffortHub = class {
|
|
283
|
+
constructor(remote) {
|
|
284
|
+
this.remote = remote;
|
|
285
|
+
}
|
|
286
|
+
remote;
|
|
287
|
+
live = /* @__PURE__ */ new Map();
|
|
288
|
+
disposed = false;
|
|
289
|
+
source(sessionId2) {
|
|
290
|
+
return { getSnapshot: () => this.live.get(sessionId2)?.items ?? EMPTY, subscribe: (listener) => this.subscribe(sessionId2, listener) };
|
|
291
|
+
}
|
|
292
|
+
responseSource(sessionId2) {
|
|
293
|
+
return { getSnapshot: () => this.live.get(sessionId2)?.responses ?? (this.disposed ? UNAVAILABLE : CONNECTING), subscribe: (listener) => this.subscribe(sessionId2, listener) };
|
|
294
|
+
}
|
|
295
|
+
subscribe(sessionId2, listener) {
|
|
296
|
+
if (this.disposed) return () => {
|
|
297
|
+
};
|
|
298
|
+
let state = this.live.get(sessionId2);
|
|
299
|
+
const first = state === void 0;
|
|
300
|
+
if (!state) {
|
|
301
|
+
state = { items: EMPTY, responses: CONNECTING, generation: void 0, revision: -1, listeners: /* @__PURE__ */ new Set() };
|
|
302
|
+
this.live.set(sessionId2, state);
|
|
303
|
+
}
|
|
304
|
+
const notify = () => listener();
|
|
305
|
+
state.listeners.add(notify);
|
|
306
|
+
if (first) this.open(sessionId2, state);
|
|
307
|
+
const owned = state;
|
|
308
|
+
return () => {
|
|
309
|
+
owned.listeners.delete(notify);
|
|
310
|
+
if (owned.listeners.size === 0 && this.live.get(sessionId2) === owned) {
|
|
311
|
+
this.live.delete(sessionId2);
|
|
312
|
+
void owned.stream?.dispose().catch(() => {
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
open(sessionId2, state) {
|
|
318
|
+
const reset = () => {
|
|
319
|
+
state.items = EMPTY;
|
|
320
|
+
state.responses = UNAVAILABLE;
|
|
321
|
+
state.generation = void 0;
|
|
322
|
+
state.revision = -1;
|
|
323
|
+
for (const notify of state.listeners) notify();
|
|
324
|
+
};
|
|
325
|
+
let stream;
|
|
326
|
+
try {
|
|
327
|
+
stream = this.remote.$stream({
|
|
328
|
+
name: "response-effort",
|
|
329
|
+
open: (signal) => this.remote.responseEffort.watch(sessionId2, signal),
|
|
330
|
+
ended: () => new Error("response-effort observation stream ended"),
|
|
331
|
+
carrierFailed: reset
|
|
332
|
+
});
|
|
333
|
+
} catch {
|
|
334
|
+
reset();
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
state.stream = stream;
|
|
338
|
+
const consume = async () => {
|
|
339
|
+
try {
|
|
340
|
+
for await (const frame of stream) {
|
|
341
|
+
if (this.disposed || this.live.get(sessionId2) !== state) return;
|
|
342
|
+
const snapshot = decodeSnapshot(frame.value);
|
|
343
|
+
if (snapshot.generation !== state.generation || snapshot.revision >= state.revision) {
|
|
344
|
+
state.generation = snapshot.generation;
|
|
345
|
+
state.revision = snapshot.revision;
|
|
346
|
+
state.items = new Map(snapshot.items.map((item) => [item.messageId, item]));
|
|
347
|
+
state.responses = { status: "ready", generation: snapshot.generation, items: [...snapshot.responses].sort((a, b) => b.sequence - a.sequence) };
|
|
348
|
+
for (const notify of state.listeners) notify();
|
|
349
|
+
}
|
|
350
|
+
frame.accept();
|
|
351
|
+
}
|
|
352
|
+
} catch {
|
|
353
|
+
if (this.live.get(sessionId2) === state) reset();
|
|
354
|
+
} finally {
|
|
355
|
+
if (this.live.get(sessionId2) === state) reset();
|
|
356
|
+
await stream.dispose().catch(() => {
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
void consume();
|
|
361
|
+
}
|
|
362
|
+
async dispose() {
|
|
363
|
+
this.disposed = true;
|
|
364
|
+
const states = [...this.live.values()];
|
|
365
|
+
this.live.clear();
|
|
366
|
+
for (const state of states) for (const notify of state.listeners) notify();
|
|
367
|
+
await Promise.allSettled(states.map((state) => state.stream?.dispose()));
|
|
368
|
+
}
|
|
369
|
+
get activeSessions() {
|
|
370
|
+
return this.live.size;
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// src/client/index.ts
|
|
375
|
+
var name = "response-effort-ui";
|
|
376
|
+
var inject = ["slots", "remote", "locale"];
|
|
377
|
+
function apply(ctx) {
|
|
378
|
+
ctx.effect(async function* () {
|
|
379
|
+
const locale = ctx.get("locale");
|
|
380
|
+
yield locale.register(NAMESPACE, "en", en);
|
|
381
|
+
yield locale.register(NAMESPACE, "zh", zh);
|
|
382
|
+
yield await ctx.remote.$mount(REMOTE);
|
|
383
|
+
const consumer = ctx.inject(["remote.responseEffort"], (scoped) => {
|
|
384
|
+
scoped.effect(async function* () {
|
|
385
|
+
const hub = new EffortHub(scoped.remote);
|
|
386
|
+
yield () => hub.dispose();
|
|
387
|
+
yield scoped.slots.inject("conversation.chat.assistant-actions", () => scoped.slots.register({
|
|
388
|
+
name: "conversation.chat.assistant-actions",
|
|
389
|
+
id: "response-effort",
|
|
390
|
+
order: 20,
|
|
391
|
+
inject: (sessionId2) => ({ effortSource: hub.source(String(sessionId2)) })
|
|
392
|
+
}, EffortBadge));
|
|
393
|
+
yield scoped.slots.inject("conversation.input.dock", () => scoped.slots.register({
|
|
394
|
+
name: "conversation.input.dock",
|
|
395
|
+
id: "response-effort",
|
|
396
|
+
order: 30,
|
|
397
|
+
locale: NAMESPACE,
|
|
398
|
+
inject: (sessionId2) => ({ responseSource: hub.responseSource(String(sessionId2)) })
|
|
399
|
+
}, EffortDock));
|
|
400
|
+
}, "response-effort: subscribed namespace");
|
|
401
|
+
});
|
|
402
|
+
yield () => consumer.dispose();
|
|
403
|
+
}, "response-effort: native action badge");
|
|
404
|
+
}
|
|
405
|
+
return module.exports;}});
|
|
406
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/client/index.ts", "../src/contracts.ts", "../src/remote-contract.ts", "../src/client/EffortDock.tsx", "../src/client/locale.ts", "../src/client/EffortBadge.tsx", "../src/client/session-store.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@deepseek-ai/cordis';\nimport type {} from '@deepseek-ai/dsh-client-ui-chat/client';\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client';\nimport type {} from '@deepseek-ai/dsh-api-gateway/client';\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client';\nimport { REMOTE } from '../remote-contract.ts';\nimport { EffortDock } from './EffortDock.tsx';\nimport { NAMESPACE, en, zh } from './locale.ts';\nimport type { LocaleRegistry } from './locale.ts';\nimport { EffortBadge } from './EffortBadge.tsx';\nimport { EffortHub } from './session-store.ts';\nimport type { EffortTransport } from './session-store.ts';\n\nexport const name = 'response-effort-ui';\nexport const inject = ['slots', 'remote', 'locale'];\nexport function apply(ctx: Context): void {\n ctx.effect(async function* () {\n const locale = ctx.get('locale') as LocaleRegistry;\n yield locale.register(NAMESPACE, 'en', en);\n yield locale.register(NAMESPACE, 'zh', zh);\n yield await ctx.remote.$mount(REMOTE);\n const consumer = ctx.inject(['remote.responseEffort'], scoped => {\n scoped.effect(async function* () {\n const hub = new EffortHub(scoped.remote as unknown as EffortTransport);\n yield () => hub.dispose();\n yield scoped.slots.inject('conversation.chat.assistant-actions', () => scoped.slots.register({\n name: 'conversation.chat.assistant-actions', id: 'response-effort', order: 20,\n inject: sessionId => ({ effortSource: hub.source(String(sessionId)) }),\n }, EffortBadge));\n yield scoped.slots.inject('conversation.input.dock', () => scoped.slots.register({\n name: 'conversation.input.dock', id: 'response-effort', order: 30, locale: NAMESPACE,\n inject: sessionId => ({ responseSource: hub.responseSource(String(sessionId)) }),\n }, EffortDock));\n }, 'response-effort: subscribed namespace');\n });\n yield () => consumer.dispose();\n }, 'response-effort: native action badge');\n}\n", "export type Terminal = 'completed' | 'incomplete' | 'failed';\nexport type UnknownReason = 'invalid-event' | 'invalid-effort' | 'event-limit' | 'byte-limit' | 'timeout' | 'interrupted' | 'stream-ended' | 'read-error' | 'ambiguous' | 'unavailable';\nexport type Observation =\n | { readonly kind: 'observed'; readonly effort: string; readonly terminal: Terminal; readonly responseId?: string }\n | { readonly kind: 'absent'; readonly terminal: Terminal; readonly responseId?: string }\n | { readonly kind: 'unknown'; readonly reason: UnknownReason };\n\nexport interface Target { readonly provider: string; readonly url: string }\nexport interface Limits {\n readonly maxConcurrent: number;\n readonly maxResponseBytes: number;\n readonly maxEventBytes: number;\n readonly maxObserveMs: number;\n readonly maxEffortChars: number;\n readonly pendingMs: number;\n readonly maxEntries: number;\n readonly maxSessionEntries: number;\n readonly ttlMs: number;\n}\nexport const DEFAULT_LIMITS: Limits = Object.freeze({\n maxConcurrent: 8, maxResponseBytes: 16 * 1024 * 1024, maxEventBytes: 1024 * 1024,\n maxObserveMs: 10 * 60_000, maxEffortChars: 256, pendingMs: 2 * 60_000,\n maxEntries: 2000, maxSessionEntries: 200, ttlMs: 6 * 60 * 60_000,\n});\nexport interface Settings { readonly enabled: boolean; readonly targets: readonly Target[]; readonly limits: Limits }\nexport interface EffortItem {\n readonly messageId: string;\n readonly provider: string;\n readonly model: string;\n readonly observedAt: number;\n readonly result: Observation;\n}\nexport interface ResponseItem {\n readonly captureId: string;\n readonly sequence: number;\n readonly provider: string;\n readonly model: string;\n readonly observedAt: number;\n readonly result: Observation;\n}\nexport interface Snapshot {\n readonly generation: string;\n readonly revision: number;\n readonly items: readonly EffortItem[];\n readonly responses: readonly ResponseItem[];\n}\nexport function record(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined;\n}\nexport function text(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n", "import type { TypertCodec, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';\nimport { record } from './contracts.ts';\nimport type { EffortItem, Observation, ResponseItem, Snapshot } from './contracts.ts';\n\nfunction boundedText(value: unknown, max = 1024): value is string { return typeof value === 'string' && value.length > 0 && value.length <= max; }\nconst reasons = new Set(['invalid-event', 'invalid-effort', 'event-limit', 'byte-limit', 'timeout', 'interrupted', 'stream-ended', 'read-error', 'ambiguous', 'unavailable']);\nfunction observation(value: unknown): Observation {\n const data = record(value);\n if (!data) throw new TypeError('Invalid effort observation');\n if (data.kind === 'unknown' && typeof data.reason === 'string' && reasons.has(data.reason)) return { kind: 'unknown', reason: data.reason as Extract<Observation, { kind: 'unknown' }>['reason'] };\n if (data.terminal !== 'completed' && data.terminal !== 'incomplete' && data.terminal !== 'failed') throw new TypeError('Invalid effort terminal');\n const extra = boundedText(data.responseId, 512) ? { responseId: data.responseId } : {};\n if (data.kind === 'absent') return { kind: 'absent', terminal: data.terminal, ...extra };\n if (data.kind === 'observed' && typeof data.effort === 'string' && [...data.effort].length <= 4096 && data.effort.trim()) return { kind: 'observed', terminal: data.terminal, effort: data.effort, ...extra };\n throw new TypeError('Invalid effort observation');\n}\nexport function decodeSnapshot(value: unknown): Snapshot {\n const data = record(value);\n if (!data || !boundedText(data.generation) || !Number.isSafeInteger(data.revision) || (data.revision as number) < 0 || !Array.isArray(data.items) || data.items.length > 10000) throw new TypeError('Invalid effort snapshot');\n const seen = new Set<string>();\n const items: EffortItem[] = data.items.map((value: unknown) => {\n const item = record(value);\n if (!item || !boundedText(item.messageId) || !boundedText(item.provider) || !boundedText(item.model) || !Number.isFinite(item.observedAt) || seen.has(item.messageId)) throw new TypeError('Invalid effort item');\n seen.add(item.messageId);\n return { messageId: item.messageId, provider: item.provider, model: item.model, observedAt: item.observedAt as number, result: observation(item.result) };\n });\n if (!Array.isArray(data.responses) || data.responses.length > 10000) throw new TypeError('Invalid effort responses');\n const captures = new Set<string>();\n const sequences = new Set<number>();\n const responses: ResponseItem[] = data.responses.map((value: unknown) => {\n const item = record(value);\n if (!item || !boundedText(item.captureId) || !boundedText(item.provider) || !boundedText(item.model)\n || !Number.isFinite(item.observedAt) || Math.abs(item.observedAt as number) > 8.64e15\n || !Number.isSafeInteger(item.sequence) || (item.sequence as number) < 1\n || captures.has(item.captureId) || sequences.has(item.sequence as number)) throw new TypeError('Invalid effort response');\n captures.add(item.captureId); sequences.add(item.sequence as number);\n return { captureId: item.captureId, sequence: item.sequence as number, provider: item.provider, model: item.model,\n observedAt: item.observedAt as number, result: observation(item.result) };\n });\n return { generation: data.generation, revision: data.revision as number, items, responses };\n}\nconst sessionId: TypertCodec = {\n mode: 'strict', typeSymbol: '@deepseek-ai/dsh-session/types#SessionId',\n create: () => ({ parse(value: unknown) { if (!boundedText(value)) throw new TypeError('Expected Session ID'); return value; } }),\n};\nexport const REMOTE: TypertRemoteContribution = {\n package: 'dsh-response-effort',\n descriptors: [{\n id: 'dsh-response-effort#responseEffort/watch', service: 'responseEffort', namespace: 'responseEffort', method: 'watch', mode: 'stream',\n invocation: { kind: 'direct' }, parameters: [{ name: 'session', wire: 'sessionId', source: 'lookup', lookup: 'session', codec: sessionId }],\n cancellation: { parameter: 'signal' },\n result: { mode: 'strict', typeSymbol: 'dsh-response-effort#Snapshot', create: () => ({ parse: decodeSnapshot }) },\n }],\n};\n", "import { useId, useState, useSyncExternalStore } from 'react';\nimport type { CSSProperties } from 'react';\nimport type { Observation } from '../contracts.ts';\nimport type { ResponseFeed, ResponseSource } from './session-store.ts';\nimport type { EffortTranslate } from './locale.ts';\n\nexport interface DockProps { readonly responseSource: ResponseSource; readonly t: EffortTranslate }\nconst buttonStyle: CSSProperties = {\n font: 'inherit', color: 'var(--dsw-alias-label-secondary)', background: 'transparent',\n border: 0, padding: '2px 4px', cursor: 'pointer', borderRadius: 4, flexShrink: 0,\n};\nconst clipped: CSSProperties = { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 };\nfunction resultText(result: Observation, t: EffortTranslate): string {\n return result.kind === 'observed' ? `effort: ${result.effort}` : result.kind === 'absent' ? `effort: ${t('absent')}` : t('unknown');\n}\nexport function EffortDock({ responseSource, t }: DockProps) {\n const feed = useSyncExternalStore(responseSource.subscribe, responseSource.getSnapshot, responseSource.getSnapshot);\n if (feed.status !== 'ready' || feed.items.length === 0) return null;\n return <DockView key={feed.generation} feed={feed} t={t} />;\n}\nfunction DockView({ feed, t }: { readonly feed: ResponseFeed; readonly t: EffortTranslate }) {\n const [expanded, setExpanded] = useState(false);\n const [visible, setVisible] = useState(20);\n const historyId = useId();\n const latest = feed.items[0];\n if (!latest) return null;\n const summary = `${t('recent')}\uFF1A${resultText(latest.result, t)} \u00B7 ${t('response', { sequence: latest.sequence })}`;\n return <section data-response-effort-dock=\"\" aria-label={t('recent')} style={{\n boxSizing: 'border-box', minWidth: 0, margin: '0 auto',\n width: 'calc(100% - 2 * var(--dsh-composer-side-clearance, 16px) - 4 * var(--dsh-composer-dock-inset, 4px))',\n maxWidth: 'calc(var(--dsh-composer-card-max-width, 800px) - 4 * var(--dsh-composer-dock-inset, 4px))',\n borderRadius: 12, fontSize: 13, lineHeight: '20px',\n color: 'var(--dsw-alias-label-secondary)', background: 'var(--dsw-alias-bg-layer-1)',\n boxShadow: '0 0 0 1px var(--dsw-alias-border-l1), 0 2px 8px var(--dsw-alias-border-l1)',\n }}>\n <button type=\"button\" aria-expanded={expanded} aria-controls={historyId}\n aria-label={t(expanded ? 'hide' : 'view')} title={`${summary}\\n${t('explanation')}`}\n style={{ ...buttonStyle, boxSizing: 'border-box', display: 'flex', alignItems: 'center', gap: 10,\n width: '100%', height: 36, padding: '4px 8px 4px 12px', borderRadius: 12, textAlign: 'left' }}\n onClick={() => setExpanded(value => !value)}>\n <svg aria-hidden=\"true\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ flexShrink: 0 }}>\n <path d=\"M3 12h4l3-8 4 16 3-8h4\" />\n </svg>\n <span role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" style={{ ...clipped, flex: 1, color: 'var(--dsw-alias-label-primary)' }}>{summary}</span>\n <svg aria-hidden=\"true\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ flexShrink: 0, transform: expanded ? 'rotate(180deg)' : undefined }}>\n <path d=\"m8 10 4 4 4-4\" />\n </svg>\n </button>\n {expanded && <div id={historyId} style={{ padding: '0 12px 8px' }}>\n <ol aria-label={t('view')} style={{ listStyle: 'none', margin: '6px 0', padding: 0, maxHeight: 224, overflowY: 'auto' }}>\n {feed.items.slice(0, visible).map(item => {\n const value = resultText(item.result, t);\n const status = item.result.kind === 'unknown' ? t('unknownHint', { reason: item.result.reason }) : t(item.result.terminal);\n return <li key={item.captureId} data-response-capture={item.captureId} style={{ padding: '5px 0', borderTop: '1px solid var(--dsw-alias-border-l1)' }}>\n <div style={{ display: 'flex', gap: 8, alignItems: 'baseline', flexWrap: 'wrap' }}>\n <span>{t('response', { sequence: item.sequence })}</span>\n <time dateTime={new Date(item.observedAt).toISOString()} title={new Date(item.observedAt).toLocaleString()}>{new Date(item.observedAt).toLocaleTimeString()}</time>\n <span title={`${value}\\n${status}\\n${t('explanation')}`} style={{ ...clipped, flex: '1 1 80px', color: 'var(--dsw-alias-label-primary)' }}>{value}</span>\n <span title={status}>{item.result.kind === 'unknown' ? t('unknown') : t(item.result.terminal)}</span>\n </div>\n <div title={`${item.provider} / ${item.model}`} style={clipped}>{item.provider} / {item.model}</div>\n </li>;\n })}\n </ol>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>\n <span>{t('count', { shown: Math.min(visible, feed.items.length), total: feed.items.length })}</span>\n {visible < feed.items.length && <button type=\"button\" style={buttonStyle} onClick={() => setVisible(value => value + 20)}>{t('more')}</button>}\n </div>\n <p style={{ margin: '4px 0 0', fontSize: 11 }}>{t('retention')}</p>\n </div>}\n </section>;\n}\n", "import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';\n\nexport const NAMESPACE = 'response-effort';\nexport const en = {\n recent: 'Latest response', response: 'Response #{sequence}', view: 'View records', hide: 'Hide records',\n empty: 'No SSE observations available', connecting: 'Connecting to SSE observations\u2026', unavailable: 'SSE observations unavailable',\n absent: 'Not returned', unknown: 'Unconfirmed', more: 'Show more', count: '{shown} / {total} retained records',\n explanation: 'Server-reported reasoning.effort, not measured reasoning. Updated when each matching SSE observation finishes; not the current request setting.',\n retention: 'Memory only; old records expire or are evicted. Numbers restart when this session has no retained records. Not a whole-turn request count.',\n unknownHint: 'No confirmed effort: {reason}', completed: 'Completed', incomplete: 'Incomplete', failed: 'Failed',\n};\nexport const zh: Record<keyof typeof en, string> = {\n recent: '\u6700\u8FD1\u54CD\u5E94', response: '\u54CD\u5E94 #{sequence}', view: '\u67E5\u770B\u8BB0\u5F55', hide: '\u6536\u8D77\u8BB0\u5F55',\n empty: '\u6682\u65E0\u53EF\u7528\u7684 SSE \u89C2\u6D4B', connecting: '\u6B63\u5728\u8FDE\u63A5 SSE \u89C2\u6D4B\u2026', unavailable: 'SSE \u89C2\u6D4B\u6682\u4E0D\u53EF\u7528',\n absent: '\u672A\u8FD4\u56DE', unknown: '\u65E0\u6CD5\u786E\u8BA4', more: '\u67E5\u770B\u66F4\u591A', count: '\u5DF2\u663E\u793A {shown} / {total} \u6761\u4FDD\u7559\u8BB0\u5F55',\n explanation: '\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684 reasoning.effort\uFF0C\u4E0D\u662F\u6D4B\u5F97\u7684\u5B9E\u9645\u63A8\u7406\u91CF\u3002\u6BCF\u6B21\u5339\u914D\u7684 SSE \u89C2\u6D4B\u7ED3\u675F\u540E\u66F4\u65B0\uFF0C\u4E0D\u4EE3\u8868\u5F53\u524D\u8BF7\u6C42\u8BBE\u7F6E\u3002',\n retention: '\u4EC5\u4FDD\u5B58\u5728\u5185\u5B58\uFF1B\u65E7\u8BB0\u5F55\u4F1A\u8FC7\u671F\u6216\u6DD8\u6C70\u3002\u4F1A\u8BDD\u8BB0\u5F55\u5168\u90E8\u6E05\u7A7A\u540E\u91CD\u65B0\u7F16\u53F7\uFF0C\u4E0D\u662F\u6574\u8F6E\u8BF7\u6C42\u603B\u6570\u3002',\n unknownHint: '\u65E0\u6CD5\u786E\u8BA4 effort\uFF1A{reason}', completed: '\u5DF2\u5B8C\u6210', incomplete: '\u672A\u5B8C\u6210', failed: '\u5931\u8D25',\n};\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap { 'response-effort': keyof typeof en }\n}\nexport type EffortTranslate = TranslateNS<typeof NAMESPACE>;\n/** The public dictionary-registration face; no Client implementation is bundled. */\nexport interface LocaleRegistry { register(namespace: string, locale: string, dictionary: Record<string, string>): () => void }\n", "import { useSyncExternalStore } from 'react';\nimport type { EffortSource } from './session-store.ts';\n\nexport interface BadgeProps { readonly messageId: string; readonly effortSource: EffortSource }\n/** Message-bound metadata only; never falls back to a request or another message. */\nexport function EffortBadge({ messageId, effortSource }: BadgeProps) {\n const items = useSyncExternalStore(effortSource.subscribe, effortSource.getSnapshot, effortSource.getSnapshot);\n const observation = items.get(messageId)?.result;\n if (!observation || observation.kind === 'unknown') return null;\n const value = observation.kind === 'observed' ? observation.effort : '\u672A\u8FD4\u56DE';\n const explanation = observation.kind === 'observed'\n ? `\u670D\u52A1\u7AEF\u54CD\u5E94\u8FD4\u56DE\u7684 reasoning.effort\uFF1A${value}\u3002\u4E0D\u662F\u6D4B\u5F97\u7684\u5B9E\u9645\u63A8\u7406\u91CF\u3002`\n : '\u5DF2\u6536\u5230\u5B8C\u6574\u7684 Responses \u7EC8\u6001\uFF0C\u4F46\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE reasoning.effort\u3002';\n return <span data-response-effort={observation.kind} title={explanation} aria-label={`effort: ${value}\uFF1B${explanation}`}\n style={{ display: 'inline-block', maxWidth: '14em', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontSize: '12px', lineHeight: '20px', color: 'var(--dsw-alias-label-tertiary, currentColor)', padding: '0 4px', verticalAlign: 'middle' }}>\n effort: {value}\n </span>;\n}\n", "import type { RemoteStreamItem, RemoteStreamOptions } from '@deepseek-ai/dsh-api-gateway/client';\nimport type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';\nimport type { EffortItem, ResponseItem, Snapshot } from '../contracts.ts';\nimport { decodeSnapshot } from '../remote-contract.ts';\n\nexport interface RemoteReader<Item> extends AsyncIterable<RemoteStreamItem<Item>> { dispose(): Promise<void> }\nexport interface EffortTransport {\n $mount(contribution: TypertRemoteContribution): Promise<() => Promise<void>>;\n $stream<Item>(options: RemoteStreamOptions<Item>): RemoteReader<Item>;\n responseEffort: { watch(sessionId: string, signal?: AbortSignal): AsyncIterable<Snapshot> };\n}\nexport interface Source<T> {\n getSnapshot(): T;\n subscribe(listener: () => void): () => void;\n}\nexport type EffortSource = Source<ReadonlyMap<string, EffortItem>>;\nexport interface ResponseFeed {\n readonly status: 'connecting' | 'ready' | 'unavailable';\n readonly generation?: string;\n readonly items: readonly ResponseItem[];\n}\nexport type ResponseSource = Source<ResponseFeed>;\nconst EMPTY: ReadonlyMap<string, EffortItem> = new Map();\nconst CONNECTING: ResponseFeed = Object.freeze({ status: 'connecting', items: Object.freeze([]) });\nconst UNAVAILABLE: ResponseFeed = Object.freeze({ status: 'unavailable', items: Object.freeze([]) });\ninterface LiveSession {\n items: ReadonlyMap<string, EffortItem>;\n responses: ResponseFeed;\n generation: string | undefined;\n revision: number;\n readonly listeners: Set<() => void>;\n stream?: RemoteReader<Snapshot>;\n}\n/** Badge and response dock share one native stream per actively rendered Session. */\nexport class EffortHub {\n private live = new Map<string, LiveSession>();\n private disposed = false;\n constructor(private readonly remote: EffortTransport) {}\n source(sessionId: string): EffortSource {\n return { getSnapshot: () => this.live.get(sessionId)?.items ?? EMPTY, subscribe: listener => this.subscribe(sessionId, listener) };\n }\n responseSource(sessionId: string): ResponseSource {\n return { getSnapshot: () => this.live.get(sessionId)?.responses ?? (this.disposed ? UNAVAILABLE : CONNECTING), subscribe: listener => this.subscribe(sessionId, listener) };\n }\n private subscribe(sessionId: string, listener: () => void): () => void {\n if (this.disposed) return () => {};\n let state = this.live.get(sessionId);\n const first = state === undefined;\n if (!state) { state = { items: EMPTY, responses: CONNECTING, generation: undefined, revision: -1, listeners: new Set() }; this.live.set(sessionId, state); }\n const notify = () => listener();\n state.listeners.add(notify);\n if (first) this.open(sessionId, state);\n const owned = state;\n return () => {\n owned.listeners.delete(notify);\n if (owned.listeners.size === 0 && this.live.get(sessionId) === owned) {\n this.live.delete(sessionId);\n void owned.stream?.dispose().catch(() => {});\n }\n };\n }\n private open(sessionId: string, state: LiveSession): void {\n const reset = () => {\n state.items = EMPTY; state.responses = UNAVAILABLE; state.generation = undefined; state.revision = -1;\n for (const notify of state.listeners) notify();\n };\n let stream: RemoteReader<Snapshot>;\n try {\n stream = this.remote.$stream<Snapshot>({\n name: 'response-effort', open: signal => this.remote.responseEffort.watch(sessionId, signal),\n ended: () => new Error('response-effort observation stream ended'), carrierFailed: reset,\n });\n } catch { reset(); return; }\n state.stream = stream;\n const consume = async () => {\n try {\n for await (const frame of stream) {\n if (this.disposed || this.live.get(sessionId) !== state) return;\n const snapshot = decodeSnapshot(frame.value);\n if (snapshot.generation !== state.generation || snapshot.revision >= state.revision) {\n state.generation = snapshot.generation; state.revision = snapshot.revision;\n state.items = new Map(snapshot.items.map(item => [item.messageId, item]));\n state.responses = { status: 'ready', generation: snapshot.generation, items: [...snapshot.responses].sort((a, b) => b.sequence - a.sequence) };\n for (const notify of state.listeners) notify();\n }\n frame.accept();\n }\n } catch { if (this.live.get(sessionId) === state) reset(); }\n finally {\n if (this.live.get(sessionId) === state) reset();\n await stream.dispose().catch(() => {});\n }\n };\n void consume();\n }\n async dispose(): Promise<void> {\n this.disposed = true;\n const states = [...this.live.values()];\n this.live.clear();\n for (const state of states) for (const notify of state.listeners) notify();\n await Promise.allSettled(states.map(state => state.stream?.dispose()));\n }\n get activeSessions(): number { return this.live.size; }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["value", "import_react", "import_jsx_runtime", "observation", "sessionId", "sessionId"]
|
|
7
|
+
}
|