dsh-lcx-codex 0.4.3-pre.12 → 0.4.3-pre.3
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 +17 -19
- package/lib/dsh-responses.js +2 -9
- package/lib/grok-native-search.js +75 -12
- package/lib/index.js +5 -11
- package/lib/responses-stream.js +77 -117
- package/lib/types/grok-native-search.d.ts +7 -2
- package/package.json +18 -22
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
**为 DeepSeek Harness 中的 GPT 提供 Responses 生命周期能力,并为 Grok 接入原生 Web / X Search。**
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/dsh-lcx-codex)
|
|
10
|
-
[](#安装)
|
|
11
11
|
[](LICENSE)
|
|
12
12
|
|
|
13
13
|
**简体中文** · [English](README_EN.md) · [更新日志](CHANGELOG.md) · [问题反馈](https://github.com/kk3ya03-star/dsh-lcx-codex/issues)
|
|
@@ -20,20 +20,18 @@ LCX Codex 是 [DeepSeek Harness](https://github.com/deepseek-ai/DeepSeek-Harness
|
|
|
20
20
|
|
|
21
21
|
## 安装
|
|
22
22
|
|
|
23
|
-
本页对应 **`0.4.3-pre.
|
|
23
|
+
本页对应 **`0.4.3-pre.3` 预发布版**,适配 **DSH `0.1.3-alpha.2`**。稳定版仍为 `0.4.2`,使用旧版 DSH `0.1.1-rc.2` 的用户请看[稳定版说明](https://github.com/kk3ya03-star/dsh-lcx-codex/blob/v0.4.2/README.md)。
|
|
24
24
|
|
|
25
|
-
安装前,请确认 DSH
|
|
25
|
+
安装前,请确认 DSH Web 能正常启动,并已配置需要使用的 GPT Responses 或 Grok Responses API 路由。Node.js 要求 `^22.19.0 || >=24.0.0`;Windows 启动出现 `fs-ext` 报错时,先看下方[故障排查](#故障排查)。
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
|
-
dsh plugin --profile web add dsh-lcx-codex@0.4.3-pre.
|
|
28
|
+
dsh plugin --profile web add dsh-lcx-codex@0.4.3-pre.3
|
|
29
29
|
dsh web
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
以后升级预发布版,可执行 `dsh plugin --profile web add dsh-lcx-codex@prelatest`。不带版本或标签安装会得到稳定版,**不是本页介绍的新版本**。
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
DSH 持久化层重新打开同一个已保存 session 时,LCX 可以恢复该 session 内保存的 v5 checkpoint;这只是 DSH session persistence 上的继续对话,**不是 Codex rollout/checkpoint 的进程级 restart/resume 机制**。
|
|
34
|
+
**从 `0.4.2` 升级:** 旧插件配置和 v3/v4 压缩检查点不再兼容,请重新配置插件并新建会话。新版 v5 GPT 检查点仍支持重启续聊。
|
|
37
35
|
|
|
38
36
|
## 启用
|
|
39
37
|
|
|
@@ -77,7 +75,7 @@ Grok 使用 xAI Responses 的服务端工具,而不是把搜索包装成 DSH f
|
|
|
77
75
|
|
|
78
76
|
开启任意 Grok 原生搜索后,Grok 请求会移除 DSH `web_search`,避免重复搜索语义;`web_fetch`、`read` 及其他 DSH/MCP function tools 仍保持可用。原生搜索结果可以继续进入本地工具调用,再回到同一 Grok agentic workflow;插件会保存 xAI 必需的 provider-native replay state,但不会把服务端搜索伪装成 DSH 本地工具调用。
|
|
79
77
|
|
|
80
|
-
当前支持 **API Key / API Gateway** 路由;OAuth / SuperGrok / X Premium
|
|
78
|
+
当前支持 **API Key / API Gateway** 路由;OAuth / SuperGrok / X Premium 订阅登录不在本版范围内。搜索来源 URL 会尽量保留,但具体 citation 展示形式仍受上游兼容网关返回格式影响。
|
|
81
79
|
|
|
82
80
|
### GPT 搜索图片并显示
|
|
83
81
|
|
|
@@ -105,9 +103,9 @@ Alpha 需要单独开启,且接口通过能力探测后才会出现。目前
|
|
|
105
103
|
| `90%` 至 `95%` | 优先尝试远程原生压缩。 |
|
|
106
104
|
| 达到 `95%` | 允许 DSH 紧急裁剪工具结果,再按流程压缩。 |
|
|
107
105
|
|
|
108
|
-
也可以输入 `/compact` 手动压缩。这些阈值是固定策略,不需要额外设置;实际能否压缩取决于是否有可压缩的历史以及接口支持情况。
|
|
106
|
+
也可以输入 `/compact` 手动压缩。这些阈值是固定策略,不需要额外设置;实际能否压缩取决于是否有可压缩的历史以及接口支持情况。
|
|
109
107
|
|
|
110
|
-
|
|
108
|
+
压缩后可以继续对话、重启恢复或切换 GPT 模型。遇到不兼容的模型或接口配置时,插件改用可迁移的历史,不会强行复用原生状态。首次建立检查点时,部分可恢复失败可以回退到 DSH 基础压缩;并非所有失败都会回退。
|
|
111
109
|
|
|
112
110
|
## 缓存
|
|
113
111
|
|
|
@@ -120,9 +118,11 @@ Pi `0.85.1` 的显式缓存模式支持 `30m` 长保留参数;`cacheRetention=
|
|
|
120
118
|
|
|
121
119
|
## 故障排查
|
|
122
120
|
|
|
123
|
-
|
|
121
|
+
**DSH 在 Windows 启动时报 `fs-ext` 错误?**
|
|
122
|
+
|
|
123
|
+
DSH `0.1.3-alpha.2` 会在启动时加载 `fs-ext`,即使 Windows 实际不使用它。当它的原生模块不可用时,DSH 会在启动阶段退出。这是 **DSH 的依赖加载问题,不是插件压缩或会话锁损坏**。
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
本版 Windows 实测使用了一个最小 DSH 修正:仅在非 Windows 平台加载 `fs-ext`,保留原有 Win32 会话锁。插件不会自动修改 DSH;未经该修正的 Windows 环境不保证能启动。不要用关闭会话锁来绕过问题。
|
|
126
126
|
|
|
127
127
|
**安装后没有变化?**
|
|
128
128
|
|
|
@@ -134,20 +134,18 @@ Pi `0.85.1` 的显式缓存模式支持 `30m` 长保留参数;`cacheRetention=
|
|
|
134
134
|
|
|
135
135
|
## 版本与验证范围
|
|
136
136
|
|
|
137
|
-
本版使用 DSH `0.1.
|
|
138
|
-
|
|
139
|
-
发布候选已通过 **246/246 PASS**、strict host/client typecheck 与 DSH schema 校验。真实 DSH `0.1.5-alpha.1` 隔离运行已验证:Web 启动、headless GPT 普通请求、Session V3 `system/message`、Native V2 `/compact`、compact 后同 session continuation,以及 v5 checkpoint 的 session identity 绑定。
|
|
137
|
+
本版使用 DSH `0.1.3-alpha.2`、DSH host Pi `0.85.1` 和插件 Pi `0.85.1`。插件单独声明 Pi 依赖,不替换 DSH 的依赖。
|
|
140
138
|
|
|
141
|
-
|
|
139
|
+
发布前完整测试为 **237/237 PASS**,strict host/client typecheck 与 4 个 DSH schema 均通过。真实运行覆盖 GPT Hosted/Native V2 回归、DeepSeek 原生 DSH 搜索回归,以及 Grok 4.5/4.6 原生 Web/X Search、Web/X → 本地 `read` → continuation、provider-native replay、完整 DSH 重启后的续聊、Grok 父/子代理 session/cache 隔离。GPT 已验证的父 cache-sharing 策略保持不变。
|
|
142
140
|
|
|
143
|
-
仍需保留的预发布限制:Alpha 引用及 screenshot 展示、代理/NO_PROXY、更广的并发/取消和后台 continuable subagent 矩阵仍未全面覆盖;Grok OAuth
|
|
141
|
+
仍需保留的预发布限制:Windows DSH `0.1.3-alpha.2` 的 `fs-ext` 启动问题需要文档中的最小 host loading 修正;Alpha 引用及 screenshot 展示、代理/NO_PROXY、更广的并发/取消和后台 continuable subagent 矩阵仍未全面覆盖;Grok OAuth 不支持,citation 渲染仍可能受上游网关格式影响。详细变更见 [v0.4.3-pre.3 发布说明](https://github.com/kk3ya03-star/dsh-lcx-codex/releases/tag/v0.4.3-pre.3)。
|
|
144
142
|
|
|
145
143
|
## 开发与反馈
|
|
146
144
|
|
|
147
145
|
```sh
|
|
148
146
|
npm ci --ignore-scripts
|
|
149
|
-
npm ci --prefix scripts/runtime-
|
|
150
|
-
node scripts/link-dsh-runtime.mjs scripts/runtime-
|
|
147
|
+
npm ci --prefix scripts/runtime-alpha2 --ignore-scripts
|
|
148
|
+
node scripts/link-dsh-runtime.mjs scripts/runtime-alpha2
|
|
151
149
|
node scripts/check-generated.mjs
|
|
152
150
|
npm run typecheck
|
|
153
151
|
npm test
|
package/lib/dsh-responses.js
CHANGED
|
@@ -93,7 +93,7 @@ function attachmentResolver(ctx, options) {
|
|
|
93
93
|
const attachments = attachmentServices(ctx?.attachments);
|
|
94
94
|
return async (block, signal) => {
|
|
95
95
|
if (attachments === undefined)
|
|
96
|
-
throw error("LCX requires the DSH request-image attachment API", "LCX_COMPACT_IMAGE_API_UNAVAILABLE");
|
|
96
|
+
throw error("LCX requires the DSH 0.1.3 request-image attachment API", "LCX_COMPACT_IMAGE_API_UNAVAILABLE");
|
|
97
97
|
const request = await attachments.store.readImageRequest(block.attachment, { maxPixels: options.requestImagePixelBudget, maxBytes: options.requestImageMaxBytes }, signal);
|
|
98
98
|
const data = request.data;
|
|
99
99
|
const mediaType = request.mediaType ?? block.attachment.mediaType;
|
|
@@ -280,18 +280,11 @@ function projectFiles(messages, ctx) {
|
|
|
280
280
|
content: projectFileContent(message.content, fileRequestText),
|
|
281
281
|
}));
|
|
282
282
|
}
|
|
283
|
-
function flattenMessageText(message) {
|
|
284
|
-
return message.content
|
|
285
|
-
.map((block) => (block.type === "text" ? block.text : ""))
|
|
286
|
-
.join("");
|
|
287
|
-
}
|
|
288
283
|
async function dshToPiMessages(messages, ctx, options, imageMap) {
|
|
289
284
|
const result = [];
|
|
290
285
|
for (const message of messages) {
|
|
291
|
-
if (message.role === "system")
|
|
292
|
-
result.push({ role: "user", content: flattenMessageText(message), timestamp: 0 });
|
|
286
|
+
if (message.role === "system")
|
|
293
287
|
continue;
|
|
294
|
-
}
|
|
295
288
|
if (message.role === "assistant") {
|
|
296
289
|
result.push(toPiAssistant(message, options.onReplayDegrade));
|
|
297
290
|
continue;
|
|
@@ -75,10 +75,37 @@ function validVisibleItem(item) {
|
|
|
75
75
|
typeof item.name === "string" && typeof item.input === "string";
|
|
76
76
|
return false;
|
|
77
77
|
}
|
|
78
|
+
function textSha256(text) {
|
|
79
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
80
|
+
}
|
|
81
|
+
function lcxCitationAddition(item) {
|
|
82
|
+
if (item.type !== "message" ||
|
|
83
|
+
typeof item.id !== "string" ||
|
|
84
|
+
!item.id.startsWith("msg_lcx_sources_"))
|
|
85
|
+
return undefined;
|
|
86
|
+
const text = itemText(item);
|
|
87
|
+
return text.startsWith("\n\nSources:\n")
|
|
88
|
+
? { kind: "citation-sources", textSha256: textSha256(text) }
|
|
89
|
+
: undefined;
|
|
90
|
+
}
|
|
91
|
+
function validVisibleAdditions(value) {
|
|
92
|
+
if (!Array.isArray(value) || value.length > GROK_NATIVE_REPLAY_MAX_ITEMS)
|
|
93
|
+
return undefined;
|
|
94
|
+
const additions = [];
|
|
95
|
+
for (const candidate of value) {
|
|
96
|
+
if (!isRecord(candidate) ||
|
|
97
|
+
candidate.kind !== "citation-sources" ||
|
|
98
|
+
typeof candidate.textSha256 !== "string" ||
|
|
99
|
+
!/^[0-9a-f]{64}$/u.test(candidate.textSha256))
|
|
100
|
+
return undefined;
|
|
101
|
+
additions.push({ kind: "citation-sources", textSha256: candidate.textSha256 });
|
|
102
|
+
}
|
|
103
|
+
return additions;
|
|
104
|
+
}
|
|
78
105
|
function readGrokNativeReplayEnvelope(value, route) {
|
|
79
106
|
if (!isRecord(value) ||
|
|
80
107
|
value.kind !== "xai-responses-native-search" ||
|
|
81
|
-
value.version !==
|
|
108
|
+
(value.version !== 1 && value.version !== 2))
|
|
82
109
|
return undefined;
|
|
83
110
|
if (value.provider !== route.provider ||
|
|
84
111
|
value.model !== route.model ||
|
|
@@ -100,10 +127,16 @@ function readGrokNativeReplayEnvelope(value, route) {
|
|
|
100
127
|
const output = [];
|
|
101
128
|
const itemKinds = new Map();
|
|
102
129
|
const callIds = new Set();
|
|
130
|
+
const migratedAdditions = [];
|
|
103
131
|
for (const candidate of value.output) {
|
|
104
132
|
if (!isRecord(candidate) || typeof candidate.type !== "string")
|
|
105
133
|
return undefined;
|
|
106
134
|
const item = candidate;
|
|
135
|
+
const legacyAddition = value.version === 1 ? lcxCitationAddition(item) : undefined;
|
|
136
|
+
if (legacyAddition) {
|
|
137
|
+
migratedAdditions.push(legacyAddition);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
107
140
|
if (GROK_NATIVE_SERVER_TOOL_TYPES.has(item.type)) {
|
|
108
141
|
if (typeof item.id !== "string" || item.id.length === 0)
|
|
109
142
|
return undefined;
|
|
@@ -130,27 +163,39 @@ function readGrokNativeReplayEnvelope(value, route) {
|
|
|
130
163
|
}
|
|
131
164
|
if (output.length === 0)
|
|
132
165
|
return undefined;
|
|
166
|
+
const visibleAdditions = value.version === 1
|
|
167
|
+
? migratedAdditions
|
|
168
|
+
: validVisibleAdditions(value.visibleAdditions);
|
|
169
|
+
if (!visibleAdditions)
|
|
170
|
+
return undefined;
|
|
133
171
|
return {
|
|
134
172
|
kind: "xai-responses-native-search",
|
|
135
|
-
version:
|
|
173
|
+
version: 2,
|
|
136
174
|
provider: route.provider,
|
|
137
175
|
model: route.model,
|
|
138
176
|
sourceSessionId: route.sessionId,
|
|
139
177
|
routeAuthorityFingerprint: grokNativeReplayRouteFingerprint(route),
|
|
140
178
|
output,
|
|
179
|
+
visibleAdditions,
|
|
141
180
|
};
|
|
142
181
|
}
|
|
143
|
-
export function createGrokNativeReplayEnvelope(output, route) {
|
|
182
|
+
export function createGrokNativeReplayEnvelope(output, route, visibleAdditions = []) {
|
|
144
183
|
if (!route || !Array.isArray(output))
|
|
145
184
|
return undefined;
|
|
185
|
+
const additions = visibleAdditions.map((candidate) => isRecord(candidate) && typeof candidate.type === "string"
|
|
186
|
+
? lcxCitationAddition(candidate)
|
|
187
|
+
: undefined);
|
|
188
|
+
if (additions.some((addition) => addition === undefined))
|
|
189
|
+
return undefined;
|
|
146
190
|
return readGrokNativeReplayEnvelope({
|
|
147
191
|
kind: "xai-responses-native-search",
|
|
148
|
-
version:
|
|
192
|
+
version: 2,
|
|
149
193
|
provider: route.provider,
|
|
150
194
|
model: route.model,
|
|
151
195
|
sourceSessionId: route.sessionId,
|
|
152
196
|
routeAuthorityFingerprint: grokNativeReplayRouteFingerprint(route),
|
|
153
197
|
output,
|
|
198
|
+
visibleAdditions: additions,
|
|
154
199
|
}, route);
|
|
155
200
|
}
|
|
156
201
|
function itemText(item) {
|
|
@@ -188,6 +233,19 @@ function visibleItemMatchesInput(item, candidate) {
|
|
|
188
233
|
return candidate.call_id === item.call_id;
|
|
189
234
|
return true;
|
|
190
235
|
}
|
|
236
|
+
function additionMatchesBlock(addition, candidate) {
|
|
237
|
+
return isRecord(candidate) && candidate.type === "text" &&
|
|
238
|
+
typeof candidate.text === "string" &&
|
|
239
|
+
candidate.text.startsWith("\n\nSources:\n") &&
|
|
240
|
+
textSha256(candidate.text) === addition.textSha256;
|
|
241
|
+
}
|
|
242
|
+
function additionMatchesInput(addition, candidate) {
|
|
243
|
+
if (!isRecord(candidate) || candidate.type !== "message")
|
|
244
|
+
return false;
|
|
245
|
+
if (typeof candidate.id !== "string" || !candidate.id.startsWith("msg_lcx_sources_"))
|
|
246
|
+
return false;
|
|
247
|
+
return textSha256(itemText(candidate)) === addition.textSha256;
|
|
248
|
+
}
|
|
191
249
|
function replayForMessage(message, route) {
|
|
192
250
|
if (message.role !== "assistant" || message.source.kind !== "model")
|
|
193
251
|
return undefined;
|
|
@@ -214,18 +272,22 @@ function replayForMessage(message, route) {
|
|
|
214
272
|
anchors.push(item);
|
|
215
273
|
blockIndex += 1;
|
|
216
274
|
}
|
|
217
|
-
else if (!(item.type === "reasoning" &&
|
|
218
|
-
(!itemText(item).trim() || (reasoningCounts.get(String(item.id)) ?? 0) > 1))) {
|
|
275
|
+
else if (!(item.type === "reasoning" && (reasoningCounts.get(String(item.id)) ?? 0) > 1)) {
|
|
219
276
|
return undefined;
|
|
220
277
|
}
|
|
221
278
|
}
|
|
222
|
-
//
|
|
223
|
-
//
|
|
279
|
+
// Pi can coalesce repeated reasoning IDs in terminal-only gateway responses.
|
|
280
|
+
// Match every provider-visible DSH block and only the hashed LCX additions.
|
|
224
281
|
if (anchors.length === 0)
|
|
225
282
|
return undefined;
|
|
283
|
+
for (const addition of envelope.visibleAdditions) {
|
|
284
|
+
if (!additionMatchesBlock(addition, message.content[blockIndex]))
|
|
285
|
+
return undefined;
|
|
286
|
+
blockIndex += 1;
|
|
287
|
+
}
|
|
226
288
|
if (blockIndex !== message.content.length)
|
|
227
289
|
return undefined;
|
|
228
|
-
return { envelope, visible: anchors };
|
|
290
|
+
return { envelope, visible: anchors, additions: envelope.visibleAdditions };
|
|
229
291
|
}
|
|
230
292
|
export function restoreGrokNativeReplay(input, messages, route) {
|
|
231
293
|
const restored = structuredClone(input);
|
|
@@ -236,11 +298,12 @@ export function restoreGrokNativeReplay(input, messages, route) {
|
|
|
236
298
|
const replay = replayForMessage(message, route);
|
|
237
299
|
if (!replay)
|
|
238
300
|
continue;
|
|
239
|
-
const { envelope, visible } = replay;
|
|
240
|
-
const replacedLength = visible.length;
|
|
301
|
+
const { envelope, visible, additions } = replay;
|
|
302
|
+
const replacedLength = visible.length + additions.length;
|
|
241
303
|
let start = -1;
|
|
242
304
|
for (let index = cursor; index <= restored.length - replacedLength; index += 1) {
|
|
243
|
-
if (visible.every((item, offset) => visibleItemMatchesInput(item, restored[index + offset]))
|
|
305
|
+
if (visible.every((item, offset) => visibleItemMatchesInput(item, restored[index + offset])) &&
|
|
306
|
+
additions.every((addition, offset) => additionMatchesInput(addition, restored[index + visible.length + offset]))) {
|
|
244
307
|
start = index;
|
|
245
308
|
break;
|
|
246
309
|
}
|
package/lib/index.js
CHANGED
|
@@ -522,15 +522,8 @@ async function serializeNativeAware(messages, route, routeConfig, ctx, options)
|
|
|
522
522
|
responsesCompat: routeConfig.responsesCompat,
|
|
523
523
|
...extra,
|
|
524
524
|
});
|
|
525
|
-
const firstMessage = messages[0];
|
|
526
|
-
const systemHead = firstMessage?.role === "system" ? firstMessage : undefined;
|
|
527
|
-
const surfaceMessages = systemHead ? messages.slice(1) : messages;
|
|
528
|
-
const systemPrompt = systemHead?.content
|
|
529
|
-
.filter((block) => block.type === "text")
|
|
530
|
-
.map((block) => block.text)
|
|
531
|
-
.join("") || undefined;
|
|
532
525
|
const prelude = await serializeDshMessages([], ctx, serializeOptions(undefined, {
|
|
533
|
-
systemPrompt,
|
|
526
|
+
systemPrompt: options.system,
|
|
534
527
|
includeSystemPrompt: true,
|
|
535
528
|
}));
|
|
536
529
|
const ephemeralPreludeItemCount = prelude.input.length;
|
|
@@ -551,7 +544,7 @@ async function serializeNativeAware(messages, route, routeConfig, ctx, options)
|
|
|
551
544
|
input.push(...restoreGrokNativeReplay(serialized.input, batch, options.grokNativeReplayRoute));
|
|
552
545
|
mergeMap(imageMap, serialized.imageMap);
|
|
553
546
|
};
|
|
554
|
-
for (const message of
|
|
547
|
+
for (const message of messages ?? []) {
|
|
555
548
|
assertSupportedCheckpointMessage(message);
|
|
556
549
|
const state = session
|
|
557
550
|
? checkpointStateForMessage(session, message)
|
|
@@ -607,7 +600,7 @@ async function* remoteCompactionStream(options, routeConfig, ctx, next) {
|
|
|
607
600
|
const history = stripCompactionDirective(options.messages);
|
|
608
601
|
const route = currentRoute(options, routeConfig);
|
|
609
602
|
try {
|
|
610
|
-
const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, tools: options.tools });
|
|
603
|
+
const prepared = await serializeNativeAware(history, route, routeConfig, ctx, { signal: options.signal, system: options.system, tools: options.tools });
|
|
611
604
|
const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
|
|
612
605
|
const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
|
|
613
606
|
const generation = generationControlsFromSession(sessionFor(ctx, route.sessionId), route);
|
|
@@ -799,7 +792,7 @@ async function* managedResponsesStream(options, routeConfig, ctx) {
|
|
|
799
792
|
try {
|
|
800
793
|
if (options.stop !== undefined)
|
|
801
794
|
throw Object.assign(new Error("LCX Responses does not support GenerateOptions.stop"), { code: "LCX_RESPONSES_UNSUPPORTED_OPTION" });
|
|
802
|
-
const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, { signal: options.signal, tools: options.tools });
|
|
795
|
+
const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, { signal: options.signal, system: options.system, tools: options.tools });
|
|
803
796
|
const cacheSessionId = promptCacheSessionId(route, routeConfig, ctx);
|
|
804
797
|
const headers = await authenticatedHeaders(ctx, routeConfig, cacheSessionId, cacheSessionId === undefined ? null : route.sessionId);
|
|
805
798
|
const body = buildResponsesBody({
|
|
@@ -846,6 +839,7 @@ async function* managedGrokNativeSearchStream(options, routeConfig, nativeSearch
|
|
|
846
839
|
const visibleTools = grokVisibleFunctionTools(options.tools, nativeSearch);
|
|
847
840
|
const prepared = await serializeNativeAware(options.messages, route, routeConfig, ctx, {
|
|
848
841
|
signal: options.signal,
|
|
842
|
+
system: options.system,
|
|
849
843
|
tools: visibleTools,
|
|
850
844
|
grokNativeReplayRoute: nativeReplayRoute,
|
|
851
845
|
});
|
package/lib/responses-stream.js
CHANGED
|
@@ -484,40 +484,6 @@ function itemText(item) {
|
|
|
484
484
|
return String(item.input ?? "");
|
|
485
485
|
return "";
|
|
486
486
|
}
|
|
487
|
-
const GROK_RENDER_MARKER = /(?:\bstateless_invoke\s+)?\{?render_inline_citation(?:\s*\(\s*citation_id\s*=\s*\d+\s*\)|\s+with\s+citation_id\s+is\s+\d+)\}?/giu;
|
|
488
|
-
const GROK_UI_CITATION_MARKER = /render_inline_citation[^\r\n]*/giu;
|
|
489
|
-
const GROK_PRIVATE_RENDER_MARKER = /[\uE000-\uF8FF]render_inline_citation[^\uE000-\uF8FF\r\n]*[\uE000-\uF8FF]/giu;
|
|
490
|
-
const GROK_NUMBERED_CITATION = /\[\[\d+\]\]\(https?:\/\/[^)\s]+\)/giu;
|
|
491
|
-
const GROK_EOS_MARKER = /<\|eos\|>/giu;
|
|
492
|
-
const GROK_SOURCE_TAIL = /(?:^|[ \t\r\n]+)Sources:\s*(?=(?:\r?\n)?\s*[-*])/iu;
|
|
493
|
-
function sanitizeGrokVisibleText(value) {
|
|
494
|
-
let text = value
|
|
495
|
-
.replace(GROK_RENDER_MARKER, "")
|
|
496
|
-
.replace(GROK_UI_CITATION_MARKER, "")
|
|
497
|
-
.replace(GROK_PRIVATE_RENDER_MARKER, "")
|
|
498
|
-
.replace(GROK_NUMBERED_CITATION, "")
|
|
499
|
-
.replace(GROK_EOS_MARKER, "");
|
|
500
|
-
const sourceTail = text.search(GROK_SOURCE_TAIL);
|
|
501
|
-
if (sourceTail >= 0)
|
|
502
|
-
text = text.slice(0, sourceTail);
|
|
503
|
-
return text.replace(/[ \t]{2,}/gu, " ").replace(/[ \t]+([,.;:!?])/gu, "$1").replace(/[ \t]+\n/gu, "\n").trimEnd();
|
|
504
|
-
}
|
|
505
|
-
function sanitizeGrokTerminalItem(item, index) {
|
|
506
|
-
const normalized = normalizedTerminalItem(item, index);
|
|
507
|
-
if (normalized.type !== "message" || !Array.isArray(normalized.content))
|
|
508
|
-
return normalized;
|
|
509
|
-
return {
|
|
510
|
-
...normalized,
|
|
511
|
-
content: normalized.content.map((part) => {
|
|
512
|
-
if (!isObject(part) || (part.type !== "output_text" && part.type !== "refusal"))
|
|
513
|
-
return structuredClone(part);
|
|
514
|
-
const text = sanitizeGrokVisibleText(String(part.text ?? part.refusal ?? ""));
|
|
515
|
-
return part.type === "output_text"
|
|
516
|
-
? { ...structuredClone(part), text }
|
|
517
|
-
: { ...structuredClone(part), refusal: text };
|
|
518
|
-
}),
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
487
|
/** @param {UnknownRecord} item @param {number} index */
|
|
522
488
|
function normalizedTerminalItem(item, index) {
|
|
523
489
|
if (item.type === "message")
|
|
@@ -608,52 +574,43 @@ function recordMatches(record, item) {
|
|
|
608
574
|
*/
|
|
609
575
|
async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
610
576
|
const open = new Map();
|
|
611
|
-
const
|
|
612
|
-
const
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
const max = Math.min(token.length - 1, lower.length);
|
|
629
|
-
for (let size = max; size > 0; size -= 1) {
|
|
630
|
-
if (lower.endsWith(token.slice(0, size))) {
|
|
631
|
-
holdStart = Math.min(holdStart, raw.length - size);
|
|
632
|
-
break;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
577
|
+
const completed = new Set();
|
|
578
|
+
const completedWireItems = new Map();
|
|
579
|
+
const serverToolIds = new Map();
|
|
580
|
+
const citations = new Map();
|
|
581
|
+
const observeCitation = (candidate) => {
|
|
582
|
+
if (!isObject(candidate))
|
|
583
|
+
return;
|
|
584
|
+
try {
|
|
585
|
+
const url = new URL(String(candidate.url ?? ""));
|
|
586
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
587
|
+
return;
|
|
588
|
+
const title = typeof candidate.title === "string"
|
|
589
|
+
? candidate.title.replace(/[\r\n]+/gu, " ").trim()
|
|
590
|
+
: "";
|
|
591
|
+
if (!citations.has(url.href))
|
|
592
|
+
citations.set(url.href, title);
|
|
635
593
|
}
|
|
636
|
-
|
|
594
|
+
catch { }
|
|
637
595
|
};
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
596
|
+
const observeCitations = (item) => {
|
|
597
|
+
if (!isObject(item))
|
|
598
|
+
return;
|
|
599
|
+
if (item.type === "message" && Array.isArray(item.content)) {
|
|
600
|
+
for (const part of item.content) {
|
|
601
|
+
if (!isObject(part) || part.type !== "output_text" || !Array.isArray(part.annotations))
|
|
602
|
+
continue;
|
|
603
|
+
for (const annotation of part.annotations)
|
|
604
|
+
if (isObject(annotation) && annotation.type === "url_citation")
|
|
605
|
+
observeCitation(annotation);
|
|
606
|
+
}
|
|
643
607
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
state.emitted = target;
|
|
650
|
-
if (final)
|
|
651
|
-
grokTextProjection.delete(index);
|
|
652
|
-
return delta;
|
|
608
|
+
if (item.type === "web_search_call" &&
|
|
609
|
+
isObject(item.action) &&
|
|
610
|
+
Array.isArray(item.action.sources))
|
|
611
|
+
for (const source of item.action.sources)
|
|
612
|
+
observeCitation(source);
|
|
653
613
|
};
|
|
654
|
-
const completed = new Set();
|
|
655
|
-
const completedWireItems = new Map();
|
|
656
|
-
const serverToolIds = new Map();
|
|
657
614
|
const isServerToolItem = (value) => isObject(value) && options.serverToolTypes?.has(String(value.type ?? "")) === true;
|
|
658
615
|
const observeServerTool = (item) => {
|
|
659
616
|
const type = String(item.type);
|
|
@@ -686,6 +643,10 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
686
643
|
const index = Number.isInteger(event.output_index)
|
|
687
644
|
? Number(event.output_index)
|
|
688
645
|
: 0;
|
|
646
|
+
if ((event.type === "response.output_item.added" ||
|
|
647
|
+
event.type === "response.output_item.done") &&
|
|
648
|
+
isObject(event.item))
|
|
649
|
+
observeCitations(event.item);
|
|
689
650
|
if (event.type === "response.output_item.done" && isObject(event.item))
|
|
690
651
|
completedWireItems.set(index, structuredClone(event.item));
|
|
691
652
|
if ((event.type === "response.output_item.added" ||
|
|
@@ -694,18 +655,10 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
694
655
|
observeServerTool(event.item);
|
|
695
656
|
continue;
|
|
696
657
|
}
|
|
697
|
-
// Grok may send many encrypted reasoning items with no visible summary.
|
|
698
|
-
// Keep them in completedWireItems/nativeOutput, but do not open empty UI blocks.
|
|
699
|
-
if (options.serverToolTypes &&
|
|
700
|
-
(event.type === "response.output_item.added" || event.type === "response.output_item.done") &&
|
|
701
|
-
isObject(event.item) && event.item.type === "reasoning" &&
|
|
702
|
-
!itemText(event.item).trim() && !open.get(index)?.text.trim())
|
|
703
|
-
continue;
|
|
704
658
|
if (event.type === "response.output_item.added" && isObject(event.item)) {
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
yield { ...event, item: options.serverToolTypes ? addedShell(item, index) : item };
|
|
659
|
+
const item = normalizedTerminalItem(event.item, index);
|
|
660
|
+
open.set(index, { kind: itemKind(item), item, text: itemText(item) });
|
|
661
|
+
yield { ...event, item };
|
|
709
662
|
continue;
|
|
710
663
|
}
|
|
711
664
|
if (event.type === "response.output_text.delta") {
|
|
@@ -726,19 +679,11 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
726
679
|
record = next.value;
|
|
727
680
|
}
|
|
728
681
|
record.text = String(record.text ?? "") + String(event.delta ?? "");
|
|
729
|
-
|
|
730
|
-
yield event;
|
|
731
|
-
else {
|
|
732
|
-
const delta = grokProjectionDelta(index, record.text);
|
|
733
|
-
if (delta)
|
|
734
|
-
yield { ...event, delta };
|
|
735
|
-
}
|
|
682
|
+
yield event;
|
|
736
683
|
continue;
|
|
737
684
|
}
|
|
738
685
|
if (event.type === "response.reasoning_summary_text.delta" ||
|
|
739
686
|
event.type === "response.reasoning_text.delta") {
|
|
740
|
-
if (options.serverToolTypes && !open.has(index) && !String(event.delta ?? "").trim())
|
|
741
|
-
continue;
|
|
742
687
|
let record = open.get(index);
|
|
743
688
|
if (!record) {
|
|
744
689
|
const item = {
|
|
@@ -810,13 +755,7 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
810
755
|
continue;
|
|
811
756
|
}
|
|
812
757
|
if (event.type === "response.output_item.done" && isObject(event.item)) {
|
|
813
|
-
const
|
|
814
|
-
const item = options.serverToolTypes ? sanitizeGrokTerminalItem(rawItem, index) : rawItem;
|
|
815
|
-
if (options.serverToolTypes && item.type === "message") {
|
|
816
|
-
const delta = grokProjectionDelta(index, itemText(rawItem), true);
|
|
817
|
-
if (delta)
|
|
818
|
-
yield { type: "response.output_text.delta", output_index: index, content_index: 0, item_id: item.id, delta };
|
|
819
|
-
}
|
|
758
|
+
const item = normalizedTerminalItem(event.item, index);
|
|
820
759
|
const identity = itemIdentity(item);
|
|
821
760
|
if (identity)
|
|
822
761
|
completed.add(identity);
|
|
@@ -836,23 +775,50 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
836
775
|
.sort(([left], [right]) => left - right)
|
|
837
776
|
.map(([, item]) => item);
|
|
838
777
|
const nativeOutput = terminalOutput.map((item) => structuredClone(item));
|
|
778
|
+
const nativeVisibleAdditions = [];
|
|
839
779
|
for (const item of terminalOutput) {
|
|
780
|
+
observeCitations(item);
|
|
840
781
|
if (isServerToolItem(item))
|
|
841
782
|
observeServerTool(item);
|
|
842
783
|
}
|
|
843
784
|
const output = terminalOutput
|
|
844
785
|
.filter((item) => !isServerToolItem(item))
|
|
845
|
-
.filter((item) => !(options.serverToolTypes && isObject(item) &&
|
|
846
|
-
item.type === "reasoning" && !itemText(item).trim()))
|
|
847
786
|
.map((item, terminalIndex) => isObject(item)
|
|
848
|
-
? (
|
|
849
|
-
? sanitizeGrokTerminalItem(item, terminalIndex)
|
|
850
|
-
: normalizedTerminalItem(item, terminalIndex))
|
|
787
|
+
? normalizedTerminalItem(item, terminalIndex)
|
|
851
788
|
: item);
|
|
789
|
+
if (options.serverToolTypes && citations.size > 0) {
|
|
790
|
+
const visibleText = output
|
|
791
|
+
.filter(isObject)
|
|
792
|
+
.map((item) => itemText(item))
|
|
793
|
+
.join("\n");
|
|
794
|
+
const missing = [...citations].filter(([url]) => !visibleText.includes(url));
|
|
795
|
+
if (missing.length > 0) {
|
|
796
|
+
const suffix = missing
|
|
797
|
+
.map(([url, title]) => `- ${title ? `${title}: ` : ""}${url}`)
|
|
798
|
+
.join("\n");
|
|
799
|
+
const responseId = String(response.id ?? "native")
|
|
800
|
+
.replace(/[^A-Za-z0-9_-]/gu, "_")
|
|
801
|
+
.slice(0, 40);
|
|
802
|
+
const fallbackItem = {
|
|
803
|
+
type: "message",
|
|
804
|
+
id: `msg_lcx_sources_${responseId}`.slice(0, 64),
|
|
805
|
+
role: "assistant",
|
|
806
|
+
status: "completed",
|
|
807
|
+
content: [{
|
|
808
|
+
type: "output_text",
|
|
809
|
+
text: `\n\nSources:\n${suffix}`,
|
|
810
|
+
annotations: [],
|
|
811
|
+
}],
|
|
812
|
+
};
|
|
813
|
+
output.push(fallbackItem);
|
|
814
|
+
nativeVisibleAdditions.push(structuredClone(fallbackItem));
|
|
815
|
+
}
|
|
816
|
+
}
|
|
852
817
|
if (event.type === "response.completed" &&
|
|
853
818
|
response.status === "completed" &&
|
|
854
819
|
options.serverToolTypes) {
|
|
855
820
|
meta.nativeOutput = nativeOutput;
|
|
821
|
+
meta.nativeVisibleAdditions = nativeVisibleAdditions;
|
|
856
822
|
}
|
|
857
823
|
const used = new Set();
|
|
858
824
|
for (const [streamIndex, record] of open) {
|
|
@@ -869,11 +835,6 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
869
835
|
: normalizedTerminalItem(record.item, streamIndex);
|
|
870
836
|
if (terminalIndex >= 0)
|
|
871
837
|
used.add(terminalIndex);
|
|
872
|
-
if (options.serverToolTypes && item.type === "message") {
|
|
873
|
-
const delta = grokProjectionDelta(streamIndex, itemText(item), true);
|
|
874
|
-
if (delta)
|
|
875
|
-
yield { type: "response.output_text.delta", output_index: streamIndex, content_index: 0, item_id: item.id, delta };
|
|
876
|
-
}
|
|
877
838
|
yield {
|
|
878
839
|
type: "response.output_item.done",
|
|
879
840
|
output_index: streamIndex,
|
|
@@ -884,7 +845,6 @@ async function* normalizedResponseEvents(source, meta = {}, options = {}) {
|
|
|
884
845
|
completed.add(identity);
|
|
885
846
|
}
|
|
886
847
|
open.clear();
|
|
887
|
-
grokTextProjection.clear();
|
|
888
848
|
for (const [terminalIndex, candidate] of output.entries()) {
|
|
889
849
|
if (!isObject(candidate) ||
|
|
890
850
|
!itemKind(candidate) ||
|
|
@@ -1000,7 +960,7 @@ function rawArguments(value) {
|
|
|
1000
960
|
}
|
|
1001
961
|
}
|
|
1002
962
|
/** @param {unknown} message */
|
|
1003
|
-
function replayState(message, nativeOutput, nativeReplayRoute) {
|
|
963
|
+
function replayState(message, nativeOutput, nativeVisibleAdditions, nativeReplayRoute) {
|
|
1004
964
|
if (!isObject(message))
|
|
1005
965
|
return undefined;
|
|
1006
966
|
const content = Array.isArray(message.content)
|
|
@@ -1011,7 +971,7 @@ function replayState(message, nativeOutput, nativeReplayRoute) {
|
|
|
1011
971
|
const api = typeof message.api === "string" ? message.api : undefined;
|
|
1012
972
|
if (!provider || !model || !api)
|
|
1013
973
|
return undefined;
|
|
1014
|
-
const grokNative = createGrokNativeReplayEnvelope(nativeOutput, nativeReplayRoute);
|
|
974
|
+
const grokNative = createGrokNativeReplayEnvelope(nativeOutput, nativeReplayRoute, nativeVisibleAdditions);
|
|
1015
975
|
return {
|
|
1016
976
|
response: {
|
|
1017
977
|
kind: "pi-ai",
|
|
@@ -1189,7 +1149,7 @@ async function* toDshChunks(events, signal, wireMeta, nativeReplayRoute) {
|
|
|
1189
1149
|
const reason = successfulFinish(message);
|
|
1190
1150
|
const replay = reason.kind === "error"
|
|
1191
1151
|
? undefined
|
|
1192
|
-
: replayState(message, wireMeta?.nativeOutput, nativeReplayRoute);
|
|
1152
|
+
: replayState(message, wireMeta?.nativeOutput, wireMeta?.nativeVisibleAdditions, nativeReplayRoute);
|
|
1193
1153
|
yield {
|
|
1194
1154
|
type: "finish",
|
|
1195
1155
|
reason,
|
|
@@ -16,19 +16,24 @@ type WireTool = Record<string, unknown>;
|
|
|
16
16
|
type WireItem = Record<string, unknown> & {
|
|
17
17
|
type: string;
|
|
18
18
|
};
|
|
19
|
+
type GrokNativeVisibleAddition = {
|
|
20
|
+
kind: "citation-sources";
|
|
21
|
+
textSha256: string;
|
|
22
|
+
};
|
|
19
23
|
type GrokNativeReplayEnvelope = {
|
|
20
24
|
kind: "xai-responses-native-search";
|
|
21
|
-
version:
|
|
25
|
+
version: 2;
|
|
22
26
|
provider: string;
|
|
23
27
|
model: string;
|
|
24
28
|
sourceSessionId: string;
|
|
25
29
|
routeAuthorityFingerprint: string;
|
|
26
30
|
output: WireItem[];
|
|
31
|
+
visibleAdditions: GrokNativeVisibleAddition[];
|
|
27
32
|
};
|
|
28
33
|
export declare function grokNativeReplayRouteFingerprint(route: GrokNativeReplayRoute): string;
|
|
29
34
|
export declare function grokNativeSearchEnabled(state: GrokNativeSearchState): boolean;
|
|
30
35
|
export declare function grokVisibleFunctionTools(tools: readonly ToolSchema[] | undefined, state?: GrokNativeSearchState): ToolSchema[] | undefined;
|
|
31
36
|
export declare function grokWireTools(tools: readonly unknown[] | undefined, state: GrokNativeSearchState): WireTool[];
|
|
32
|
-
export declare function createGrokNativeReplayEnvelope(output: readonly unknown[] | undefined, route: GrokNativeReplayRoute | undefined): GrokNativeReplayEnvelope | undefined;
|
|
37
|
+
export declare function createGrokNativeReplayEnvelope(output: readonly unknown[] | undefined, route: GrokNativeReplayRoute | undefined, visibleAdditions?: readonly unknown[]): GrokNativeReplayEnvelope | undefined;
|
|
33
38
|
export declare function restoreGrokNativeReplay(input: readonly unknown[], messages: readonly Message[], route: GrokNativeReplayRoute | undefined): unknown[];
|
|
34
39
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-lcx-codex",
|
|
3
|
-
"version": "0.4.3-pre.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.4.3-pre.3",
|
|
4
|
+
"description": "DSH GPT Responses lifecycle owner with Native V2 compaction/replay and Hosted/Alpha Search capabilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
7
7
|
"dsh",
|
|
@@ -11,10 +11,7 @@
|
|
|
11
11
|
"openai-responses",
|
|
12
12
|
"sub2api",
|
|
13
13
|
"newapi",
|
|
14
|
-
"compaction"
|
|
15
|
-
"grok",
|
|
16
|
-
"xai",
|
|
17
|
-
"x-search"
|
|
14
|
+
"compaction"
|
|
18
15
|
],
|
|
19
16
|
"repository": {
|
|
20
17
|
"type": "git",
|
|
@@ -59,7 +56,6 @@
|
|
|
59
56
|
"@earendil-works/pi-ai": "0.85.1"
|
|
60
57
|
},
|
|
61
58
|
"devDependencies": {
|
|
62
|
-
"@deepseek-ai/dsh": "0.1.5-alpha.1",
|
|
63
59
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
64
60
|
"@types/node": "^22.20.0",
|
|
65
61
|
"@types/react": "~18.3.1",
|
|
@@ -68,21 +64,21 @@
|
|
|
68
64
|
},
|
|
69
65
|
"peerDependencies": {
|
|
70
66
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
71
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
72
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
73
|
-
"@deepseek-ai/dsh-client-locale": "0.1.
|
|
74
|
-
"@deepseek-ai/dsh-client-modules": "0.1.
|
|
75
|
-
"@deepseek-ai/dsh-client-store": "0.1.
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.
|
|
77
|
-
"@deepseek-ai/dsh-compaction": "0.1.
|
|
78
|
-
"@deepseek-ai/dsh-credentials": "0.1.
|
|
79
|
-
"@deepseek-ai/dsh-fs": "0.1.
|
|
80
|
-
"@deepseek-ai/dsh-llm": "0.1.
|
|
81
|
-
"@deepseek-ai/dsh-session": "0.1.
|
|
82
|
-
"@deepseek-ai/dsh-settings": "0.1.
|
|
83
|
-
"@deepseek-ai/dsh-tool-web": "0.1.
|
|
84
|
-
"@deepseek-ai/dsh-tools": "0.1.
|
|
85
|
-
"@deepseek-ai/dsh-web": "0.1.
|
|
67
|
+
"@deepseek-ai/dsh-agent": "0.1.3-alpha.2",
|
|
68
|
+
"@deepseek-ai/dsh-attachment": "0.1.3-alpha.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-locale": "0.1.3-alpha.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-modules": "0.1.3-alpha.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-store": "0.1.3-alpha.2",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.3-alpha.2",
|
|
73
|
+
"@deepseek-ai/dsh-compaction": "0.1.3-alpha.2",
|
|
74
|
+
"@deepseek-ai/dsh-credentials": "0.1.3-alpha.2",
|
|
75
|
+
"@deepseek-ai/dsh-fs": "0.1.3-alpha.2",
|
|
76
|
+
"@deepseek-ai/dsh-llm": "0.1.3-alpha.2",
|
|
77
|
+
"@deepseek-ai/dsh-session": "0.1.3-alpha.2",
|
|
78
|
+
"@deepseek-ai/dsh-settings": "0.1.3-alpha.2",
|
|
79
|
+
"@deepseek-ai/dsh-tool-web": "0.1.3-alpha.2",
|
|
80
|
+
"@deepseek-ai/dsh-tools": "0.1.3-alpha.2",
|
|
81
|
+
"@deepseek-ai/dsh-web": "0.1.3-alpha.2",
|
|
86
82
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
87
83
|
"react": "^18.2.0"
|
|
88
84
|
},
|