dsh-more 0.0.3 → 0.0.4
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/CONTRIBUTING.md +1 -1
- package/README.md +5 -3
- package/README.zh-CN.md +5 -3
- package/dist/client.js +33 -35
- package/dist/index.js +37 -50
- package/dist/types/client/index.d.ts +5 -1
- package/dist/types/kernel/client/activation.d.ts +2 -1
- package/dist/types/kernel/client/config-card.d.ts +2 -2
- package/dist/types/kernel/client/message-actions.d.ts +4 -0
- package/dist/types/kernel/client/patch.d.ts +1 -1
- package/dist/types/kernel/host/settings.d.ts +1 -1
- package/dist/types/patches/conversation-quick-navigation/client/index.d.ts +5 -0
- package/dist/types/patches/conversation-quick-navigation/client/navigation.d.ts +3 -3
- package/dist/types/patches/message-delete/client/index.d.ts +1 -1
- package/dist/types/patches/message-delete/host/message-selection.d.ts +3 -3
- package/dist/types/patches/message-delete/host/projection.d.ts +26 -3
- package/dist/types/patches/message-edit/client/index.d.ts +1 -1
- package/dist/types/patches/message-edit/host/edit-continuation.d.ts +3 -3
- package/dist/types/patches/model-reasoning-efforts/client/index.d.ts +17 -2
- package/dist/types/platform/dsh/client/message-targets.d.ts +3 -2
- package/dist/types/platform/dsh/client/runtime.d.ts +2 -1
- package/dist/types/platform/dsh/client/session-sync.d.ts +4 -2
- package/dist/types/platform/dsh/host/session-history.d.ts +3 -3
- package/dsh.plugin.json +1 -1
- package/package.json +63 -46
package/CONTRIBUTING.md
CHANGED
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Practical, independently switchable patches for missing context and history cont
|
|
|
6
6
|
|
|
7
7
|
`dsh-more` integrates with the existing DSH interface instead of adding a separate management dashboard. Its current patch set can edit a user message and restart from that point, remove one message while preserving the surrounding context, and permanently delete a session while leaving native archive behavior intact.
|
|
8
8
|
|
|
9
|
-
> **Compatibility:** the current release targets DeepSeek Harness `0.1.
|
|
9
|
+
> **Compatibility:** the current release targets DeepSeek Harness `0.1.2-rc.1` and requires Node.js `>= 24`. DSH is still a release candidate, so upgrades may require changes in the centralized adapter layer described below.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -23,7 +23,7 @@ All three switches live under **Settings → Plugins → Plugin configuration
|
|
|
23
23
|
### Requirements
|
|
24
24
|
|
|
25
25
|
- Node.js `>= 24`
|
|
26
|
-
- A working `dsh` CLI and a Web profile compatible with DSH `0.1.
|
|
26
|
+
- A working `dsh` CLI and a Web profile compatible with DSH `0.1.2-rc.1`
|
|
27
27
|
- Access to the npm registry that publishes `dsh-more`
|
|
28
28
|
|
|
29
29
|
pnpm is needed only when installing or developing from source. For a published release, use the DSH plugin command so the package is installed into the selected DSH profile; do not install it globally with `npm install -g`.
|
|
@@ -233,7 +233,9 @@ The repository does not currently contain a full browser end-to-end suite agains
|
|
|
233
233
|
|
|
234
234
|
## Compatibility notes
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
This update migrates to the split Client services, `useChat` snapshots, settings registration, and session projection APIs, and updates message action row targeting. Dependencies and the lockfile target `0.1.2-rc.1` without the retired `dsh-client-runtime`. For an existing local linked install, rebuild, restart DSH, and reload the page to load both the new Host and Client.
|
|
237
|
+
|
|
238
|
+
- The current dependency set targets DSH `0.1.2-rc.1`; pre-release API or DOM changes can require adapter updates.
|
|
237
239
|
- In-product DSH More copy is currently primarily Simplified Chinese, although native Copy/Archive selectors recognize both Chinese and English labels.
|
|
238
240
|
- Message actions operate only on ordinary user messages and assistant messages still present in the current model surface; editing requires a completed owning turn.
|
|
239
241
|
- Permanent deletion supports DSH persistence locations of kind `jsonl` only.
|
package/README.zh-CN.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
`dsh-more` 不创建平行的“管理中心”,而是把能力直接嵌入 DSH 现有界面。当前补丁可以编辑用户消息并从该处重新开始、在保留前后上下文的前提下删除单条消息,以及在不改变原生归档语义的情况下永久删除会话。
|
|
8
8
|
|
|
9
|
-
> **兼容性:** 当前发布面向 DeepSeek Harness `0.1.
|
|
9
|
+
> **兼容性:** 当前发布面向 DeepSeek Harness `0.1.2-rc.1`,要求 Node.js `>= 24`。DSH 仍是 RC 版本,升级后可能需要调整下文所述的集中适配层。
|
|
10
10
|
|
|
11
11
|
## 功能概览
|
|
12
12
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
### 环境要求
|
|
24
24
|
|
|
25
25
|
- Node.js `>= 24`
|
|
26
|
-
- 可正常使用的 `dsh` CLI,以及与 DSH `0.1.
|
|
26
|
+
- 可正常使用的 `dsh` CLI,以及与 DSH `0.1.2-rc.1` 兼容的 Web profile
|
|
27
27
|
- 能访问发布 `dsh-more` 的 npm registry
|
|
28
28
|
|
|
29
29
|
只有从源码安装或参与开发时才需要 pnpm。安装已发布版本时,应通过 DSH 插件命令把包加入指定 profile;不要使用 `npm install -g` 全局安装。
|
|
@@ -233,7 +233,9 @@ pnpm run package # 构建并生成 npm tarball
|
|
|
233
233
|
|
|
234
234
|
## 兼容性说明
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
本次适配迁移到新版拆分后的 Client 服务、`useChat` 聊天快照、设置注册和会话投影接口,并更新消息操作行定位。依赖与锁文件统一到 `0.1.2-rc.1`;不再加载已停止更新的 `dsh-client-runtime`。已有本地链接安装在重新构建后,需要重启 DSH 并刷新页面以加载新的 Host 和 Client。
|
|
237
|
+
|
|
238
|
+
- 当前依赖面向 DSH `0.1.2-rc.1`;预发布 API 或 DOM 变化可能要求更新 adapter。
|
|
237
239
|
- DSH More 的产品内文案目前以简体中文为主;对 DSH 原生 Copy/Archive 元素的定位同时识别中英文标签。
|
|
238
240
|
- 消息操作只面向仍在当前 model surface 中的普通用户消息和助手消息;编辑要求所属轮次已经完成。
|
|
239
241
|
- 永久删除只支持 DSH 返回的 `jsonl` 持久化定位。
|
package/dist/client.js
CHANGED
|
@@ -506,6 +506,7 @@ function installSessionDeleteMenuItems(onDelete) {
|
|
|
506
506
|
frame = null;
|
|
507
507
|
for (const [archiveButton, deleteItem] of deleteItems) {
|
|
508
508
|
if (!archiveButton.isConnected) {
|
|
509
|
+
deleteItem.remove();
|
|
509
510
|
deleteItems.delete(archiveButton);
|
|
510
511
|
} else if (!deleteItem.isConnected) {
|
|
511
512
|
archiveButton.removeAttribute(DELETE_SOURCE_ATTRIBUTE);
|
|
@@ -654,8 +655,7 @@ var clientPatch = {
|
|
|
654
655
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
655
656
|
name: "shell.overlay",
|
|
656
657
|
id: `${PLUGIN_NAME}-${SESSION_DELETE_PATCH_ID}`,
|
|
657
|
-
order: 90
|
|
658
|
-
registrant: PLUGIN_NAME
|
|
658
|
+
order: 90
|
|
659
659
|
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SessionDeleteController, { ...props, ctx, activation })));
|
|
660
660
|
}
|
|
661
661
|
};
|
|
@@ -769,8 +769,7 @@ var clientPatch2 = {
|
|
|
769
769
|
ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
|
|
770
770
|
name: "conversation.session.header.utilities",
|
|
771
771
|
id: `${PLUGIN_NAME}-${CONVERSATION_MARKDOWN_EXPORT_PATCH_ID}`,
|
|
772
|
-
order: 100
|
|
773
|
-
registrant: PLUGIN_NAME
|
|
772
|
+
order: 100
|
|
774
773
|
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConversationMarkdownExportButton, { ...props, activation })));
|
|
775
774
|
}
|
|
776
775
|
};
|
|
@@ -1066,9 +1065,14 @@ function ModelsPageEffortPortal(props) {
|
|
|
1066
1065
|
syncButtons();
|
|
1067
1066
|
const observer = new MutationObserver(schedule);
|
|
1068
1067
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
1068
|
+
document.addEventListener("input", schedule);
|
|
1069
|
+
document.addEventListener("change", schedule);
|
|
1069
1070
|
return () => {
|
|
1070
1071
|
observer.disconnect();
|
|
1072
|
+
document.removeEventListener("input", schedule);
|
|
1073
|
+
document.removeEventListener("change", schedule);
|
|
1071
1074
|
if (frame !== null) window.cancelAnimationFrame(frame);
|
|
1075
|
+
document.querySelectorAll(`[${EFFORT_BUTTON_ATTR}]`).forEach((element) => element.remove());
|
|
1072
1076
|
};
|
|
1073
1077
|
}, [enabled, syncButtons]);
|
|
1074
1078
|
(0, import_react5.useEffect)(() => {
|
|
@@ -1115,13 +1119,13 @@ var clientPatch3 = {
|
|
|
1115
1119
|
getSnapshot: scope.getSnapshot.bind(scope),
|
|
1116
1120
|
subscribe: scope.subscribe.bind(scope),
|
|
1117
1121
|
set: scope.set.bind(scope),
|
|
1118
|
-
unset: scope.unset.bind(scope)
|
|
1122
|
+
unset: scope.unset.bind(scope),
|
|
1123
|
+
mutate: scope.mutate.bind(scope)
|
|
1119
1124
|
};
|
|
1120
1125
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
1121
1126
|
name: "shell.overlay",
|
|
1122
1127
|
id: `${PLUGIN_NAME}-${MODEL_REASONING_EFFORTS_PATCH_ID}`,
|
|
1123
|
-
order: 90
|
|
1124
|
-
registrant: PLUGIN_NAME
|
|
1128
|
+
order: 90
|
|
1125
1129
|
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ModelsPageEffortPortal, { ...props, scope: boundScope, activation })));
|
|
1126
1130
|
}
|
|
1127
1131
|
};
|
|
@@ -1168,14 +1172,11 @@ function sameTurns(left, right) {
|
|
|
1168
1172
|
});
|
|
1169
1173
|
}
|
|
1170
1174
|
function createConversationTurnSelector() {
|
|
1171
|
-
let previousOrder;
|
|
1172
1175
|
let previous = [];
|
|
1173
1176
|
return (snapshot) => {
|
|
1174
|
-
if (snapshot.chat.order === previousOrder) return previous;
|
|
1175
|
-
previousOrder = snapshot.chat.order;
|
|
1176
1177
|
const next = [];
|
|
1177
|
-
for (const key of snapshot.
|
|
1178
|
-
const summary = turnSummary(snapshot.
|
|
1178
|
+
for (const key of snapshot.order) {
|
|
1179
|
+
const summary = turnSummary(snapshot.nodes.get(key), key, next.length + 1);
|
|
1179
1180
|
if (summary !== null) next.push(summary);
|
|
1180
1181
|
}
|
|
1181
1182
|
if (!sameTurns(previous, next)) previous = next;
|
|
@@ -1183,9 +1184,9 @@ function createConversationTurnSelector() {
|
|
|
1183
1184
|
};
|
|
1184
1185
|
}
|
|
1185
1186
|
function historyWindowSignature(snapshot) {
|
|
1186
|
-
const first = snapshot.
|
|
1187
|
-
const last = snapshot.
|
|
1188
|
-
return `${first}\0${last}\0${String(snapshot.
|
|
1187
|
+
const first = snapshot.order[0] ?? "";
|
|
1188
|
+
const last = snapshot.order.at(-1) ?? "";
|
|
1189
|
+
return `${first}\0${last}\0${String(snapshot.order.length)}`;
|
|
1189
1190
|
}
|
|
1190
1191
|
function shouldAutoLoadOlder(state) {
|
|
1191
1192
|
return state.enabled && state.surfaceAvailable && state.hasMore && !state.loadingOlder && !state.paused;
|
|
@@ -1310,10 +1311,10 @@ function ConversationQuickNavigation(props) {
|
|
|
1310
1311
|
const settings = (0, import_react6.useSyncExternalStore)(props.activation.subscribe, props.activation.getSnapshot, props.activation.getSnapshot);
|
|
1311
1312
|
const enabled = settings[CONVERSATION_QUICK_NAVIGATION_PATCH_ID];
|
|
1312
1313
|
const selector = (0, import_react6.useMemo)(createConversationTurnSelector, [props.sessionId]);
|
|
1313
|
-
const allTurns = props.
|
|
1314
|
+
const allTurns = props.useChat(selector);
|
|
1314
1315
|
const hasMore = props.useSession((snapshot) => snapshot.hasMore);
|
|
1315
1316
|
const loadingOlder = props.useSession((snapshot) => snapshot.loadingOlder);
|
|
1316
|
-
const windowSignature = props.
|
|
1317
|
+
const windowSignature = props.useChat(historyWindowSignature);
|
|
1317
1318
|
const projected = props.useProjection(MESSAGE_VISIBILITY_PROJECTION_KEY);
|
|
1318
1319
|
const hiddenSeqs = (0, import_react6.useMemo)(() => new Set(projected?.deletedSeqs ?? []), [projected]);
|
|
1319
1320
|
const turns = (0, import_react6.useMemo)(
|
|
@@ -1406,7 +1407,7 @@ function ConversationQuickNavigation(props) {
|
|
|
1406
1407
|
scrollport?.removeEventListener("scroll", schedule);
|
|
1407
1408
|
if (frame !== null) window.cancelAnimationFrame(frame);
|
|
1408
1409
|
};
|
|
1409
|
-
}, [enabled, turns]);
|
|
1410
|
+
}, [enabled, turns, props.sessionId]);
|
|
1410
1411
|
(0, import_react6.useEffect)(() => {
|
|
1411
1412
|
if (!shouldAutoLoadOlder({ enabled, surfaceAvailable, hasMore, loadingOlder, paused: autoLoadPaused })) return;
|
|
1412
1413
|
const pendingSignature = pendingLoadSignatureRef.current;
|
|
@@ -1567,8 +1568,7 @@ var clientPatch4 = {
|
|
|
1567
1568
|
ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
|
|
1568
1569
|
name: "conversation.session.header.utilities",
|
|
1569
1570
|
id: `${PLUGIN_NAME}-${CONVERSATION_QUICK_NAVIGATION_PATCH_ID}`,
|
|
1570
|
-
order: 120
|
|
1571
|
-
registrant: PLUGIN_NAME
|
|
1571
|
+
order: 120
|
|
1572
1572
|
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ConversationQuickNavigation, { ...props, activation })));
|
|
1573
1573
|
}
|
|
1574
1574
|
};
|
|
@@ -1681,8 +1681,7 @@ function installPatchConfigCard(ctx, activation) {
|
|
|
1681
1681
|
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
1682
1682
|
name: "settings.plugin.item",
|
|
1683
1683
|
key: PATCH_SETTINGS_NAMESPACE,
|
|
1684
|
-
priority: 90
|
|
1685
|
-
registrant: PLUGIN_NAME
|
|
1684
|
+
priority: 90
|
|
1686
1685
|
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PatchConfigCard, { ...props, activation })));
|
|
1687
1686
|
}
|
|
1688
1687
|
|
|
@@ -1727,13 +1726,10 @@ function createMessageSurfaceSelector(active = true) {
|
|
|
1727
1726
|
if (!active) return () => EMPTY_MESSAGE_SURFACE;
|
|
1728
1727
|
const nodeCache = /* @__PURE__ */ new WeakMap();
|
|
1729
1728
|
let previous = EMPTY_MESSAGE_SURFACE;
|
|
1730
|
-
let previousOrder;
|
|
1731
1729
|
return (snapshot) => {
|
|
1732
|
-
if (snapshot.chat.order === previousOrder) return previous;
|
|
1733
|
-
previousOrder = snapshot.chat.order;
|
|
1734
1730
|
const rows = [];
|
|
1735
|
-
for (const key of snapshot.
|
|
1736
|
-
const node = snapshot.
|
|
1731
|
+
for (const key of snapshot.order) {
|
|
1732
|
+
const node = snapshot.nodes.get(key);
|
|
1737
1733
|
if (node === void 0) continue;
|
|
1738
1734
|
let row = nodeCache.get(node);
|
|
1739
1735
|
if (row === void 0) {
|
|
@@ -1755,8 +1751,8 @@ function createMessageSurfaceSelector(active = true) {
|
|
|
1755
1751
|
function hostForRow(row, kind) {
|
|
1756
1752
|
const existing = row.querySelector(":scope [data-dshmore-message-actions]");
|
|
1757
1753
|
if (kind === "assistant") {
|
|
1758
|
-
const turnRoot = row.querySelector("[data-turn-tail][data-
|
|
1759
|
-
const copyButton2 = turnRoot?.querySelector('button[aria-label="\u590D\u5236"], button[aria-label="Copy"]');
|
|
1754
|
+
const turnRoot = row.querySelector("[data-turn-tail][data-actions-reveal]");
|
|
1755
|
+
const copyButton2 = turnRoot?.querySelector('button[aria-label="\u590D\u5236"], button[aria-label="Copy"], button[aria-label="\u5DF2\u590D\u5236"], button[aria-label="Copied"]');
|
|
1760
1756
|
const builtInActions2 = copyButton2?.parentElement;
|
|
1761
1757
|
const placeBeforeClock = (host3) => {
|
|
1762
1758
|
if (builtInActions2 === void 0 || builtInActions2 === null) return;
|
|
@@ -1780,7 +1776,7 @@ function hostForRow(row, kind) {
|
|
|
1780
1776
|
else row.appendChild(host2);
|
|
1781
1777
|
return host2;
|
|
1782
1778
|
}
|
|
1783
|
-
const copyButton = row.querySelector('button[aria-label="\u590D\u5236"], button[aria-label="Copy"]');
|
|
1779
|
+
const copyButton = row.querySelector('button[aria-label="\u590D\u5236"], button[aria-label="Copy"], button[aria-label="\u5DF2\u590D\u5236"], button[aria-label="Copied"]');
|
|
1784
1780
|
const builtInActions = copyButton?.parentElement;
|
|
1785
1781
|
if (existing !== null) {
|
|
1786
1782
|
if (builtInActions !== void 0 && builtInActions !== null && (existing.parentElement !== builtInActions || existing.nextElementSibling !== copyButton)) {
|
|
@@ -1822,7 +1818,7 @@ function trajectorySourceSeq(row) {
|
|
|
1822
1818
|
}
|
|
1823
1819
|
function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = true) {
|
|
1824
1820
|
const selector = (0, import_react8.useMemo)(() => createMessageSurfaceSelector(active), [active, props.sessionId]);
|
|
1825
|
-
const surface = props.
|
|
1821
|
+
const surface = props.useChat(selector);
|
|
1826
1822
|
const surfaceRef = (0, import_react8.useRef)(surface);
|
|
1827
1823
|
const hiddenSeqsRef = (0, import_react8.useRef)(hiddenSeqs);
|
|
1828
1824
|
const hiddenTrajectoryKeysRef = (0, import_react8.useRef)(hiddenTrajectoryKeys);
|
|
@@ -1935,7 +1931,10 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
|
|
|
1935
1931
|
requestFullScanRef.current = requestFullScan;
|
|
1936
1932
|
const observer = new MutationObserver((records) => {
|
|
1937
1933
|
for (const record of records) {
|
|
1938
|
-
if (record.removedNodes.length > 0)
|
|
1934
|
+
if (record.removedNodes.length > 0) {
|
|
1935
|
+
pruneDisconnected = true;
|
|
1936
|
+
collectRows(record.target);
|
|
1937
|
+
}
|
|
1939
1938
|
record.addedNodes.forEach(collectRows);
|
|
1940
1939
|
}
|
|
1941
1940
|
if (pendingChatRows.size > 0 || pendingTrajectoryRows.size > 0 || pruneDisconnected) schedule();
|
|
@@ -1951,7 +1950,7 @@ function useMessageTargets(props, hiddenSeqs, hiddenTrajectoryKeys, active = tru
|
|
|
1951
1950
|
}
|
|
1952
1951
|
for (const host of document.querySelectorAll("[data-dshmore-message-actions]")) host.remove();
|
|
1953
1952
|
};
|
|
1954
|
-
}, [active]);
|
|
1953
|
+
}, [active, props.sessionId]);
|
|
1955
1954
|
(0, import_react8.useLayoutEffect)(() => {
|
|
1956
1955
|
requestFullScanRef.current?.();
|
|
1957
1956
|
}, [surface, hiddenSeqs, hiddenTrajectoryKeys]);
|
|
@@ -2004,8 +2003,7 @@ function apply(ctx) {
|
|
|
2004
2003
|
ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
|
|
2005
2004
|
name: "conversation.session.header.utilities",
|
|
2006
2005
|
id: `${PLUGIN_NAME}-message-actions`,
|
|
2007
|
-
order: 90
|
|
2008
|
-
registrant: PLUGIN_NAME
|
|
2006
|
+
order: 90
|
|
2009
2007
|
}, (props) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MessageActionsController, { ...props, ctx, activation })));
|
|
2010
2008
|
for (const patch of CLIENT_PATCHES) patch.install(ctx, activation);
|
|
2011
2009
|
}
|
package/dist/index.js
CHANGED
|
@@ -153,9 +153,8 @@ var MESSAGE_EDIT_PATCH_ID = "message-edit";
|
|
|
153
153
|
|
|
154
154
|
// src/patches/message-edit/host/edit-continuation.ts
|
|
155
155
|
import { createHash, randomUUID } from "node:crypto";
|
|
156
|
-
import { resolveSessionPreset } from "@deepseek-ai/dsh-agent-presets";
|
|
157
156
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
158
|
-
import { SessionId as SessionId2 } from "@deepseek-ai/dsh-session";
|
|
157
|
+
import { SessionId as SessionId2, SessionLogOffset, SessionSeq } from "@deepseek-ai/dsh-session";
|
|
159
158
|
|
|
160
159
|
// src/platform/dsh/host/session-history.ts
|
|
161
160
|
function completedTurns(events) {
|
|
@@ -233,18 +232,19 @@ function editedContent(original, text) {
|
|
|
233
232
|
return [{ type: "text", text }, ...kept];
|
|
234
233
|
}
|
|
235
234
|
function inspectEditCut(session, targetSeq, editedText) {
|
|
235
|
+
if (!Number.isSafeInteger(targetSeq) || targetSeq < 0) throw new DshMoreError("bad-request", "\u6D88\u606F\u5E8F\u53F7\u65E0\u6548\u3002");
|
|
236
236
|
const text = editedText.trim();
|
|
237
237
|
if (text === "") throw new DshMoreError("bad-request", "\u7F16\u8F91\u540E\u7684\u6D88\u606F\u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
238
238
|
if (text.length > 1e5) throw new DshMoreError("bad-request", "\u7F16\u8F91\u540E\u7684\u6D88\u606F\u8FC7\u957F\u3002");
|
|
239
|
-
const event = session.
|
|
239
|
+
const event = session.eventAt(SessionSeq(targetSeq));
|
|
240
240
|
if (event?.type !== "user/message" || event.data.source.kind !== "user" || event.surfaceOp !== "append") {
|
|
241
241
|
throw new DshMoreError("bad-request", "\u53EA\u80FD\u7F16\u8F91\u666E\u901A\u7528\u6237\u6D88\u606F\u3002");
|
|
242
242
|
}
|
|
243
|
-
const turns = completedTurns(session.
|
|
243
|
+
const turns = completedTurns(session.snapshotEvents());
|
|
244
244
|
const owning = turns.find((turn) => targetSeq >= turn.startSeq && targetSeq <= turn.endSeq);
|
|
245
245
|
if (owning === void 0) throw new DshMoreError("invalid-turn-range", "\u8FD9\u6761\u6D88\u606F\u6240\u5C5E\u8F6E\u6B21\u5C1A\u672A\u5B8C\u6210\u3002", 409);
|
|
246
246
|
return {
|
|
247
|
-
targetSeq,
|
|
247
|
+
targetSeq: event.seq,
|
|
248
248
|
turn: owning.turn,
|
|
249
249
|
turnStartSeq: owning.startSeq,
|
|
250
250
|
laterTurnCount: turns.filter((turn) => turn.turn >= owning.turn).length,
|
|
@@ -252,17 +252,17 @@ function inspectEditCut(session, targetSeq, editedText) {
|
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
254
|
function sourceMessage(session, targetSeq) {
|
|
255
|
-
const event = session.
|
|
255
|
+
const event = session.eventAt(targetSeq);
|
|
256
256
|
if (event?.type !== "user/message") throw new DshMoreError("bad-request", "\u7528\u6237\u6D88\u606F\u4E0D\u5B58\u5728\u3002");
|
|
257
257
|
return event;
|
|
258
258
|
}
|
|
259
259
|
async function createEditedContinuation(ctx, sourceAgent, cut, editedText, childId = SessionId2(`session-${randomUUID()}`)) {
|
|
260
260
|
const source = sourceAgent.session;
|
|
261
261
|
const original = sourceMessage(source, cut.targetSeq);
|
|
262
|
-
const presetId =
|
|
262
|
+
const presetId = ctx.sessionProjections.stateOf(source, "agentPreset") ?? void 0;
|
|
263
263
|
const roster = ctx.get("agentPresets");
|
|
264
264
|
const request = source.requestHeader()?.config;
|
|
265
|
-
const seed = source.
|
|
265
|
+
const seed = source.snapshotEvents(SessionLogOffset(0), SessionLogOffset(cut.turnStartSeq));
|
|
266
266
|
let releaseRuntimeContextReplay;
|
|
267
267
|
const releaseReplay = () => {
|
|
268
268
|
const release = releaseRuntimeContextReplay;
|
|
@@ -272,10 +272,11 @@ async function createEditedContinuation(ctx, sourceAgent, cut, editedText, child
|
|
|
272
272
|
const child = await ctx.agents.create({
|
|
273
273
|
sessionId: childId,
|
|
274
274
|
seed,
|
|
275
|
+
inheritedEventCount: SessionLogOffset(seed.length),
|
|
275
276
|
meta: {
|
|
276
277
|
...source.header.cwd === void 0 ? {} : { cwd: source.header.cwd },
|
|
277
278
|
parentSession: source.id,
|
|
278
|
-
|
|
279
|
+
isSeeded: true,
|
|
279
280
|
...presetId === void 0 ? {} : { agentPreset: presetId }
|
|
280
281
|
},
|
|
281
282
|
agentOptions: {
|
|
@@ -367,9 +368,9 @@ var MESSAGE_DELETE_PATCH_ID = "message-delete";
|
|
|
367
368
|
|
|
368
369
|
// src/patches/message-delete/host/message-selection.ts
|
|
369
370
|
import { toolPairingBalancedAfter, toolPairingBalancedBefore } from "@deepseek-ai/dsh-compaction";
|
|
370
|
-
import { isAppendSurfaceEvent } from "@deepseek-ai/dsh-session";
|
|
371
|
+
import { isAppendSurfaceEvent, SessionSeq as SessionSeq2 } from "@deepseek-ai/dsh-session";
|
|
371
372
|
function assertDeletableTarget(session, seq) {
|
|
372
|
-
const event = session.
|
|
373
|
+
const event = session.eventAt(SessionSeq2(seq));
|
|
373
374
|
if (event?.type === "user/message" && isAppendSurfaceEvent(event) && event.data.source.kind === "user") return;
|
|
374
375
|
if (event?.type === "assistant/message" && isAppendSurfaceEvent(event)) return;
|
|
375
376
|
throw new DshMoreError("bad-request", "\u53EA\u80FD\u5220\u9664\u4ECD\u5728\u5F53\u524D\u4E0A\u4E0B\u6587\u4E2D\u7684\u7528\u6237\u6D88\u606F\u6216\u52A9\u624B\u6D88\u606F\u3002");
|
|
@@ -377,7 +378,7 @@ function assertDeletableTarget(session, seq) {
|
|
|
377
378
|
function selectMessageDeletion(session, targetSeq) {
|
|
378
379
|
if (!Number.isSafeInteger(targetSeq) || targetSeq < 0) throw new DshMoreError("bad-request", "\u6D88\u606F\u5E8F\u53F7\u65E0\u6548\u3002");
|
|
379
380
|
const nodes = [...session.surface.nodes];
|
|
380
|
-
const targetIndex = nodes.indexOf(targetSeq);
|
|
381
|
+
const targetIndex = nodes.indexOf(SessionSeq2(targetSeq));
|
|
381
382
|
if (targetIndex < 0) throw new DshMoreError("selection-empty", "\u8FD9\u6761\u6D88\u606F\u5DF2\u7ECF\u4E0D\u5728\u5F53\u524D\u6A21\u578B\u4E0A\u4E0B\u6587\u4E2D\u3002");
|
|
382
383
|
assertDeletableTarget(session, targetSeq);
|
|
383
384
|
let startIndex = targetIndex;
|
|
@@ -392,7 +393,7 @@ function selectMessageDeletion(session, targetSeq) {
|
|
|
392
393
|
}
|
|
393
394
|
const shadowedSeqs = nodes.slice(startIndex, endIndex + 1);
|
|
394
395
|
if (shadowedSeqs.length === 0) throw new DshMoreError("selection-empty", "\u6CA1\u6709\u53EF\u5220\u9664\u7684\u4E0A\u4E0B\u6587\u8282\u70B9\u3002");
|
|
395
|
-
return { targetSeq, shadowedSeqs };
|
|
396
|
+
return { targetSeq: SessionSeq2(targetSeq), shadowedSeqs };
|
|
396
397
|
}
|
|
397
398
|
|
|
398
399
|
// src/patches/message-delete/host/projection.ts
|
|
@@ -432,7 +433,7 @@ function deletionUpdate(event) {
|
|
|
432
433
|
}
|
|
433
434
|
var messageDeleteProjection = {
|
|
434
435
|
key: MESSAGE_VISIBILITY_PROJECTION_KEY,
|
|
435
|
-
schema,
|
|
436
|
+
stateSchema: schema,
|
|
436
437
|
stateVersion: 3,
|
|
437
438
|
init: () => ({ deletedSeqs: [], hiddenTrajectoryKeys: [] }),
|
|
438
439
|
apply: (state, event) => {
|
|
@@ -443,14 +444,15 @@ var messageDeleteProjection = {
|
|
|
443
444
|
if (nextSeqs.length === state.deletedSeqs.length && nextKeys.length === state.hiddenTrajectoryKeys.length) return state;
|
|
444
445
|
return { deletedSeqs: nextSeqs, hiddenTrajectoryKeys: nextKeys };
|
|
445
446
|
},
|
|
446
|
-
|
|
447
|
+
wire: {
|
|
448
|
+
viewSchema: schema,
|
|
449
|
+
view: (state) => state
|
|
450
|
+
}
|
|
447
451
|
};
|
|
448
452
|
|
|
449
453
|
// src/patches/message-delete/host/rebuild.ts
|
|
450
454
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
451
|
-
import {
|
|
452
|
-
import { CallId } from "@deepseek-ai/dsh-llm";
|
|
453
|
-
import { Session, SessionId as SessionId4 } from "@deepseek-ai/dsh-session";
|
|
455
|
+
import { Session, SessionId as SessionId4, SessionLogOffset as SessionLogOffset2 } from "@deepseek-ai/dsh-session";
|
|
454
456
|
function recordedDeletionSeqs(events) {
|
|
455
457
|
const deleted = /* @__PURE__ */ new Set();
|
|
456
458
|
for (const event of events) {
|
|
@@ -470,21 +472,10 @@ function recordedDeletionSeqs(events) {
|
|
|
470
472
|
}
|
|
471
473
|
return deleted;
|
|
472
474
|
}
|
|
473
|
-
function toolCalls(message) {
|
|
474
|
-
const calls = [];
|
|
475
|
-
for (const block of message.content) {
|
|
476
|
-
const value = block;
|
|
477
|
-
if (value.type !== "tool-call" || typeof value.name !== "string") continue;
|
|
478
|
-
const callId = typeof value.id === "string" ? value.id : typeof value.callId === "string" ? value.callId : void 0;
|
|
479
|
-
if (callId === void 0) continue;
|
|
480
|
-
calls.push({ callId, name: value.name, arguments: typeof value.arguments === "string" ? value.arguments : "{}" });
|
|
481
|
-
}
|
|
482
|
-
return calls;
|
|
483
|
-
}
|
|
484
475
|
function buildCleanSeed(source, selection) {
|
|
485
|
-
const deleted = recordedDeletionSeqs(source.
|
|
476
|
+
const deleted = recordedDeletionSeqs(source.snapshotEvents());
|
|
486
477
|
for (const seq of selection.shadowedSeqs) deleted.add(seq);
|
|
487
|
-
const survivors = source.surface.nodes.filter((seq) => !deleted.has(seq)).map((seq) => source.
|
|
478
|
+
const survivors = source.surface.nodes.filter((seq) => !deleted.has(seq)).map((seq) => source.eventAt(seq)).filter((event) => event !== void 0 && source.deriveEventMessage(event) !== null);
|
|
488
479
|
const rebuilt = Session.create(SessionId4(`session-rebuild-${randomUUID3()}`));
|
|
489
480
|
let turn = 0;
|
|
490
481
|
let step = 0;
|
|
@@ -534,14 +525,15 @@ function buildCleanSeed(source, selection) {
|
|
|
534
525
|
...event.data.usage === void 0 ? {} : { usage: event.data.usage }
|
|
535
526
|
}, { surfaceOp: "append" });
|
|
536
527
|
assistantSeen = true;
|
|
537
|
-
for (const call of
|
|
538
|
-
|
|
539
|
-
|
|
528
|
+
for (const call of event.data.message.content) {
|
|
529
|
+
if (call.type !== "tool-call") continue;
|
|
530
|
+
rebuilt.append("tool/call", { turn, step, callId: call.id, name: call.name, arguments: call.arguments });
|
|
531
|
+
loggedCalls.add(call.id);
|
|
540
532
|
}
|
|
541
533
|
continue;
|
|
542
534
|
}
|
|
543
535
|
if (event.type === "tool/result") {
|
|
544
|
-
const callId =
|
|
536
|
+
const callId = event.data.message.source.callId;
|
|
545
537
|
if (!loggedCalls.has(callId)) {
|
|
546
538
|
rebuilt.append("tool/call", { turn, step, callId: event.data.message.source.callId, name: "restored-tool", arguments: "{}" });
|
|
547
539
|
loggedCalls.add(callId);
|
|
@@ -550,11 +542,11 @@ function buildCleanSeed(source, selection) {
|
|
|
550
542
|
}
|
|
551
543
|
}
|
|
552
544
|
closeTurn();
|
|
553
|
-
return rebuilt.
|
|
545
|
+
return rebuilt.snapshotEvents();
|
|
554
546
|
}
|
|
555
547
|
async function createDeletedContinuation(ctx, sourceAgent, selection, childId = SessionId4(`session-${randomUUID3()}`)) {
|
|
556
548
|
const source = sourceAgent.session;
|
|
557
|
-
const presetId =
|
|
549
|
+
const presetId = ctx.sessionProjections.stateOf(source, "agentPreset") ?? void 0;
|
|
558
550
|
const roster = ctx.get("agentPresets");
|
|
559
551
|
const request = source.requestHeader()?.config;
|
|
560
552
|
const provider = request?.provider ?? sourceAgent.options.provider;
|
|
@@ -574,10 +566,12 @@ async function createDeletedContinuation(ctx, sourceAgent, selection, childId =
|
|
|
574
566
|
const child = await ctx.agents.create({
|
|
575
567
|
sessionId: childId,
|
|
576
568
|
seed,
|
|
569
|
+
// Rebuilt events are renumbered child-owned history, not a verbatim parent prefix.
|
|
570
|
+
inheritedEventCount: SessionLogOffset2(0),
|
|
577
571
|
meta: {
|
|
578
572
|
...source.header.cwd === void 0 ? {} : { cwd: source.header.cwd },
|
|
579
573
|
parentSession: source.id,
|
|
580
|
-
|
|
574
|
+
isSeeded: false,
|
|
581
575
|
...presetId === void 0 ? {} : { agentPreset: presetId }
|
|
582
576
|
},
|
|
583
577
|
agentOptions: {
|
|
@@ -611,7 +605,7 @@ async function createDeletedContinuation(ctx, sourceAgent, selection, childId =
|
|
|
611
605
|
|
|
612
606
|
// src/patches/message-delete/host/index.ts
|
|
613
607
|
function targetTurn(session, seq) {
|
|
614
|
-
return completedTurns(session.
|
|
608
|
+
return completedTurns(session.snapshotEvents()).find((turn) => seq >= turn.startSeq && seq <= turn.endSeq)?.turn ?? 0;
|
|
615
609
|
}
|
|
616
610
|
function facts2(sessionId, session, selection, continuationSessionId) {
|
|
617
611
|
const turn = targetTurn(session, selection.targetSeq);
|
|
@@ -973,7 +967,7 @@ function render(ctx, payload) {
|
|
|
973
967
|
if ([...title].length > MAX_TITLE_LENGTH) throw new DshMoreError("bad-request", "\u4F1A\u8BDD\u6807\u9898\u8FC7\u957F\u3002");
|
|
974
968
|
const session = requireLiveSession(ctx, sessionId);
|
|
975
969
|
requireIdleAgent(ctx, sessionId, session);
|
|
976
|
-
const transcript = conversationMarkdown(session.
|
|
970
|
+
const transcript = conversationMarkdown(session.snapshotEvents(), { title, sessionId });
|
|
977
971
|
return new RawPatchResponse(transcript.markdown, "text/markdown; charset=utf-8");
|
|
978
972
|
}
|
|
979
973
|
var hostPatch4 = {
|
|
@@ -983,9 +977,6 @@ var hostPatch4 = {
|
|
|
983
977
|
})
|
|
984
978
|
};
|
|
985
979
|
|
|
986
|
-
// src/patches/model-reasoning-efforts/host/index.ts
|
|
987
|
-
import { settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
988
|
-
|
|
989
980
|
// src/patches/model-reasoning-efforts/shared.ts
|
|
990
981
|
var MODEL_REASONING_EFFORTS_PATCH_ID = "model-reasoning-efforts";
|
|
991
982
|
var LLM_PI_AI_SETTINGS_NAMESPACE = "llm-pi-ai";
|
|
@@ -1028,7 +1019,7 @@ function validateReasoningEfforts(raw) {
|
|
|
1028
1019
|
}
|
|
1029
1020
|
|
|
1030
1021
|
// src/patches/model-reasoning-efforts/host/index.ts
|
|
1031
|
-
var LLM_PI_AI_NS =
|
|
1022
|
+
var LLM_PI_AI_NS = LLM_PI_AI_SETTINGS_NAMESPACE;
|
|
1032
1023
|
function piAiSection(ctx) {
|
|
1033
1024
|
const value = ctx.settings.get(LLM_PI_AI_NS);
|
|
1034
1025
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
@@ -1214,9 +1205,6 @@ var HostPatchActivation = class {
|
|
|
1214
1205
|
}
|
|
1215
1206
|
};
|
|
1216
1207
|
|
|
1217
|
-
// src/kernel/host/settings.ts
|
|
1218
|
-
import { installSettingsSection, settingsNamespace as settingsNamespace2 } from "@deepseek-ai/dsh-settings";
|
|
1219
|
-
|
|
1220
1208
|
// src/generated/host-settings-schema.ts
|
|
1221
1209
|
import z2 from "@deepseek-ai/schemastery";
|
|
1222
1210
|
var PatchSettingsSchema = z2.object({
|
|
@@ -1229,11 +1217,10 @@ var PatchSettingsSchema = z2.object({
|
|
|
1229
1217
|
});
|
|
1230
1218
|
|
|
1231
1219
|
// src/kernel/host/settings.ts
|
|
1232
|
-
var PATCH_SETTINGS_NAMESPACE2 =
|
|
1220
|
+
var PATCH_SETTINGS_NAMESPACE2 = PATCH_SETTINGS_NAMESPACE;
|
|
1233
1221
|
function installPatchSettings(ctx, activation) {
|
|
1234
1222
|
let source = () => DEFAULT_PATCH_SETTINGS;
|
|
1235
|
-
|
|
1236
|
-
installSettingsSection(ctx, PATCH_SETTINGS_NAMESPACE2, PatchSettingsSchema, DEFAULT_PATCH_SETTINGS, {
|
|
1223
|
+
ctx.settings.installSection(ctx, PATCH_SETTINGS_NAMESPACE2, PatchSettingsSchema, DEFAULT_PATCH_SETTINGS, {
|
|
1237
1224
|
setSource: (next) => {
|
|
1238
1225
|
source = next;
|
|
1239
1226
|
},
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
1
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
|
+
export type {} from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
3
|
+
export type {} from '@deepseek-ai/dsh-client-ui-layout/client';
|
|
4
|
+
export type {} from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
5
|
+
export type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client';
|
|
2
6
|
export declare const inject: string[];
|
|
3
7
|
export declare function apply(ctx: ClientContext): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { SettingsScope
|
|
1
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
2
|
+
import type { SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
2
3
|
import { type PatchId, type PatchSettings } from '../../generated/patch-catalog.js';
|
|
3
4
|
export interface PatchActivationSource {
|
|
4
5
|
getSnapshot(): PatchSettings;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
1
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
export type {} from '@deepseek-ai/dsh-client-ui-settings-plugins/client';
|
|
3
4
|
import type { PatchActivationSource } from './activation.js';
|
|
4
5
|
type CardProps = PropsRuntime<'settings.plugin.item'>;
|
|
5
6
|
export interface PatchConfigCardProps extends CardProps {
|
|
@@ -8,4 +9,3 @@ export interface PatchConfigCardProps extends CardProps {
|
|
|
8
9
|
}
|
|
9
10
|
export declare function PatchConfigCard({ activation, initiallyOpen }: PatchConfigCardProps): JSX.Element | null;
|
|
10
11
|
export declare function installPatchConfigCard(ctx: ClientContext, activation: PatchActivationSource): void;
|
|
11
|
-
export {};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export type {} from '@deepseek-ai/dsh-client-ui-renderer/client';
|
|
2
|
+
export type {} from '@deepseek-ai/dsh-client-ui-session/client';
|
|
3
|
+
export type {} from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
4
|
+
export type {} from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
1
5
|
import type { ReactNode } from 'react';
|
|
2
6
|
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
7
|
export type ConversationHeaderProps = PropsRuntime<'conversation.session.header.utilities'>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
1
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { PatchActivationSource } from './activation.js';
|
|
3
3
|
import type { ConversationHeaderProps, MessageActions } from './message-actions.js';
|
|
4
4
|
/** A self-contained client-side patch contributed to the umbrella plugin. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { HostPatchActivation } from './activation.js';
|
|
3
|
-
export declare const PATCH_SETTINGS_NAMESPACE
|
|
3
|
+
export declare const PATCH_SETTINGS_NAMESPACE = "dsh-more";
|
|
4
4
|
/** Bind persisted DSH settings to live Host patch activation. */
|
|
5
5
|
export declare function installPatchSettings(ctx: Context, activation: HostPatchActivation): void;
|
|
@@ -3,6 +3,11 @@ import type { PatchActivationSource } from '../../../kernel/client/activation.js
|
|
|
3
3
|
import type { ClientPatch } from '../../../kernel/client/patch.js';
|
|
4
4
|
import { type ConversationTurnSummary } from './navigation.js';
|
|
5
5
|
type HeaderUtilityProps = PropsRuntime<'conversation.session.header.utilities'>;
|
|
6
|
+
export declare function conversationRow(root: HTMLElement, key: string): HTMLElement | null;
|
|
7
|
+
export declare function sessionRoot(marker: HTMLElement | null): HTMLElement | null;
|
|
8
|
+
export declare function conversationScrollport(marker: HTMLElement | null): HTMLElement | null;
|
|
9
|
+
/** The native pre-row paging control owns DSH's reader-position anchoring. */
|
|
10
|
+
export declare function nativeLoadOlderButton(scrollport: HTMLElement): HTMLButtonElement | null;
|
|
6
11
|
export declare function ConversationNavigationMenu({ turns, activeKey, hasMore, loadingOlder, autoLoadPaused, collapsed, onRetry, onToggleCollapsed, onJump, listRef, }: {
|
|
7
12
|
turns: readonly ConversationTurnSummary[];
|
|
8
13
|
activeKey: string | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
2
2
|
export interface ConversationTurnSummary {
|
|
3
3
|
key: string;
|
|
4
4
|
seq: number;
|
|
@@ -16,9 +16,9 @@ export interface AutoLoadOlderState {
|
|
|
16
16
|
paused: boolean;
|
|
17
17
|
}
|
|
18
18
|
/** Select stable user-authored turn summaries without observing assistant streaming frames. */
|
|
19
|
-
export declare function createConversationTurnSelector(): (snapshot:
|
|
19
|
+
export declare function createConversationTurnSelector(): (snapshot: ChatSnapshot) => readonly ConversationTurnSummary[];
|
|
20
20
|
/** Stable evidence that an older history page prepended visible conversation material. */
|
|
21
|
-
export declare function historyWindowSignature(snapshot:
|
|
21
|
+
export declare function historyWindowSignature(snapshot: ChatSnapshot): string;
|
|
22
22
|
export declare function shouldAutoLoadOlder(state: AutoLoadOlderState): boolean;
|
|
23
23
|
/** Pick the last turn at or above the reading line, falling back to the first turn. */
|
|
24
24
|
export declare function activeTurnAt(positions: readonly TurnPosition[], readingLine: number): string | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
1
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { ConversationHeaderProps, MessageActions } from '../../../kernel/client/message-actions.js';
|
|
3
3
|
export declare function useMessageActions(props: ConversationHeaderProps & {
|
|
4
4
|
ctx: ClientContext;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type Session } from '@deepseek-ai/dsh-session';
|
|
1
|
+
import { SessionSeq, type Session } from '@deepseek-ai/dsh-session';
|
|
2
2
|
export interface MessageDeletionSelection {
|
|
3
|
-
targetSeq:
|
|
4
|
-
shadowedSeqs: readonly
|
|
3
|
+
targetSeq: SessionSeq;
|
|
4
|
+
shadowedSeqs: readonly SessionSeq[];
|
|
5
5
|
}
|
|
6
6
|
/** Expand only as far as needed to keep tool call/result pairing valid. */
|
|
7
7
|
export declare function selectMessageDeletion(session: Session, targetSeq: number): MessageDeletionSelection;
|
|
@@ -1,8 +1,31 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
1
|
+
import { type SessionEvent } from '@deepseek-ai/dsh-session';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { type MessageVisibilityProjection } from '../../../kernel/message-visibility.js';
|
|
3
4
|
declare module '@deepseek-ai/dsh-session-projection/types' {
|
|
5
|
+
interface SessionProjectionStateMap {
|
|
6
|
+
dshMoreMessageDelete: MessageVisibilityProjection;
|
|
7
|
+
}
|
|
4
8
|
interface SessionProjectionMap {
|
|
5
9
|
dshMoreMessageDelete: MessageVisibilityProjection;
|
|
6
10
|
}
|
|
7
11
|
}
|
|
8
|
-
export declare const messageDeleteProjection:
|
|
12
|
+
export declare const messageDeleteProjection: {
|
|
13
|
+
key: "dshMoreMessageDelete";
|
|
14
|
+
stateSchema: z.ZodObject<{
|
|
15
|
+
deletedSeqs: z.ZodArray<z.ZodNumber>;
|
|
16
|
+
hiddenTrajectoryKeys: z.ZodArray<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
stateVersion: number;
|
|
19
|
+
init: () => {
|
|
20
|
+
deletedSeqs: never[];
|
|
21
|
+
hiddenTrajectoryKeys: never[];
|
|
22
|
+
};
|
|
23
|
+
apply: (state: NoInfer<MessageVisibilityProjection>, event: SessionEvent) => MessageVisibilityProjection;
|
|
24
|
+
wire: {
|
|
25
|
+
viewSchema: z.ZodObject<{
|
|
26
|
+
deletedSeqs: z.ZodArray<z.ZodNumber>;
|
|
27
|
+
hiddenTrajectoryKeys: z.ZodArray<z.ZodString>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
view: (state: NoInfer<MessageVisibilityProjection>) => MessageVisibilityProjection;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClientContext } from '@deepseek-ai/
|
|
1
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { ConversationHeaderProps, MessageActions } from '../../../kernel/client/message-actions.js';
|
|
3
3
|
export declare function useMessageActions(props: ConversationHeaderProps & {
|
|
4
4
|
ctx: ClientContext;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
|
-
import { SessionId, type Session } from '@deepseek-ai/dsh-session';
|
|
3
|
+
import { SessionId, SessionSeq, type Session } from '@deepseek-ai/dsh-session';
|
|
4
4
|
export interface EditCut {
|
|
5
|
-
targetSeq:
|
|
5
|
+
targetSeq: SessionSeq;
|
|
6
6
|
turn: number;
|
|
7
|
-
turnStartSeq:
|
|
7
|
+
turnStartSeq: SessionSeq;
|
|
8
8
|
laterTurnCount: number;
|
|
9
9
|
contentDigest: string;
|
|
10
10
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SettingsScope } from '@deepseek-ai/dsh-client-
|
|
1
|
+
import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
2
2
|
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
export type {} from '@deepseek-ai/dsh-client-ui-settings';
|
|
3
4
|
import type { PatchActivationSource } from '../../../kernel/client/activation.js';
|
|
4
5
|
import type { ClientPatch } from '../../../kernel/client/patch.js';
|
|
5
6
|
import { type ThinkingLevel } from '../shared.js';
|
|
@@ -14,6 +15,21 @@ export interface ModelDraft {
|
|
|
14
15
|
nonReasoning: boolean;
|
|
15
16
|
levels: Partial<Record<ThinkingLevel, LevelDraft>>;
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Locate every model row of every open model catalog in the shipped Models
|
|
20
|
+
* settings page (the provider editor's 模型目录). The classes are the models
|
|
21
|
+
* package's own CSS-module hashes, stable per build.
|
|
22
|
+
*/
|
|
23
|
+
export declare function findModelEntries(): HTMLElement[];
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the provider route for one model entry: the editor header's route
|
|
26
|
+
* span when the route differs from the display name, else the owning provider
|
|
27
|
+
* card's display name (which for such providers equals the route). Returns
|
|
28
|
+
* null for the custom-provider creation card, which has no saved provider yet.
|
|
29
|
+
*/
|
|
30
|
+
export declare function providerRouteOf(entry: HTMLElement): string | null;
|
|
31
|
+
/** Resolve the model id from a model entry's first row input (the id field). */
|
|
32
|
+
export declare function modelIdOf(entry: HTMLElement): string | null;
|
|
17
33
|
/**
|
|
18
34
|
* The level toggles + wire-value inputs shared by the editor modal. Draft
|
|
19
35
|
* state lives in the caller so the modal survives models-page re-renders.
|
|
@@ -36,4 +52,3 @@ export declare function ModelsPageEffortPortal(props: OverlayProps & {
|
|
|
36
52
|
activation: PatchActivationSource;
|
|
37
53
|
}): JSX.Element | null;
|
|
38
54
|
export declare const clientPatch: ClientPatch;
|
|
39
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
2
2
|
import type { ConversationHeaderProps, MessageTarget } from '../../../kernel/client/message-actions.js';
|
|
3
3
|
export interface MessageSurfaceRow {
|
|
4
4
|
key: string;
|
|
@@ -10,5 +10,6 @@ export interface MessageSurfaceSnapshot {
|
|
|
10
10
|
byKey: ReadonlyMap<string, MessageSurfaceRow>;
|
|
11
11
|
}
|
|
12
12
|
/** Select only facts used by message actions, retaining identity across unrelated stream frames. */
|
|
13
|
-
export declare function createMessageSurfaceSelector(active?: boolean): (snapshot:
|
|
13
|
+
export declare function createMessageSurfaceSelector(active?: boolean): (snapshot: ChatSnapshot) => MessageSurfaceSnapshot;
|
|
14
|
+
export declare function hostForRow(row: HTMLElement, kind: MessageTarget['kind']): HTMLElement;
|
|
14
15
|
export declare function useMessageTargets(props: ConversationHeaderProps, hiddenSeqs: ReadonlySet<number>, hiddenTrajectoryKeys: ReadonlySet<string>, active?: boolean): readonly MessageTarget[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ISessions
|
|
1
|
+
import type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
2
|
+
import type { IWorkspaces } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
2
3
|
export interface RefreshableSessions extends ISessions {
|
|
3
4
|
refresh(): Promise<void>;
|
|
4
5
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { SessionId
|
|
1
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
2
|
+
import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
3
|
+
import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
2
4
|
import type { RefreshableSessions, RefreshableWorkspaces } from './runtime.js';
|
|
3
5
|
/** Switch synchronously so a following archive/removal frame cannot expose the empty view. */
|
|
4
6
|
export declare function openSessionWithoutGap(sessions: RefreshableSessions, sessionId: SessionId): void;
|
|
@@ -15,4 +17,4 @@ export declare function followSessionHandoff(sessions: RefreshableSessions, targ
|
|
|
15
17
|
/** Prefer push-frame convergence after deletion; re-pull both baselines only as a fallback. */
|
|
16
18
|
export declare function settleSessionRemoval(sessions: RefreshableSessions, workspaces: RefreshableWorkspaces, sessionId: SessionId): Promise<void>;
|
|
17
19
|
/** Pick the nearest non-archived row so deleting the current session never exposes a blank gap. */
|
|
18
|
-
export declare function adjacentVisibleSession(sessions: SessionListState, workspaces:
|
|
20
|
+
export declare function adjacentVisibleSession(sessions: SessionListState, workspaces: WorkspaceSnapshot, deletingSessionId: SessionId): SessionId | undefined;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
1
|
+
import type { SessionEvent, SessionSeq } from '@deepseek-ai/dsh-session';
|
|
2
2
|
export interface CompletedTurn {
|
|
3
3
|
turn: number;
|
|
4
|
-
startSeq:
|
|
5
|
-
endSeq:
|
|
4
|
+
startSeq: SessionSeq;
|
|
5
|
+
endSeq: SessionSeq;
|
|
6
6
|
}
|
|
7
7
|
/** Return only turns with a durable start/end pair, in log order. */
|
|
8
8
|
export declare function completedTurns(events: readonly SessionEvent[]): CompletedTurn[];
|
package/dsh.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-more",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Practical patches for missing DeepSeek Harness Web context and history controls.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,12 +56,16 @@
|
|
|
56
56
|
"client": {
|
|
57
57
|
"platform": "web",
|
|
58
58
|
"inject": [
|
|
59
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
60
59
|
"@deepseek-ai/dsh-client-ui-slots",
|
|
61
60
|
"@deepseek-ai/dsh-client-ui-conversation",
|
|
62
61
|
"@deepseek-ai/dsh-client-ui-primitives",
|
|
63
62
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins"
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins",
|
|
64
|
+
"@deepseek-ai/dsh-api-session-controller",
|
|
65
|
+
"@deepseek-ai/dsh-api-workspace-controller",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-chat",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-session",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-renderer"
|
|
65
69
|
]
|
|
66
70
|
}
|
|
67
71
|
},
|
|
@@ -84,52 +88,57 @@
|
|
|
84
88
|
"prepack": "npm run check"
|
|
85
89
|
},
|
|
86
90
|
"peerDependencies": {
|
|
87
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
88
|
-
"@deepseek-ai/dsh-agent": "^0.1.
|
|
89
|
-
"@deepseek-ai/dsh-client-
|
|
90
|
-
"@deepseek-ai/dsh-client-ui-
|
|
91
|
-
"@deepseek-ai/dsh-client-ui-
|
|
92
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-
|
|
94
|
-
"@deepseek-ai/dsh-
|
|
95
|
-
"@deepseek-ai/dsh-
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
98
|
-
"@deepseek-ai/dsh-
|
|
99
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
100
|
-
"@deepseek-ai/dsh-session-
|
|
101
|
-
"@deepseek-ai/dsh-
|
|
102
|
-
"@deepseek-ai/dsh-
|
|
103
|
-
"@deepseek-ai/dsh-
|
|
104
|
-
"@deepseek-ai/dsh-
|
|
105
|
-
"@deepseek-ai/
|
|
106
|
-
"@deepseek-ai/schemastery": "^3.18.1",
|
|
91
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
92
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-rc.1",
|
|
97
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-compaction": "^0.1.2-rc.1",
|
|
99
|
+
"@deepseek-ai/dsh-agent-presets": "^0.1.2-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.2-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-session": "^0.1.2-rc.1",
|
|
103
|
+
"@deepseek-ai/dsh-session-persistence": "^0.1.2-rc.1",
|
|
104
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.2-rc.1",
|
|
105
|
+
"@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.2-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-workspace": "^0.1.2-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-web-app": "^0.1.2-rc.1",
|
|
109
|
+
"@deepseek-ai/schemastery": "^3.18.2",
|
|
107
110
|
"react": "^18.2.0",
|
|
108
111
|
"react-dom": "^18.2.0",
|
|
109
|
-
"zod": "^4.4.3"
|
|
112
|
+
"zod": "^4.4.3",
|
|
113
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
|
|
114
|
+
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.2-rc.1",
|
|
115
|
+
"@deepseek-ai/dsh-client-ui-chat": "^0.1.2-rc.1",
|
|
116
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.2-rc.1",
|
|
117
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1",
|
|
118
|
+
"@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
|
|
119
|
+
"@deepseek-ai/dsh-llm-retry": "^0.1.2-rc.1"
|
|
110
120
|
},
|
|
111
121
|
"devDependencies": {
|
|
112
|
-
"@deepseek-ai/cordis": "4.0.
|
|
113
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
114
|
-
"@deepseek-ai/dsh-client-
|
|
115
|
-
"@deepseek-ai/dsh-client-ui-
|
|
116
|
-
"@deepseek-ai/dsh-client-ui-
|
|
117
|
-
"@deepseek-ai/dsh-client-ui-
|
|
118
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.
|
|
119
|
-
"@deepseek-ai/dsh-client-ui-
|
|
120
|
-
"@deepseek-ai/dsh-
|
|
121
|
-
"@deepseek-ai/dsh-
|
|
122
|
-
"@deepseek-ai/dsh-
|
|
123
|
-
"@deepseek-ai/dsh-
|
|
124
|
-
"@deepseek-ai/dsh-
|
|
125
|
-
"@deepseek-ai/dsh-session": "0.1.
|
|
126
|
-
"@deepseek-ai/dsh-session-
|
|
127
|
-
"@deepseek-ai/dsh-
|
|
128
|
-
"@deepseek-ai/dsh-
|
|
129
|
-
"@deepseek-ai/dsh-
|
|
130
|
-
"@deepseek-ai/dsh-
|
|
131
|
-
"@deepseek-ai/
|
|
132
|
-
"@deepseek-ai/schemastery": "3.18.1",
|
|
122
|
+
"@deepseek-ai/cordis": "4.0.2",
|
|
123
|
+
"@deepseek-ai/dsh-agent": "0.1.2-rc.1",
|
|
124
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
|
|
125
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.1.2-rc.1",
|
|
126
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
|
|
127
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1",
|
|
128
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.2-rc.1",
|
|
129
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1",
|
|
130
|
+
"@deepseek-ai/dsh-compaction": "0.1.2-rc.1",
|
|
131
|
+
"@deepseek-ai/dsh-agent-presets": "0.1.2-rc.1",
|
|
132
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1",
|
|
133
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
134
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
135
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.2-rc.1",
|
|
136
|
+
"@deepseek-ai/dsh-session-projection": "0.1.2-rc.1",
|
|
137
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
138
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
139
|
+
"@deepseek-ai/dsh-workspace": "0.1.2-rc.1",
|
|
140
|
+
"@deepseek-ai/dsh-web-app": "0.1.2-rc.1",
|
|
141
|
+
"@deepseek-ai/schemastery": "3.18.2",
|
|
133
142
|
"@types/node": "^24.0.0",
|
|
134
143
|
"@types/react": "~18.3.0",
|
|
135
144
|
"@types/react-dom": "~18.3.0",
|
|
@@ -138,6 +147,14 @@
|
|
|
138
147
|
"react-dom": "18.3.1",
|
|
139
148
|
"typescript": "^5.9.2",
|
|
140
149
|
"vitest": "^4.0.0",
|
|
141
|
-
"zod": "4.4.3"
|
|
150
|
+
"zod": "4.4.3",
|
|
151
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.2-rc.1",
|
|
152
|
+
"@deepseek-ai/dsh-api-workspace-controller": "0.1.2-rc.1",
|
|
153
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.1.2-rc.1",
|
|
154
|
+
"@deepseek-ai/dsh-client-ui-session": "0.1.2-rc.1",
|
|
155
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
|
|
156
|
+
"@deepseek-ai/dsh-client-store": "0.1.2-rc.1",
|
|
157
|
+
"@deepseek-ai/dsh-llm-retry": "0.1.2-rc.1",
|
|
158
|
+
"happy-dom": "20.14.0"
|
|
142
159
|
}
|
|
143
160
|
}
|