@deepseek-ai/dsh-client-ui-plan 0.1.6-alpha.2 → 0.1.7-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +7 -5
- package/README.zh.md +8 -6
- package/lib/client.js +79 -61
- package/lib/types/client/PlanCard.d.ts +22 -3
- package/lib/types/client/PlanPreview.d.ts +3 -3
- package/lib/types/client/locales.d.ts +0 -4
- package/package.json +23 -23
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/client/ui-plan/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: e9e38251ff69ed601e486b4c1ce351b236e7bcb7
|
|
6
|
+
README.zh.md: 91fe232d27007fea8264e98c895ca2788585710c
|
package/README.md
CHANGED
|
@@ -29,13 +29,13 @@ Mount this plugin alongside `ui-conversation` and `dsh-plan-mode`; the chip then
|
|
|
29
29
|
|
|
30
30
|
### What the chip shows
|
|
31
31
|
|
|
32
|
-
While the effective target is plan mode, the seat renders the
|
|
32
|
+
While the effective target is plan mode, the seat renders the blue "Plan" status button — the plan glyph ahead of the label, swapped for a circled cross while the enabled button is hovered or keyboard-focused — which executes `/plan off`. Otherwise the seat stays empty: a host without plan mode, or a Draft with no session, shows nothing. While plan mode is the effective target, the composer textarea's placeholder switches to the plan-task hint — "describe your task to generate plan" — unless the owning surface supplies its own placeholder.
|
|
33
33
|
|
|
34
34
|
### Reading submitted plans
|
|
35
35
|
|
|
36
|
-
When a Turn ends, each submitted plan appears in its final artifact area, using the file-delivery card treatment with a Markdown icon, title, and Open action. A pending plan opens automatically once per submission in the current browser session. Closing it stays effective across review remounts; a new submission opens its own plan. Historical cards open only when clicked. Use the card or review strip’s View full plan link to read
|
|
36
|
+
When a Turn ends, each submitted plan appears in its final artifact area, using the file-delivery card treatment with a Markdown icon, title, and Open action. A pending plan opens automatically once per submission in the current browser session. Closing it stays effective across review remounts; a new submission opens its own plan. Historical cards open only when clicked. Use the card or review strip’s View full plan link to read the complete Markdown. Plan tabs show a plain text file icon. Different submissions retain separate tabs; the review buttons alone decide whether implementation may begin.
|
|
37
37
|
|
|
38
|
-
A review without a logged invocation also opens automatically. Its complete text lives only in the tab’s navigation memory, and the pending review card can reopen it. Reloading the page loses that text; an expired preview directs the user back to a pending review.
|
|
38
|
+
A review without a logged invocation also opens automatically. Its complete text lives only in the tab’s navigation memory, and the pending review card can reopen it. Reloading the page loses that text; an expired preview directs the user back to a pending review. Plans opened from an embedded child conversation use the visible sidebar while retaining the child’s address for document reads.
|
|
39
39
|
|
|
40
40
|
### Failures
|
|
41
41
|
|
|
@@ -49,9 +49,11 @@ Admission failures (`matched: false`, business errors, transport faults) surface
|
|
|
49
49
|
<details>
|
|
50
50
|
<summary>Implementation internals — click to expand</summary>
|
|
51
51
|
|
|
52
|
-
The chip occupies the conversation-declared `conversation.input.plan` single seat; the node half is an empty apply (the roster row). Reads ride the generic projection pair through the standard-kit `useProjection`: the effective target is `pending ? !active : active` — a folded host value, not client optimism, so an arriving frame corrects the chip either way. The seat's injected face carries one verb, `exitPlanMode`, which executes `/plan off` through `ctx.remote.commands.execute` and maps admission failures to an inline error line. The placeholder and hint text live in ui-conversation's `conversation` locale namespace and are shared verbatim with the claimed `/plan` command hint.
|
|
52
|
+
The chip occupies the conversation-declared `conversation.input.plan` single seat; the node half is an empty apply (the roster row). Reads ride the generic projection pair through the standard-kit `useProjection`: the effective target is `pending ? !active : active` — a folded host value, not client optimism, so an arriving frame corrects the chip either way. The seat's injected face carries one verb, `exitPlanMode`, which executes `/plan off` through `ctx.remote.commands.execute` and maps admission failures to an inline error line. The placeholder and hint text live in ui-conversation's `conversation` locale namespace and are shared verbatim with the claimed `/plan` command hint.
|
|
53
53
|
|
|
54
|
-
Plan cards derive from native `tool/call` or PTC dispatch arguments through a Conversation Definition, with each invocation’s resolved Turn location. They contribute to the additive `conversation.chat.turnTail` list alongside file deliveries. The plan resource address identifies the invocation and its complete ordinary or direct-parent subagent Session address; its provider reads existing Session history, including older pages, without storing document text in sidebar layout. The question plugin owns the review action slot and supplies its request key, complete text, and optional invocation identity. The [decision](../../../.agents/notes/implemented/feature/2026-09-17-persistent-plan-cards.md) explains why review lifetime and document lifetime remain separate.
|
|
54
|
+
Plan cards derive from native `tool/call` or PTC dispatch arguments through a Conversation Definition, with each invocation’s resolved Turn location. They contribute to the additive `conversation.chat.turnTail` list alongside file deliveries. The plan resource address identifies the invocation and its complete ordinary or direct-parent subagent Session address; its provider reads existing Session history, including older pages, without storing document text in sidebar layout. The question plugin owns the review action slot and supplies its request key, complete text, and optional invocation identity. The automatic open reads `ctx.sidebarRight.mounted` through a bound hook and runs once a seat is on screen: a review arriving while a global panel is active mounts ahead of the returning seat in the same commit, before that seat binds. The [decision](../../../.agents/notes/implemented/feature/2026-09-17-persistent-plan-cards.md) explains why review lifetime and document lifetime remain separate. Subagent plan addresses also preserve unknown mode so history reads can resolve the child descriptor.
|
|
55
|
+
|
|
56
|
+
The framework-bound `usePlans(turn)` exposes only submitted-plan data for that Turn. Chat indexes membership on Node updates and orders this collection when read; card rendering neither scans the transcript nor subscribes to other Turns or Node kinds.
|
|
55
57
|
|
|
56
58
|
</details>
|
|
57
59
|
|
package/README.zh.md
CHANGED
|
@@ -25,17 +25,17 @@ kind: "package-reference"
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## 使用本包
|
|
27
27
|
|
|
28
|
-
与 `ui-conversation` 及 `dsh-plan-mode` 一起挂载本插件;plan 模式激活时,徽章随即占据 composer 的 plan 座位(访问模式控件右侧)。经 `/plan` 命令路径进入 plan 模式——从 composer 的 `+` Command
|
|
28
|
+
与 `ui-conversation` 及 `dsh-plan-mode` 一起挂载本插件;plan 模式激活时,徽章随即占据 composer 的 plan 座位(访问模式控件右侧)。经 `/plan` 命令路径进入 plan 模式——从 composer 的 `+` Command 菜单选择「计划」,或键入 `/plan`——再用徽章将其关闭。
|
|
29
29
|
|
|
30
30
|
### 徽章显示什么
|
|
31
31
|
|
|
32
|
-
当有效目标为 plan
|
|
32
|
+
当有效目标为 plan 模式时,该座位渲染蓝色「计划」状态按钮——标签前是计划图标,按钮可用且被悬停或键盘聚焦时换成圆形 ×——点击执行 `/plan off`。否则座位保持为空:未组合 plan-mode 的宿主,或尚无会话的 Draft,都不显示任何内容。plan 模式为有效目标期间,composer 文本框的 placeholder 切换为 plan 任务提示——「describe your task to generate plan」——除非所属 surface 提供自己的 placeholder。
|
|
33
33
|
|
|
34
34
|
### 查看已提交的计划
|
|
35
35
|
|
|
36
|
-
回合结束后,每次提交的计划都会显示在该回合末尾的产物区域,并采用文件产物卡片的样式,包含 Markdown
|
|
36
|
+
回合结束后,每次提交的计划都会显示在该回合末尾的产物区域,并采用文件产物卡片的样式,包含 Markdown 图标、标题和“打开”操作。在当前浏览器会话中,每份待审计划自动打开一次;关闭后,重新挂载审批组件不会再次展开,新提交会打开其对应计划。历史卡片仅在点击后打开。通过卡片或审批条带上的“查看全文”链接可阅读完整 Markdown。计划标签页显示纯文本文件图标。不同提交保留独立标签页;是否开始实施仍由审批按钮决定。
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
没有已记录调用标识的审批也会自动打开。完整正文只保存在标签页的导航内存中,待处理审批卡片可以重新打开它。刷新页面会丢失该正文;失效的预览会提示用户返回待处理审批。在嵌入式子对话中打开计划时,预览使用当前可见的侧栏,读取文档仍保留子会话地址。
|
|
39
39
|
|
|
40
40
|
### 失败
|
|
41
41
|
|
|
@@ -49,9 +49,11 @@ kind: "package-reference"
|
|
|
49
49
|
<details>
|
|
50
50
|
<summary>实现细节——点击展开</summary>
|
|
51
51
|
|
|
52
|
-
徽章占据 conversation 声明的 `conversation.input.plan` 单实例座位;node 半部是空 apply(roster 行)。读取经 standard-kit 的 `useProjection` 走通用投影对:有效目标是 `pending ? !active : active`——折叠的宿主值而非客户端乐观态,因此到达的帧无论哪个方向都会纠正徽章。座位注入面携带一个动词 `exitPlanMode`,经 `ctx.remote.commands.execute` 执行 `/plan off`,并把准入失败映射为一行内联错误。placeholder 与提示文案位于 ui-conversation 的 `conversation` locale 命名空间,与已认领 `/plan`
|
|
52
|
+
徽章占据 conversation 声明的 `conversation.input.plan` 单实例座位;node 半部是空 apply(roster 行)。读取经 standard-kit 的 `useProjection` 走通用投影对:有效目标是 `pending ? !active : active`——折叠的宿主值而非客户端乐观态,因此到达的帧无论哪个方向都会纠正徽章。座位注入面携带一个动词 `exitPlanMode`,经 `ctx.remote.commands.execute` 执行 `/plan off`,并把准入失败映射为一行内联错误。placeholder 与提示文案位于 ui-conversation 的 `conversation` locale 命名空间,与已认领 `/plan` 命令的提示逐字共用。
|
|
53
53
|
|
|
54
|
-
计划卡片通过 Conversation Definition 从原生 `tool/call` 或 PTC dispatch 参数派生,并使用每次调用已解析的回合位置。它们与文件产物一起贡献到可追加的 `conversation.chat.turnTail` 列表。计划资源地址标识调用及完整的普通会话地址或子会话直接父级地址;provider
|
|
54
|
+
计划卡片通过 Conversation Definition 从原生 `tool/call` 或 PTC dispatch 参数派生,并使用每次调用已解析的回合位置。它们与文件产物一起贡献到可追加的 `conversation.chat.turnTail` 列表。计划资源地址标识调用及完整的普通会话地址或子会话直接父级地址;provider 读取已有会话历史及较早分页,不把正文存入侧边栏布局。提问插件拥有审批操作插槽,并提供请求键、完整正文和可选的调用标识。自动打开通过绑定的 hook 读取 `ctx.sidebarRight.mounted`,在座位出现在屏幕上后才执行:全局面板打开期间到达的审批,会在返回时与座位在同一次提交里先挂载、早于座位完成绑定。[决策记录](../../../.agents/notes/implemented/feature/2026-09-17-persistent-plan-cards.zh.md)说明审批与文档为何保持独立生命周期。 子代理计划地址也保留未知模式,以便历史读取解析子 descriptor。
|
|
55
|
+
|
|
56
|
+
框架绑定的 `usePlans(turn)` 只提供该回合的已提交计划数据。Chat 随节点更新维护成员索引,并在读取时排列该集合;卡片渲染不扫描整段对话,也不订阅其他回合或节点类型。
|
|
55
57
|
|
|
56
58
|
</details>
|
|
57
59
|
|
package/lib/client.js
CHANGED
|
@@ -7,8 +7,8 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react = require("react");
|
|
10
|
-
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
11
10
|
require("@deepseek-ai/cordis");
|
|
11
|
+
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
12
12
|
//#region ../../util/crypto/src/index.ts
|
|
13
13
|
/**
|
|
14
14
|
* Random v4 UUID, minted from `crypto.getRandomValues`.
|
|
@@ -23,7 +23,7 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-plan/src/client/PlanPreview.module.css.mjs
|
|
26
|
-
const css$1 = ".k74WwW_cards{flex-direction:column;gap:10px;display:flex}.k74WwW_card{--plan-card-fill:var(--dsw-static-neutral-50);--plan-card-hover:var(--dsw-static-neutral-100);box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l1);background:var(--plan-card-fill);width:100%;min-width:0;height:60px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;border-radius:18px;align-items:center;gap:10px;margin:0;padding:8px 10px;transition:background-color .12s;display:flex}body[data-ds-dark-theme] .k74WwW_card{--plan-card-fill:var(--dsw-static-neutral-850);--plan-card-hover:var(--dsw-static-neutral-800)}.k74WwW_card:hover{background:var(--plan-card-hover)}.k74WwW_card:focus-visible
|
|
26
|
+
const css$1 = ".k74WwW_cards{flex-direction:column;gap:10px;display:flex}.k74WwW_card{--plan-card-fill:var(--dsw-static-neutral-50);--plan-card-hover:var(--dsw-static-neutral-100);box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l1);background:var(--plan-card-fill);width:100%;min-width:0;height:60px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;border-radius:18px;align-items:center;gap:10px;margin:0;padding:8px 10px;transition:background-color .12s;display:flex}body[data-ds-dark-theme] .k74WwW_card{--plan-card-fill:var(--dsw-static-neutral-850);--plan-card-hover:var(--dsw-static-neutral-800)}.k74WwW_card:hover{background:var(--plan-card-hover)}.k74WwW_card:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:3px}.k74WwW_cardIcon{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l1);background:var(--plan-card-fill);border-radius:10px;flex:none;place-items:center;width:40px;height:40px;display:grid}.k74WwW_cardDetails{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.k74WwW_cardTitle{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.k74WwW_cardDescription{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:16px;overflow:hidden}.k74WwW_cardOpen{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);background:var(--dsw-alias-button-floating-fill);border-radius:10px;flex:none;align-items:center;height:28px;padding:4px 8px;font-size:12px;line-height:18px;display:inline-flex}.k74WwW_reviewLink{color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:4px;padding:0;display:inline-flex}.k74WwW_reviewLink:hover{color:var(--dsw-alias-label-primary)}.k74WwW_reviewLink:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:3px}.k74WwW_preview{box-sizing:border-box;height:100%;padding:20px 24px 40px;position:relative;overflow:auto}.k74WwW_document{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;font-size:14px;line-height:1.75}.k74WwW_message{color:var(--dsw-alias-label-secondary);padding:24px;font-size:14px}.k74WwW_titleIcon{flex:none}@media (width<=767px){.k74WwW_preview{padding:16px 18px 32px}}";
|
|
27
27
|
const tagId$1 = "@deepseek-ai/dsh-client-ui-plan/PlanPreview.module.css";
|
|
28
28
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
29
29
|
const tag = document.createElement("style");
|
|
@@ -41,12 +41,10 @@ window.__ModuleLoader__.load({
|
|
|
41
41
|
"cardTitle": "k74WwW_cardTitle",
|
|
42
42
|
"cards": "k74WwW_cards",
|
|
43
43
|
"document": "k74WwW_document",
|
|
44
|
-
"iconButton": "k74WwW_iconButton",
|
|
45
44
|
"message": "k74WwW_message",
|
|
46
45
|
"preview": "k74WwW_preview",
|
|
47
46
|
"reviewLink": "k74WwW_reviewLink",
|
|
48
|
-
"titleIcon": "k74WwW_titleIcon"
|
|
49
|
-
"toolbar": "k74WwW_toolbar"
|
|
47
|
+
"titleIcon": "k74WwW_titleIcon"
|
|
50
48
|
};
|
|
51
49
|
//#endregion
|
|
52
50
|
//#region lib/types/client/PlanCard.js
|
|
@@ -56,13 +54,13 @@ window.__ModuleLoader__.load({
|
|
|
56
54
|
* @param props - Logged plan, localized copy, and Session-bound navigation.
|
|
57
55
|
* @returns keyboard-accessible plan cards, or null for a Turn without plans.
|
|
58
56
|
*/
|
|
59
|
-
function PlanCards({ turn,
|
|
60
|
-
const plans =
|
|
61
|
-
if (plans.length === 0) return null;
|
|
57
|
+
function PlanCards({ turn, usePlans, openPlan, t }) {
|
|
58
|
+
const plans = usePlans(String(turn.turn));
|
|
59
|
+
if (plans === void 0 || plans.length === 0) return null;
|
|
62
60
|
return (0, react_jsx_runtime.jsx)("div", {
|
|
63
61
|
className: PlanPreview_module_css_default.cards,
|
|
64
62
|
"data-plan-artifacts": true,
|
|
65
|
-
children: plans.map((
|
|
63
|
+
children: plans.map((plan) => (0, react_jsx_runtime.jsxs)("button", {
|
|
66
64
|
type: "button",
|
|
67
65
|
className: PlanPreview_module_css_default.card,
|
|
68
66
|
"data-plan-card": plan.callId,
|
|
@@ -98,19 +96,26 @@ window.__ModuleLoader__.load({
|
|
|
98
96
|
}
|
|
99
97
|
/**
|
|
100
98
|
* Open each pending plan automatically and retain a manual opener without answering it.
|
|
99
|
+
*
|
|
100
|
+
* The automatic open waits for a mounted Sidebar seat: a review that arrives
|
|
101
|
+
* while the Conversation is off screen mounts in the same commit as the seat,
|
|
102
|
+
* ahead of it, and the seat binds from its own effect. Reading the bound
|
|
103
|
+
* session through the hook opens once that binding exists.
|
|
101
104
|
* @param props - Review identity, Session store, localized copy, and navigation.
|
|
102
105
|
* @returns an opener for either logged or temporary plan text.
|
|
103
106
|
*/
|
|
104
|
-
function PlanReviewOpen({ review, requestKey, openReview, t, useStore, actions }) {
|
|
107
|
+
function PlanReviewOpen({ review, requestKey, openReview, useSidebarMounted, t, useStore, actions }) {
|
|
105
108
|
const identity = review.callId === void 0 ? `review:${requestKey}` : `call:${review.callId}`;
|
|
106
109
|
const opened = useStore((state) => state.opened[identity] === true);
|
|
110
|
+
const mounted = useSidebarMounted((session) => session !== void 0);
|
|
107
111
|
(0, react.useEffect)(() => {
|
|
108
|
-
if (opened) return;
|
|
112
|
+
if (opened || !mounted) return;
|
|
109
113
|
openReview(review, requestKey);
|
|
110
114
|
actions.markOpened(identity);
|
|
111
115
|
}, [
|
|
112
116
|
identity,
|
|
113
117
|
opened,
|
|
118
|
+
mounted,
|
|
114
119
|
openReview,
|
|
115
120
|
review,
|
|
116
121
|
requestKey,
|
|
@@ -124,7 +129,7 @@ window.__ModuleLoader__.load({
|
|
|
124
129
|
onClick: () => {
|
|
125
130
|
openReview(review, requestKey);
|
|
126
131
|
},
|
|
127
|
-
children: [t("preview.full"), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
132
|
+
children: [t("preview.full"), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, { size: 14 })]
|
|
128
133
|
});
|
|
129
134
|
}
|
|
130
135
|
//#endregion
|
|
@@ -166,7 +171,7 @@ window.__ModuleLoader__.load({
|
|
|
166
171
|
//#region lib/types/client/PlanPreview.js
|
|
167
172
|
/** Read-only Markdown viewer for logged plans and temporary review documents. */
|
|
168
173
|
/**
|
|
169
|
-
* Render the submitted plan with its complete Markdown
|
|
174
|
+
* Render the submitted plan with its complete Markdown.
|
|
170
175
|
* @param props - Framework-bound tab identity, resource, and copy.
|
|
171
176
|
* @returns the plan document or a localized loading/failure state.
|
|
172
177
|
*/
|
|
@@ -179,7 +184,12 @@ window.__ModuleLoader__.load({
|
|
|
179
184
|
const labels = (0, react.useMemo)(() => ({
|
|
180
185
|
code: {
|
|
181
186
|
copyLabel: t("copy"),
|
|
182
|
-
copiedLabel: t("copied")
|
|
187
|
+
copiedLabel: t("copied"),
|
|
188
|
+
toolbarLabels: {
|
|
189
|
+
codeLabel: t("codeBlock.title"),
|
|
190
|
+
wrapLabel: t("codeBlock.wrap"),
|
|
191
|
+
unwrapLabel: t("codeBlock.unwrap")
|
|
192
|
+
}
|
|
183
193
|
},
|
|
184
194
|
footnotes: t("markdown.footnotes")
|
|
185
195
|
}), [t]);
|
|
@@ -188,44 +198,33 @@ window.__ModuleLoader__.load({
|
|
|
188
198
|
role: "status",
|
|
189
199
|
children: [temporary ? t("preview.expired") : resource.status === "none" ? t("preview.unavailable") : resource.status === "failed" ? t("preview.failed") : t("preview.loading"), !temporary && resource.failure !== void 0 && (0, react_jsx_runtime.jsx)("p", { children: planFailureLine(t, resource.failure) })]
|
|
190
200
|
});
|
|
191
|
-
return (0, react_jsx_runtime.
|
|
201
|
+
return (0, react_jsx_runtime.jsx)("section", {
|
|
192
202
|
className: PlanPreview_module_css_default.preview,
|
|
193
203
|
"data-plan-preview": "callId" in plan ? plan.callId : tab.tab.navigation.address,
|
|
194
204
|
"aria-label": plan.title,
|
|
195
|
-
children:
|
|
196
|
-
className: PlanPreview_module_css_default.toolbar,
|
|
197
|
-
children: (0, react_jsx_runtime.jsx)("button", {
|
|
198
|
-
type: "button",
|
|
199
|
-
className: PlanPreview_module_css_default.iconButton,
|
|
200
|
-
"aria-label": t("copy"),
|
|
201
|
-
onClick: () => {
|
|
202
|
-
(0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(plan.markdown);
|
|
203
|
-
},
|
|
204
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, {})
|
|
205
|
-
})
|
|
206
|
-
}), (0, react_jsx_runtime.jsx)("div", {
|
|
205
|
+
children: (0, react_jsx_runtime.jsx)("div", {
|
|
207
206
|
className: PlanPreview_module_css_default.document,
|
|
208
207
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
|
|
209
208
|
text: plan.markdown,
|
|
210
209
|
labels
|
|
211
210
|
})
|
|
212
|
-
})
|
|
211
|
+
})
|
|
213
212
|
});
|
|
214
213
|
}
|
|
215
214
|
/**
|
|
216
|
-
* Display a
|
|
215
|
+
* Display a plain file icon and the heading in its tab after resource recovery.
|
|
217
216
|
* @param props - Framework-bound tab identity and resource reader.
|
|
218
|
-
* @returns a decorative
|
|
217
|
+
* @returns a decorative file icon followed by the recovered title or initial localized label.
|
|
219
218
|
*/
|
|
220
219
|
function PlanTitle({ useTabInfo, useResource }) {
|
|
221
220
|
const tab = useTabInfo();
|
|
222
221
|
const resource = useResource(tab.tab.navigation.address);
|
|
223
222
|
const params = tab.tab.navigation.params;
|
|
224
223
|
const plan = isReviewPreviewAddress(tab.tab.navigation.address) ? params !== void 0 && "planReview" in params ? params.planReview : void 0 : resource.value;
|
|
225
|
-
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
224
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
225
|
+
kind: "other",
|
|
226
|
+
size: 16,
|
|
227
|
+
className: PlanPreview_module_css_default.titleIcon
|
|
229
228
|
}), plan?.title ?? tab.tab.title] });
|
|
230
229
|
}
|
|
231
230
|
//#endregion
|
|
@@ -295,7 +294,7 @@ window.__ModuleLoader__.load({
|
|
|
295
294
|
},
|
|
296
295
|
callId: parts[1]
|
|
297
296
|
};
|
|
298
|
-
if (parts.length === 5 && parts[0] === "subagent" && (parts[3] === "one-shot" || parts[3] === "continuable")) return {
|
|
297
|
+
if (parts.length === 5 && parts[0] === "subagent" && (parts[3] === "one-shot" || parts[3] === "continuable" || parts[3] === "unknown")) return {
|
|
299
298
|
session: {
|
|
300
299
|
kind: "subagent",
|
|
301
300
|
parentSessionId: parts[1],
|
|
@@ -477,7 +476,7 @@ window.__ModuleLoader__.load({
|
|
|
477
476
|
}
|
|
478
477
|
//#endregion
|
|
479
478
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-plan/src/client/PlanModeControl.module.css.mjs
|
|
480
|
-
const css = ".rS3zOq_wrap{align-items:center;gap:6px;display:inline-flex}.rS3zOq_chip{
|
|
479
|
+
const css = ".rS3zOq_wrap{align-items:center;gap:6px;display:inline-flex}.rS3zOq_chip{background:var(--dsw-alias-state-business-tertiary);min-width:34px;height:28px;color:var(--dsw-alias-state-business-primary);cursor:pointer;border:none;border-radius:14px;align-items:center;gap:4px;padding:0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}.rS3zOq_chip:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-state-business-tertiary), var(--dsw-alias-state-business-primary) 6%)}.rS3zOq_chip:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.rS3zOq_chip:disabled{opacity:.6;cursor:default}.rS3zOq_glyph{color:currentColor;flex:none;width:14px;height:14px;display:inline-flex}.rS3zOq_hoverGlyph,.rS3zOq_chip:hover:not(:disabled) .rS3zOq_restGlyph,.rS3zOq_chip:focus-visible .rS3zOq_restGlyph{display:none}.rS3zOq_chip:hover:not(:disabled) .rS3zOq_hoverGlyph,.rS3zOq_chip:focus-visible .rS3zOq_hoverGlyph{display:block}.rS3zOq_error{color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}";
|
|
481
480
|
const tagId = "@deepseek-ai/dsh-client-ui-plan/PlanModeControl.module.css";
|
|
482
481
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
483
482
|
const tag = document.createElement("style");
|
|
@@ -488,8 +487,10 @@ window.__ModuleLoader__.load({
|
|
|
488
487
|
}
|
|
489
488
|
var PlanModeControl_module_css_default = {
|
|
490
489
|
"chip": "rS3zOq_chip",
|
|
491
|
-
"close": "rS3zOq_close",
|
|
492
490
|
"error": "rS3zOq_error",
|
|
491
|
+
"glyph": "rS3zOq_glyph",
|
|
492
|
+
"hoverGlyph": "rS3zOq_hoverGlyph",
|
|
493
|
+
"restGlyph": "rS3zOq_restGlyph",
|
|
493
494
|
"wrap": "rS3zOq_wrap"
|
|
494
495
|
};
|
|
495
496
|
//#endregion
|
|
@@ -534,11 +535,17 @@ window.__ModuleLoader__.load({
|
|
|
534
535
|
title: t("chip.on.title"),
|
|
535
536
|
disabled: locked || leaving,
|
|
536
537
|
onClick: off,
|
|
537
|
-
children: [
|
|
538
|
-
className: PlanModeControl_module_css_default.
|
|
538
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
539
|
+
className: PlanModeControl_module_css_default.glyph,
|
|
539
540
|
"aria-hidden": true,
|
|
540
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
541
|
-
|
|
541
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlanOutlineRegular, {
|
|
542
|
+
className: PlanModeControl_module_css_default.restGlyph,
|
|
543
|
+
size: 14
|
|
544
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseCircleFillRegular, {
|
|
545
|
+
className: PlanModeControl_module_css_default.hoverGlyph,
|
|
546
|
+
size: 14
|
|
547
|
+
})]
|
|
548
|
+
}), t("chip.label")]
|
|
542
549
|
}), error !== null && (0, react_jsx_runtime.jsx)("span", {
|
|
543
550
|
className: PlanModeControl_module_css_default.error,
|
|
544
551
|
role: "status",
|
|
@@ -552,7 +559,7 @@ window.__ModuleLoader__.load({
|
|
|
552
559
|
/** `plan` namespace dictionaries (the composer plan chip's copy). */
|
|
553
560
|
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
554
561
|
const zh = {
|
|
555
|
-
"chip.label": "
|
|
562
|
+
"chip.label": "计划",
|
|
556
563
|
"preview.title": "计划",
|
|
557
564
|
"preview.document": "计划 · Markdown",
|
|
558
565
|
"preview.action": "打开",
|
|
@@ -566,11 +573,9 @@ window.__ModuleLoader__.load({
|
|
|
566
573
|
"preview.notFound": "未找到这份计划",
|
|
567
574
|
"preview.unavailable": "计划预览不可用",
|
|
568
575
|
"preview.expired": "临时计划预览已失效,请从仍在等待审批的卡片重新打开。",
|
|
569
|
-
"chip.on.aria": "
|
|
570
|
-
"chip.on.title": "
|
|
571
|
-
"chip.
|
|
572
|
-
"chip.off.title": "plan mode 已关闭 — 点击开启(/plan)",
|
|
573
|
-
"chip.exitFailed": "退出 plan mode 失败"
|
|
576
|
+
"chip.on.aria": "计划模式已开启,按下关闭",
|
|
577
|
+
"chip.on.title": "计划模式已开启 — 点击关闭(/plan off)",
|
|
578
|
+
"chip.exitFailed": "退出计划模式失败"
|
|
574
579
|
};
|
|
575
580
|
/** English dictionary, checked complete against the zh key set. */
|
|
576
581
|
const en = {
|
|
@@ -590,8 +595,6 @@ window.__ModuleLoader__.load({
|
|
|
590
595
|
"preview.expired": "This temporary plan preview has expired. Reopen it from the pending review card.",
|
|
591
596
|
"chip.on.aria": "Plan mode on, press to turn off",
|
|
592
597
|
"chip.on.title": "Plan mode on — click to turn off (/plan off)",
|
|
593
|
-
"chip.off.aria": "Plan mode off, press to turn on",
|
|
594
|
-
"chip.off.title": "Plan mode off — click to turn on (/plan)",
|
|
595
598
|
"chip.exitFailed": "Failed to exit plan mode"
|
|
596
599
|
};
|
|
597
600
|
//#endregion
|
|
@@ -641,7 +644,7 @@ window.__ModuleLoader__.load({
|
|
|
641
644
|
kind: "subagent",
|
|
642
645
|
...child
|
|
643
646
|
};
|
|
644
|
-
ctx.sidebarRight.
|
|
647
|
+
ctx.sidebarRight.openResource(planAddress({
|
|
645
648
|
session,
|
|
646
649
|
callId
|
|
647
650
|
}));
|
|
@@ -652,23 +655,38 @@ window.__ModuleLoader__.load({
|
|
|
652
655
|
name: "conversation.chat.turnTail",
|
|
653
656
|
id: previewId,
|
|
654
657
|
locale: NS,
|
|
655
|
-
inject:
|
|
658
|
+
inject: (sessionId) => {
|
|
659
|
+
const binding = ctx.sessions.binding(sessionId);
|
|
660
|
+
if (binding === void 0) throw new Error(`ui-plan: unknown session "${sessionId}"`);
|
|
661
|
+
const chat = ctx.uiConversation.binding(binding).target("chat");
|
|
662
|
+
return {
|
|
663
|
+
...open(sessionId),
|
|
664
|
+
keyedHooks: { plans: (turn) => {
|
|
665
|
+
const snapshot = chat.getSnapshot();
|
|
666
|
+
if (snapshot === void 0) throw new Error("ui-plan: Chat target is unavailable");
|
|
667
|
+
return snapshot.nodes.turnDataSource(Number(turn), "submitted-plan");
|
|
668
|
+
} }
|
|
669
|
+
};
|
|
670
|
+
}
|
|
656
671
|
}, PlanCards));
|
|
657
672
|
ctx.slots.inject("conversation.plan-review.actions", () => ctx.slots.register({
|
|
658
673
|
name: "conversation.plan-review.actions",
|
|
659
674
|
id: previewId,
|
|
660
675
|
locale: NS,
|
|
661
676
|
store: reviewStore,
|
|
662
|
-
inject: (sessionId) => ({
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
677
|
+
inject: (sessionId) => ({
|
|
678
|
+
openReview: (review, requestKey) => {
|
|
679
|
+
if (review.callId !== void 0) {
|
|
680
|
+
open(sessionId).openPlan(review.callId);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
ctx.sidebarRight.openResource(reviewPreviewAddress(sessionId, `${reviewWindow}:${requestKey}`), { params: { planReview: {
|
|
684
|
+
markdown: review.plan,
|
|
685
|
+
title: (0, _deepseek_ai_dsh_client_ui_primitives.extractMarkdownPlainText)(review.plan, { mode: "first-line" })
|
|
686
|
+
} } });
|
|
687
|
+
},
|
|
688
|
+
hooks: { sidebarMounted: ctx.sidebarRight.mounted }
|
|
689
|
+
})
|
|
672
690
|
}, PlanReviewOpen));
|
|
673
691
|
ctx.slots.inject("sidebar.right.pane.tab", () => ctx.slots.register({
|
|
674
692
|
name: "sidebar.right.pane.tab",
|
|
@@ -1,26 +1,45 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
2
|
+
import type { SubmittedPlan } from './plan.ts';
|
|
3
|
+
import type { HostObservable, InjectFace, PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
4
|
import type { ToolCallId } from '@deepseek-ai/dsh-llm/brand';
|
|
5
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
6
|
import type { createPlanReviewStore } from './review-store.ts';
|
|
4
7
|
/** Session-bound navigation for logged plans. */
|
|
5
8
|
export interface PlanOpenInjected {
|
|
6
9
|
/** Open or focus the exact submitted plan. */
|
|
7
10
|
openPlan: (callId: ToolCallId) => void;
|
|
8
11
|
}
|
|
12
|
+
/** Turn-keyed submitted plans and Session-bound navigation. */
|
|
13
|
+
export interface PlanCardsInjected extends PlanOpenInjected {
|
|
14
|
+
keyedHooks: {
|
|
15
|
+
/** Resolve only this Turn's submitted plans, in invocation order. */
|
|
16
|
+
plans: (turn: string) => ObservableSnapshot<readonly SubmittedPlan[]>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
9
19
|
/** Session-bound preview navigation for one pending review. */
|
|
10
20
|
export interface PlanReviewOpenInjected {
|
|
11
21
|
/** Open the logged plan, or the request's temporary document when no invocation exists. */
|
|
12
22
|
openReview: (review: PropsRuntime<'conversation.plan-review.actions'>['review'], requestKey: string) => void;
|
|
23
|
+
readonly hooks: {
|
|
24
|
+
/** The session whose right Sidebar seat is mounted; `undefined` while none is on screen. */
|
|
25
|
+
readonly sidebarMounted: HostObservable<SessionId | undefined>;
|
|
26
|
+
};
|
|
13
27
|
}
|
|
14
28
|
/**
|
|
15
29
|
* Render the completed Turn's submitted plans in invocation order.
|
|
16
30
|
* @param props - Logged plan, localized copy, and Session-bound navigation.
|
|
17
31
|
* @returns keyboard-accessible plan cards, or null for a Turn without plans.
|
|
18
32
|
*/
|
|
19
|
-
export declare function PlanCards({ turn,
|
|
33
|
+
export declare function PlanCards({ turn, usePlans, openPlan, t }: PropsRuntime<'conversation.chat.turnTail'> & InjectFace<PlanCardsInjected> & PropsLocale<'plan'>): import("react").JSX.Element | null;
|
|
20
34
|
/**
|
|
21
35
|
* Open each pending plan automatically and retain a manual opener without answering it.
|
|
36
|
+
*
|
|
37
|
+
* The automatic open waits for a mounted Sidebar seat: a review that arrives
|
|
38
|
+
* while the Conversation is off screen mounts in the same commit as the seat,
|
|
39
|
+
* ahead of it, and the seat binds from its own effect. Reading the bound
|
|
40
|
+
* session through the hook opens once that binding exists.
|
|
22
41
|
* @param props - Review identity, Session store, localized copy, and navigation.
|
|
23
42
|
* @returns an opener for either logged or temporary plan text.
|
|
24
43
|
*/
|
|
25
|
-
export declare function PlanReviewOpen({ review, requestKey, openReview, t, useStore, actions }: PropsRuntime<'conversation.plan-review.actions'> & InjectFace<PlanReviewOpenInjected> & PropsLocale<'plan'> & PropsStore<ReturnType<typeof createPlanReviewStore>>): import("react").JSX.Element;
|
|
44
|
+
export declare function PlanReviewOpen({ review, requestKey, openReview, useSidebarMounted, t, useStore, actions }: PropsRuntime<'conversation.plan-review.actions'> & InjectFace<PlanReviewOpenInjected> & PropsLocale<'plan'> & PropsStore<ReturnType<typeof createPlanReviewStore>>): import("react").JSX.Element;
|
|
26
45
|
//# sourceMappingURL=PlanCard.d.ts.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
2
|
type PlanPreviewProps = PropsRuntime<'sidebar.right.pane.tab'> & PropsLocale<'plan'>;
|
|
3
3
|
/**
|
|
4
|
-
* Render the submitted plan with its complete Markdown
|
|
4
|
+
* Render the submitted plan with its complete Markdown.
|
|
5
5
|
* @param props - Framework-bound tab identity, resource, and copy.
|
|
6
6
|
* @returns the plan document or a localized loading/failure state.
|
|
7
7
|
*/
|
|
8
8
|
export declare function PlanPreview({ useTabInfo, useResource, t }: PlanPreviewProps): import("react").JSX.Element;
|
|
9
9
|
/**
|
|
10
|
-
* Display a
|
|
10
|
+
* Display a plain file icon and the heading in its tab after resource recovery.
|
|
11
11
|
* @param props - Framework-bound tab identity and resource reader.
|
|
12
|
-
* @returns a decorative
|
|
12
|
+
* @returns a decorative file icon followed by the recovered title or initial localized label.
|
|
13
13
|
*/
|
|
14
14
|
export declare function PlanTitle({ useTabInfo, useResource }: PropsRuntime<'sidebar.right.pane.tab.title'>): import("react").JSX.Element;
|
|
15
15
|
export {};
|
|
@@ -17,8 +17,6 @@ export declare const zh: {
|
|
|
17
17
|
'preview.expired': string;
|
|
18
18
|
'chip.on.aria': string;
|
|
19
19
|
'chip.on.title': string;
|
|
20
|
-
'chip.off.aria': string;
|
|
21
|
-
'chip.off.title': string;
|
|
22
20
|
'chip.exitFailed': string;
|
|
23
21
|
};
|
|
24
22
|
/** The plan namespace key union. */
|
|
@@ -41,8 +39,6 @@ export declare const en: {
|
|
|
41
39
|
'preview.expired': string;
|
|
42
40
|
'chip.on.aria': string;
|
|
43
41
|
'chip.on.title': string;
|
|
44
|
-
'chip.off.aria': string;
|
|
45
|
-
'chip.off.title': string;
|
|
46
42
|
'chip.exitFailed': string;
|
|
47
43
|
};
|
|
48
44
|
//# sourceMappingURL=locales.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-plan",
|
|
3
3
|
"description": "Plan mode controls, persistent transcript plan cards, and sidebar Markdown previews",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -42,32 +42,32 @@
|
|
|
42
42
|
},
|
|
43
43
|
"license": "MIT",
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@deepseek-ai/cordis": "
|
|
45
|
+
"@deepseek-ai/cordis": "~4.0.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "~18.3.1",
|
|
49
49
|
"react": "^18.2.0",
|
|
50
|
-
"@deepseek-ai/dsh-client-store": "
|
|
51
|
-
"@deepseek-ai/dsh-api-remotes": "
|
|
52
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
53
|
-
"@deepseek-ai/dsh-client-test-runtime": "
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-conversation": "
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-primitives": "
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-client-ui-renderer": "
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-client-ui-
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-
|
|
64
|
-
"@deepseek-ai/dsh-client-
|
|
65
|
-
"@deepseek-ai/dsh-client-
|
|
66
|
-
"@deepseek-ai/dsh-typert-protocol": "
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"@deepseek-ai/dsh-
|
|
69
|
-
"@deepseek-ai/dsh-
|
|
70
|
-
"@deepseek-ai/
|
|
50
|
+
"@deepseek-ai/dsh-client-store": "0.1.7-alpha.2",
|
|
51
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.7-alpha.2",
|
|
52
|
+
"@deepseek-ai/dsh-client-locale": "0.1.7-alpha.2",
|
|
53
|
+
"@deepseek-ai/dsh-client-test-runtime": "0.1.7-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-alpha.2",
|
|
56
|
+
"@deepseek-ai/dsh-plan-mode": "0.1.7-alpha.2",
|
|
57
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-alpha.2",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.7-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.1.7-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-sidebar-right": "0.1.7-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-session": "0.1.7-alpha.2",
|
|
64
|
+
"@deepseek-ai/dsh-client-resources": "0.1.7-alpha.2",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-user-questions": "0.1.7-alpha.2",
|
|
66
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.7-alpha.2",
|
|
67
|
+
"@deepseek-ai/dsh-session": "0.1.7-alpha.2",
|
|
68
|
+
"@deepseek-ai/dsh-llm": "0.1.7-alpha.2",
|
|
69
|
+
"@deepseek-ai/dsh-tools": "0.1.7-alpha.2",
|
|
70
|
+
"@deepseek-ai/dsh-util-crypto": "0.1.7-alpha.2"
|
|
71
71
|
},
|
|
72
72
|
"files": [
|
|
73
73
|
"lib/index.js",
|