relay-dsh-plugin-claude 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -13
- package/README.zh.md +15 -13
- package/cordis.patch.yml +2 -0
- package/docs/spec/claude-native-session-import.md +16 -3
- package/lib/client.js +86 -34
- package/lib/client.js.map +1 -1
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/yangbobo2021/relay-dsh-plugin-claude/stargazers)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
9
|
-
[](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.
|
|
9
|
+
[](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.5)
|
|
10
10
|
|
|
11
11
|
English | [中文](README.zh.md)
|
|
12
12
|
|
|
@@ -109,7 +109,7 @@ Use `@latest` to install the current stable release:
|
|
|
109
109
|
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@latest
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
At the time of writing, `latest` resolves to stable version `0.1.
|
|
112
|
+
At the time of writing, `latest` resolves to stable version `0.1.5`. The linked
|
|
113
113
|
npm page is the source of truth for the current version.
|
|
114
114
|
|
|
115
115
|
#### npm prerelease (recommended during DSH preview)
|
|
@@ -122,7 +122,7 @@ contains the latest model-selection synchronization fix:
|
|
|
122
122
|
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@next
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
At the time of writing, `next` resolves to `0.1.
|
|
125
|
+
At the time of writing, `next` resolves to `0.1.5`.
|
|
126
126
|
|
|
127
127
|
#### GitHub development build
|
|
128
128
|
|
|
@@ -136,7 +136,7 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/rel
|
|
|
136
136
|
full Commit SHA instead. For example:
|
|
137
137
|
|
|
138
138
|
```bash
|
|
139
|
-
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.
|
|
139
|
+
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.5
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
The official DSH CLI initializes the `web` Profile if it does not exist, asks
|
|
@@ -173,8 +173,11 @@ activates the bundle and registers the managed **Claude Code** mode automaticall
|
|
|
173
173
|
|
|
174
174
|
### 5. Import an existing Claude terminal Session
|
|
175
175
|
|
|
176
|
-
1.
|
|
177
|
-
|
|
176
|
+
1. Select **Import sessions...** below the Workspace list, then choose **Import
|
|
177
|
+
from Claude**.
|
|
178
|
+
2. In the dialog, confirm or change the visible **Target Workspace**, then select
|
|
179
|
+
**Scan Sessions**. The current Session owner or recent Workspace is only the
|
|
180
|
+
initial selection; scanning never starts before this confirmation.
|
|
178
181
|
3. Review the full Session IDs, titles, source paths, activity times, and import
|
|
179
182
|
status. Select one, several, or all Sessions.
|
|
180
183
|
4. Select **Import selected**, then open the imported DSH Session.
|
|
@@ -183,7 +186,7 @@ activates the bundle and registers the managed **Claude Code** mode automaticall
|
|
|
183
186
|
|
|
184
187
|
The selector uses the Claude Agent SDK's public Session APIs and matches the
|
|
185
188
|
terminal `/resume` scope. It excludes worktrees, SDK/headless Sessions,
|
|
186
|
-
already-bound Sessions, and Sessions outside the
|
|
189
|
+
already-bound Sessions, and Sessions outside the explicitly selected Workspace.
|
|
187
190
|
The imported history is a one-time presentation snapshot of user text, visible
|
|
188
191
|
assistant text and thinking, and completed textual tool activity. Unknown or
|
|
189
192
|
private blocks are skipped; Claude's source transcript is never modified.
|
|
@@ -271,12 +274,13 @@ This repository was designed and compatibility-tested in
|
|
|
271
274
|
long-running agent work, external-event delivery, reusable DSH workbench views,
|
|
272
275
|
and multiple conversation backends.
|
|
273
276
|
|
|
274
|
-
The plugin is independently installable.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
The plugin is independently installable. Its only Relay package dependency is
|
|
278
|
+
the provider-neutral session import hub, which the package manager installs
|
|
279
|
+
automatically. It has no runtime dependency on the Relay application, Relay
|
|
280
|
+
Events, or another feature plugin. It does not replace the official DSH layout
|
|
281
|
+
or install Files and Terminal views. This separation lets a user install only
|
|
282
|
+
Claude while the broader Relay project can compose Codex, Claude, events, waits,
|
|
283
|
+
monitors, and workbench extensions when those capabilities are needed.
|
|
280
284
|
|
|
281
285
|
Explore or star Relay to follow that broader work:
|
|
282
286
|
<https://github.com/yangbobo2021/Relay>.
|
package/README.zh.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/yangbobo2021/relay-dsh-plugin-claude/stargazers)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
9
|
-
[](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.
|
|
9
|
+
[](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.5)
|
|
10
10
|
|
|
11
11
|
[English](README.md) | 中文
|
|
12
12
|
|
|
@@ -104,7 +104,7 @@ claude
|
|
|
104
104
|
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@latest
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
本文更新时,`latest` 指向稳定版 `0.1.
|
|
107
|
+
本文更新时,`latest` 指向稳定版 `0.1.5`。最新版本请以链接中的 npm 页面
|
|
108
108
|
为准。
|
|
109
109
|
|
|
110
110
|
#### npm 预发布版(DSH 预览阶段推荐)
|
|
@@ -116,7 +116,7 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude
|
|
|
116
116
|
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@next
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
本文更新时,`next` 指向 `0.1.
|
|
119
|
+
本文更新时,`next` 指向 `0.1.5`。
|
|
120
120
|
|
|
121
121
|
#### GitHub 开发版
|
|
122
122
|
|
|
@@ -130,7 +130,7 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/rel
|
|
|
130
130
|
SHA。例如:
|
|
131
131
|
|
|
132
132
|
```bash
|
|
133
|
-
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.
|
|
133
|
+
npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.5
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
官方 DSH CLI 会在需要时初始化 `web` Profile,通过 `pnpm` 安装所选软件包和
|
|
@@ -164,15 +164,16 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 web
|
|
|
164
164
|
|
|
165
165
|
### 5. 导入已有的 Claude 终端会话
|
|
166
166
|
|
|
167
|
-
1.
|
|
168
|
-
2.
|
|
167
|
+
1. 点击工作区列表下方的 **导入会话...**,然后选择 **从 Claude 导入**。
|
|
168
|
+
2. 在弹窗中确认或切换可见的 **目标 Workspace**,然后点击 **扫描会话**。
|
|
169
|
+
当前 Session 所属 Workspace 或最近 Workspace 只作为初始选项;确认前不会开始扫描。
|
|
169
170
|
3. 检查完整 Session ID、标题、源路径、活动时间和导入状态,然后选择一个、
|
|
170
171
|
多个或全部会话。
|
|
171
172
|
4. 点击 **导入所选会话**,再打开导入后的 DSH Session。
|
|
172
173
|
5. 发送下一条消息,确认它继续的是同一个原生 Claude Session。
|
|
173
174
|
|
|
174
175
|
选择器只使用 Claude Agent SDK 的公开 Session API,其范围与终端 `/resume`
|
|
175
|
-
一致。它会排除 worktree、SDK/headless
|
|
176
|
+
一致。它会排除 worktree、SDK/headless、已经绑定以及不属于用户所选精确工作区
|
|
176
177
|
的 Session。导入历史是一次性的展示快照,包含用户文本、可见的助手文本与
|
|
177
178
|
thinking,以及已有结果的文本工具活动。未知或私有块会被跳过,Claude 源转录
|
|
178
179
|
不会被修改。
|
|
@@ -244,10 +245,11 @@ PNG;工作区中不会产生同名 PNG,也不会加载外部资源或执行
|
|
|
244
245
|
兼容性验证。Relay 是面向长时间运行 Agent、外部事件投递、可复用 DSH
|
|
245
246
|
工作台视图和多种对话后端的开源项目。
|
|
246
247
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
Monitor
|
|
248
|
+
本插件可以独立安装。唯一依赖的 Relay 包是由包管理器自动安装的中立“会话
|
|
249
|
+
导入中心”;运行时不依赖 Relay 应用、Relay Events 或其他功能插件,也不会
|
|
250
|
+
替换 DSH 官方布局或安装 Files、Terminal 视图。用户可以只安装 Claude;需要
|
|
251
|
+
时,Relay 项目则可以进一步组合 Codex、Claude、事件、Wait、Monitor 和工作台
|
|
252
|
+
扩展。
|
|
251
253
|
|
|
252
254
|
可以访问或 Star Relay 仓库,关注这些更完整的工作:
|
|
253
255
|
<https://github.com/yangbobo2021/Relay>。
|
|
@@ -309,8 +311,8 @@ DSH_ROOT=/path/to/deepseek-harness npm run verify
|
|
|
309
311
|
npm pack
|
|
310
312
|
```
|
|
311
313
|
|
|
312
|
-
`npm run verify`
|
|
313
|
-
|
|
314
|
+
`npm run verify` 会执行类型检查、测试和生产构建。边界测试仅允许中立的会话
|
|
315
|
+
导入中心依赖,并会阻止插件意外增加对 Relay 应用或其他功能插件的运行时依赖。
|
|
314
316
|
|
|
315
317
|
## 反馈
|
|
316
318
|
|
package/cordis.patch.yml
CHANGED
|
@@ -26,6 +26,14 @@ promise that another Claude client is no longer writing it.
|
|
|
26
26
|
|
|
27
27
|
## Inventory and selection
|
|
28
28
|
|
|
29
|
+
The provider-neutral session import hub owns one sidebar footer action. Claude
|
|
30
|
+
registers one renderless provider descriptor with the localized label **Import
|
|
31
|
+
from Claude**, the Claude mark, order `20`, and an `open` callback. Selecting
|
|
32
|
+
that menu row closes the hub menu and presents Claude's visible Workspace
|
|
33
|
+
selector. The current Session owner, then the recent Workspace, is only an
|
|
34
|
+
initial choice. The user may change it, and the plugin must not scan until the
|
|
35
|
+
user invokes **Scan Sessions**.
|
|
36
|
+
|
|
29
37
|
Each candidate exposes the full native Session ID, deterministic title, source
|
|
30
38
|
path, source `lastModified`, and either `ready` or `recoverable` status. The
|
|
31
39
|
ordering is descending source activity time with Session ID as a deterministic
|
|
@@ -104,11 +112,16 @@ Delivery requires all of the following evidence:
|
|
|
104
112
|
Workspace isolation, deterministic ordering, selection atomicity, source
|
|
105
113
|
revalidation, projection, one-to-one durability, concurrency, retry, and the
|
|
106
114
|
no-replacement resume rule.
|
|
107
|
-
3. Client tests cover
|
|
108
|
-
|
|
115
|
+
3. Client tests cover provider registration and disposal, explicit menu-driven
|
|
116
|
+
opening, visible Workspace choice, no automatic scan, exact selected path,
|
|
117
|
+
candidate selection, request payloads, chunked NDJSON progress, error
|
|
118
|
+
handling, disabled empty submission, and refresh order.
|
|
109
119
|
4. A real installed SDK lists and reads a native terminal Session using only the
|
|
110
120
|
public APIs.
|
|
111
121
|
5. Official DSH imports that Session, displays the projected history and title,
|
|
112
122
|
and sends the next turn to the same complete native Session ID.
|
|
113
|
-
6.
|
|
123
|
+
6. A combined Claude + Codex browser check and screenshots prove one hub action
|
|
124
|
+
presents both explicit provider rows in expanded and collapsed sidebars and
|
|
125
|
+
that the selector dialog is readable.
|
|
126
|
+
7. Typecheck, the full repository test suite, build, package-content inspection,
|
|
114
127
|
and remote CI all pass.
|
package/lib/client.js
CHANGED
|
@@ -139,7 +139,7 @@ window.__ModuleLoader__.load({
|
|
|
139
139
|
}
|
|
140
140
|
//#endregion
|
|
141
141
|
//#region src/client/claude-session-import-ui-policy.mjs
|
|
142
|
-
function claudeSessionImportUiPolicy(phase, selected = 0, failed = 0) {
|
|
142
|
+
function claudeSessionImportUiPolicy(phase, selected = 0, failed = 0, hasWorkspace = true) {
|
|
143
143
|
if (phase === "importing") return Object.freeze({
|
|
144
144
|
canClose: false,
|
|
145
145
|
primary: "importing",
|
|
@@ -151,6 +151,12 @@ window.__ModuleLoader__.load({
|
|
|
151
151
|
primary: "import-selected",
|
|
152
152
|
primaryDisabled: selected === 0
|
|
153
153
|
});
|
|
154
|
+
if (phase === "select-workspace") return Object.freeze({
|
|
155
|
+
canClose: true,
|
|
156
|
+
secondary: "cancel",
|
|
157
|
+
primary: "scan",
|
|
158
|
+
primaryDisabled: !hasWorkspace
|
|
159
|
+
});
|
|
154
160
|
if (phase === "error") return Object.freeze({
|
|
155
161
|
canClose: true,
|
|
156
162
|
secondary: "cancel",
|
|
@@ -177,7 +183,7 @@ window.__ModuleLoader__.load({
|
|
|
177
183
|
}
|
|
178
184
|
//#endregion
|
|
179
185
|
//#region \0relay-css-module:./src/client/ClaudeSessionImportAction.module.css.mjs
|
|
180
|
-
const css$1 = ".
|
|
186
|
+
const css$1 = "._8iKb1W_dialog{width:min(700px,100vw - 32px)}._8iKb1W_workspaceChoice{flex-direction:column;gap:7px;min-width:0;display:flex}._8iKb1W_workspaceChoice label{color:var(--dsw-alias-label-primary);letter-spacing:0;font-size:13px;font-weight:500;line-height:20px}._8iKb1W_workspaceChoice select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-l1);width:100%;min-height:36px;color:var(--dsw-alias-label-primary);font:inherit;letter-spacing:0;border-radius:6px;padding:0 32px 0 10px;font-size:13px}._8iKb1W_workspaceChoice select:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}._8iKb1W_workspacePath{overflow-wrap:anywhere;color:var(--dsw-alias-label-tertiary);letter-spacing:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:17px}._8iKb1W_body{flex-direction:column;gap:18px;min-height:128px;display:flex}._8iKb1W_workspace{border-bottom:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:3px;min-width:0;padding-bottom:12px;display:flex}._8iKb1W_workspace strong{overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);letter-spacing:0;font-size:14px;font-weight:500;line-height:20px}._8iKb1W_workspace span{color:var(--dsw-alias-label-tertiary);letter-spacing:0;overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:17px;overflow:hidden}._8iKb1W_message,._8iKb1W_error,._8iKb1W_success,._8iKb1W_partial{letter-spacing:0;margin:0;font-size:13px;line-height:20px}._8iKb1W_message{color:var(--dsw-alias-label-secondary)}._8iKb1W_error,._8iKb1W_dangerValue{color:var(--dsw-alias-state-error-primary)}._8iKb1W_success,._8iKb1W_accentValue{color:var(--dsw-alias-state-success-primary)}._8iKb1W_partial{color:var(--dsw-alias-state-error-secondary)}._8iKb1W_metrics{border-top:1px solid var(--dsw-alias-border-l2);border-left:1px solid var(--dsw-alias-border-l2);grid-template-columns:repeat(2,minmax(0,1fr));margin:0;display:grid}._8iKb1W_summary{flex-direction:column;gap:14px;min-width:0;display:flex}._8iKb1W_selectionToolbar{min-height:28px;color:var(--dsw-alias-label-secondary);letter-spacing:0;justify-content:space-between;align-items:center;gap:12px;font-size:12px;line-height:18px;display:flex}._8iKb1W_selectionToolbar>div{gap:4px;display:flex}._8iKb1W_selectionToolbar button{min-height:28px;color:var(--dsw-alias-state-business-primary);cursor:pointer;font:inherit;letter-spacing:0;background:0 0;border:0;border-radius:4px;padding:0 8px}._8iKb1W_selectionToolbar button:hover{background:var(--dsw-alias-fill-l2)}._8iKb1W_selectionToolbar button:focus-visible,._8iKb1W_candidates input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}._8iKb1W_candidates{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;max-height:min(390px,48vh);margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}._8iKb1W_candidates li{border-bottom:1px solid var(--dsw-alias-border-l2);min-width:0}._8iKb1W_candidates label{cursor:pointer;grid-template-columns:18px minmax(0,1fr);gap:10px;min-width:0;padding:11px 4px;display:grid}._8iKb1W_candidates input{width:16px;height:16px;accent-color:var(--dsw-alias-state-business-primary);margin:2px 0 0}._8iKb1W_candidateBody{flex-direction:column;gap:2px;min-width:0;display:flex}._8iKb1W_candidateHeading{justify-content:space-between;align-items:flex-start;gap:12px;min-width:0;display:flex}._8iKb1W_candidateHeading strong{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-primary);letter-spacing:0;font-size:13px;font-weight:500;line-height:19px}._8iKb1W_candidateHeading>span{color:var(--dsw-alias-state-success-primary);letter-spacing:0;flex:none;font-size:11px;line-height:18px}._8iKb1W_candidateBody code,._8iKb1W_candidateBody>span,._8iKb1W_candidateBody time{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-tertiary);letter-spacing:0;font-size:11px;line-height:17px}._8iKb1W_candidateBody code{color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._8iKb1W_metric{border-right:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2);min-width:0;padding:10px 12px}._8iKb1W_metric dt{color:var(--dsw-alias-label-tertiary);letter-spacing:0;font-size:11px;line-height:16px}._8iKb1W_metric dd{color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums;letter-spacing:0;margin:2px 0 0;font-size:18px;font-weight:500;line-height:24px}._8iKb1W_progress{flex-direction:column;gap:10px;display:flex}._8iKb1W_progressCopy{color:var(--dsw-alias-label-secondary);letter-spacing:0;justify-content:space-between;align-items:center;gap:16px;font-size:13px;line-height:20px;display:flex}._8iKb1W_progressCopy strong{color:var(--dsw-alias-label-primary);font-weight:500}._8iKb1W_progress progress{width:100%;height:6px;accent-color:var(--dsw-alias-state-business-primary)}._8iKb1W_failures{flex-direction:column;gap:8px;margin:14px 0 0;padding:0;list-style:none;display:flex}._8iKb1W_failures li{min-width:0;color:var(--dsw-alias-label-secondary);letter-spacing:0;grid-template-columns:minmax(88px,auto) minmax(0,1fr);gap:10px;font-size:12px;line-height:18px;display:grid}._8iKb1W_failures code,._8iKb1W_failures span{overflow-wrap:anywhere}._8iKb1W_failures code{color:var(--dsw-alias-state-error-primary)}@media (width<=520px){._8iKb1W_dialog{width:calc(100vw - 20px)}._8iKb1W_metrics{grid-template-columns:minmax(0,1fr)}._8iKb1W_selectionToolbar,._8iKb1W_candidateHeading{flex-direction:column;align-items:flex-start}._8iKb1W_candidateHeading{gap:2px}}";
|
|
181
187
|
const tagId$1 = "relay-dsh-plugin-claude/ClaudeSessionImportAction.module.css";
|
|
182
188
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
183
189
|
const tag = document.createElement("style");
|
|
@@ -205,13 +211,15 @@ window.__ModuleLoader__.load({
|
|
|
205
211
|
"selectionToolbar": "_8iKb1W_selectionToolbar",
|
|
206
212
|
"success": "_8iKb1W_success",
|
|
207
213
|
"summary": "_8iKb1W_summary",
|
|
208
|
-
"
|
|
209
|
-
"
|
|
214
|
+
"workspace": "_8iKb1W_workspace",
|
|
215
|
+
"workspaceChoice": "_8iKb1W_workspaceChoice",
|
|
216
|
+
"workspacePath": "_8iKb1W_workspacePath"
|
|
210
217
|
};
|
|
211
218
|
//#endregion
|
|
212
219
|
//#region src/client/ClaudeSessionImportAction.tsx
|
|
213
|
-
function
|
|
214
|
-
const
|
|
220
|
+
function ClaudeSessionImportProvider({ registerProvider, useClaudeSessionImportWorkspaces, useClaudeSessionImportSessions, scanWorkspace, importWorkspace, refreshWorkspaceState, t }) {
|
|
221
|
+
const workspaces = useClaudeSessionImportWorkspaces((value) => value);
|
|
222
|
+
const availableTarget = resolveImportWorkspace(workspaces, useClaudeSessionImportSessions((value) => value));
|
|
215
223
|
const [open, setOpen] = (0, react.useState)(false);
|
|
216
224
|
const [target, setTarget] = (0, react.useState)(null);
|
|
217
225
|
const [phase, setPhase] = (0, react.useState)("idle");
|
|
@@ -248,15 +256,29 @@ window.__ModuleLoader__.load({
|
|
|
248
256
|
setPhase("error");
|
|
249
257
|
});
|
|
250
258
|
};
|
|
251
|
-
const begin = () => {
|
|
252
|
-
const selected = availableTarget;
|
|
259
|
+
const begin = (0, react.useCallback)(() => {
|
|
260
|
+
const selected = availableTarget ?? workspaces.items[0] ?? null;
|
|
253
261
|
setTarget(selected);
|
|
254
262
|
setOpen(true);
|
|
255
263
|
if (selected === null) {
|
|
256
264
|
setPhase("no-workspace");
|
|
257
265
|
return;
|
|
258
266
|
}
|
|
259
|
-
|
|
267
|
+
setPhase("select-workspace");
|
|
268
|
+
}, [availableTarget, workspaces.items]);
|
|
269
|
+
(0, react.useEffect)(() => registerProvider({
|
|
270
|
+
id: "claude",
|
|
271
|
+
label: t("importAction"),
|
|
272
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSparkle16, { size: 16 }),
|
|
273
|
+
order: 20,
|
|
274
|
+
open: begin
|
|
275
|
+
}), [
|
|
276
|
+
begin,
|
|
277
|
+
registerProvider,
|
|
278
|
+
t
|
|
279
|
+
]);
|
|
280
|
+
const scanSelected = () => {
|
|
281
|
+
if (target !== null) scan(target);
|
|
260
282
|
};
|
|
261
283
|
const importSelected = () => {
|
|
262
284
|
const sessionIds = candidates.filter((candidate) => selectedIds.has(candidate.id)).map((candidate) => candidate.id);
|
|
@@ -292,18 +314,7 @@ window.__ModuleLoader__.load({
|
|
|
292
314
|
const retry = () => {
|
|
293
315
|
if (target !== null) scan(target);
|
|
294
316
|
};
|
|
295
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
296
|
-
label: t("importAction"),
|
|
297
|
-
delayMs: 500,
|
|
298
|
-
disabled: wide,
|
|
299
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
300
|
-
type: "button",
|
|
301
|
-
className: ClaudeSessionImportAction_module_css_default.trigger,
|
|
302
|
-
"aria-label": t("importAction"),
|
|
303
|
-
onClick: begin,
|
|
304
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size: wide ? 16 : 18 }), wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("importAction") })]
|
|
305
|
-
})
|
|
306
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
317
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
307
318
|
open,
|
|
308
319
|
onClose: close,
|
|
309
320
|
title: t("importTitle"),
|
|
@@ -315,6 +326,7 @@ window.__ModuleLoader__.load({
|
|
|
315
326
|
selectedCount: selectedIds.size,
|
|
316
327
|
result,
|
|
317
328
|
close,
|
|
329
|
+
scanSelected,
|
|
318
330
|
retry,
|
|
319
331
|
importSelected,
|
|
320
332
|
t
|
|
@@ -323,7 +335,39 @@ window.__ModuleLoader__.load({
|
|
|
323
335
|
className: ClaudeSessionImportAction_module_css_default.body,
|
|
324
336
|
"aria-live": "polite",
|
|
325
337
|
children: [
|
|
326
|
-
target !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
338
|
+
phase === "select-workspace" && target !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
339
|
+
className: ClaudeSessionImportAction_module_css_default.workspaceChoice,
|
|
340
|
+
children: [
|
|
341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
342
|
+
htmlFor: "claude-import-workspace",
|
|
343
|
+
children: t("importWorkspaceLabel")
|
|
344
|
+
}),
|
|
345
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
346
|
+
id: "claude-import-workspace",
|
|
347
|
+
value: target.workspaceId,
|
|
348
|
+
"aria-describedby": "claude-import-workspace-help",
|
|
349
|
+
onChange: (event) => {
|
|
350
|
+
const selected = workspaces.items.find((workspace) => workspace.workspaceId === event.currentTarget.value);
|
|
351
|
+
if (selected !== void 0) setTarget(selected);
|
|
352
|
+
},
|
|
353
|
+
children: workspaces.items.map((workspace) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
354
|
+
value: workspace.workspaceId,
|
|
355
|
+
children: workspace.title
|
|
356
|
+
}, workspace.workspaceId))
|
|
357
|
+
}),
|
|
358
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
359
|
+
id: "claude-import-workspace-help",
|
|
360
|
+
className: ClaudeSessionImportAction_module_css_default.message,
|
|
361
|
+
children: t("importChooseWorkspace")
|
|
362
|
+
}),
|
|
363
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
364
|
+
className: ClaudeSessionImportAction_module_css_default.workspacePath,
|
|
365
|
+
title: target.path,
|
|
366
|
+
children: target.path
|
|
367
|
+
})
|
|
368
|
+
]
|
|
369
|
+
}),
|
|
370
|
+
target !== null && phase !== "select-workspace" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
327
371
|
className: ClaudeSessionImportAction_module_css_default.workspace,
|
|
328
372
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: target.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
329
373
|
title: target.path,
|
|
@@ -360,7 +404,7 @@ window.__ModuleLoader__.load({
|
|
|
360
404
|
})
|
|
361
405
|
]
|
|
362
406
|
})
|
|
363
|
-
})
|
|
407
|
+
}) });
|
|
364
408
|
}
|
|
365
409
|
function SummaryView({ summary, candidates, selectedIds, onSelectionChange, t }) {
|
|
366
410
|
const select = (id, checked) => {
|
|
@@ -499,21 +543,23 @@ window.__ModuleLoader__.load({
|
|
|
499
543
|
})]
|
|
500
544
|
});
|
|
501
545
|
}
|
|
502
|
-
function modalFooter({ phase, selectedCount, result, close, retry, importSelected, t }) {
|
|
503
|
-
const policy = claudeSessionImportUiPolicy(phase, selectedCount, result?.failed);
|
|
546
|
+
function modalFooter({ phase, selectedCount, result, close, scanSelected, retry, importSelected, t }) {
|
|
547
|
+
const policy = claudeSessionImportUiPolicy(phase, selectedCount, result?.failed, phase !== "no-workspace");
|
|
504
548
|
const actions = {
|
|
505
549
|
cancel: close,
|
|
506
550
|
close,
|
|
507
551
|
"import-selected": importSelected,
|
|
508
552
|
importing: void 0,
|
|
509
|
-
retry
|
|
553
|
+
retry,
|
|
554
|
+
scan: scanSelected
|
|
510
555
|
};
|
|
511
556
|
const labels = {
|
|
512
557
|
cancel: t("cancel"),
|
|
513
558
|
close: t("close"),
|
|
514
559
|
"import-selected": t("importSelectedAction"),
|
|
515
560
|
importing: t("importImporting"),
|
|
516
|
-
retry: t("retry")
|
|
561
|
+
retry: t("retry"),
|
|
562
|
+
scan: t("importScanAction")
|
|
517
563
|
};
|
|
518
564
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [policy.secondary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
519
565
|
variant: "outline",
|
|
@@ -652,9 +698,12 @@ window.__ModuleLoader__.load({
|
|
|
652
698
|
//#endregion
|
|
653
699
|
//#region src/client/locales.ts
|
|
654
700
|
const en = {
|
|
655
|
-
importAction: "Import Claude
|
|
701
|
+
importAction: "Import from Claude",
|
|
656
702
|
importTitle: "Import Claude Sessions",
|
|
657
703
|
importDescription: "Select existing Claude terminal Sessions from this Workspace to continue in DSH.",
|
|
704
|
+
importWorkspaceLabel: "Target Workspace",
|
|
705
|
+
importChooseWorkspace: "Choose the Workspace whose Sessions you want to scan and import.",
|
|
706
|
+
importScanAction: "Scan Sessions",
|
|
658
707
|
importNoWorkspace: "Open or select a Workspace before importing Sessions.",
|
|
659
708
|
importScanning: "Scanning native Claude Sessions...",
|
|
660
709
|
importFound: "Found",
|
|
@@ -680,9 +729,12 @@ window.__ModuleLoader__.load({
|
|
|
680
729
|
retry: "Retry"
|
|
681
730
|
};
|
|
682
731
|
const zh = {
|
|
683
|
-
importAction: "
|
|
732
|
+
importAction: "从 Claude 导入",
|
|
684
733
|
importTitle: "导入 Claude 会话",
|
|
685
734
|
importDescription: "选择当前工作区中已有的 Claude 终端会话,并在 DSH 中继续。",
|
|
735
|
+
importWorkspaceLabel: "目标 Workspace",
|
|
736
|
+
importChooseWorkspace: "选择要扫描和导入会话的 Workspace。",
|
|
737
|
+
importScanAction: "扫描会话",
|
|
686
738
|
importNoWorkspace: "请先打开或选择一个工作区。",
|
|
687
739
|
importScanning: "正在扫描原生 Claude 会话...",
|
|
688
740
|
importFound: "发现",
|
|
@@ -748,13 +800,13 @@ window.__ModuleLoader__.load({
|
|
|
748
800
|
}),
|
|
749
801
|
refreshWorkspaceState: () => refreshImportedWorkspace(ctx.sessions, ctx.workspaces)
|
|
750
802
|
});
|
|
751
|
-
ctx.slots.inject("
|
|
752
|
-
name: "
|
|
753
|
-
id: "
|
|
754
|
-
order:
|
|
803
|
+
ctx.slots.inject("relay.session-import.provider", () => ctx.slots.register({
|
|
804
|
+
name: "relay.session-import.provider",
|
|
805
|
+
id: "claude",
|
|
806
|
+
order: 20,
|
|
755
807
|
inject: injected,
|
|
756
808
|
locale: "relay.claude"
|
|
757
|
-
},
|
|
809
|
+
}, ClaudeSessionImportProvider));
|
|
758
810
|
}
|
|
759
811
|
//#endregion
|
|
760
812
|
exports.apply = apply;
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["Tooltip","css","IconDownloadOutline16","Modal","Button","css","DisclosureRow","IconCodeOutline16","StateDot"],"sources":["../model-selection.mjs","../claude-import-contract.mjs","../src/client/claude-session-import-client.mjs","../src/client/claude-session-import-ui-policy.mjs","../src/client/ClaudeSessionImportAction.tsx","../src/client/ClaudeActivityView.tsx","../src/client/claude-activity.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["export function installModelSelection(ctx, preset, provider, otherProvider) {\n const connection = ctx.get(\"connection\");\n const selecting = new Set();\n const pending = new Set();\n\n const sync = () => {\n const list = ctx.sessions.list.getSnapshot();\n const id = list.current;\n if (id === undefined || list.byId[id]?.blank !== true) return;\n if (selecting.has(id)) {\n pending.add(id);\n return;\n }\n\n const selectedPreset = list.byId[id]?.agentPreset;\n if (selectedPreset !== preset && selectedPreset === otherProvider) return;\n selecting.add(id);\n void connection.api.sessions.models({ sessionId: id }).then(async (response) => {\n const { result } = response;\n if (!result.ok) return;\n const latest = ctx.sessions.list.getSnapshot().byId[id];\n if (latest?.blank !== true || latest.agentPreset !== selectedPreset) {\n pending.add(id);\n return;\n }\n const target = selectedPreset === preset\n ? result.value.groups.find((group) => group.id === provider)\n : result.value.current.provider === provider\n ? result.value.groups.find((group) => group.id !== provider && group.id !== otherProvider)\n : undefined;\n const model = target?.models[0];\n if (!target || !model) return;\n await connection.api.sessions.selectModel({\n sessionId: id,\n provider: target.id,\n model: model.id,\n ...(model.reasoning?.defaultEffort\n ? { reasoningEffort: model.reasoning.defaultEffort }\n : {}),\n });\n }).catch(() => {}).finally(() => {\n selecting.delete(id);\n if (pending.delete(id)) sync();\n });\n };\n\n const off = ctx.sessions.list.subscribe(sync);\n sync();\n return off;\n}\n","export const CLAUDE_IMPORT_PATH = \"/api/relay/claude/import\";\n","import { CLAUDE_IMPORT_PATH } from \"../../claude-import-contract.mjs\";\n\nexport function resolveImportWorkspace(workspaces, sessions) {\n const current = sessions?.current;\n if (current !== undefined) {\n const owner = workspaces?.items?.find(workspace => workspace.sessionIds?.includes(current));\n if (owner) return owner;\n }\n const recent = workspaces?.recentWorkspaceId;\n return workspaces?.items?.find(workspace => workspace.workspaceId === recent) ?? null;\n}\n\nexport async function scanClaudeWorkspace(cwd, fetchImpl = fetch) {\n const response = await fetchImpl(CLAUDE_IMPORT_PATH, requestInit(\"scan\", cwd));\n const body = await readJsonResponse(response);\n if (!response.ok) throw new Error(body?.message ?? `Claude import scan failed with HTTP ${response.status}`);\n return body;\n}\n\nexport async function importClaudeWorkspace(cwd, { sessionIds, onProgress } = {}, fetchImpl = fetch) {\n const response = await fetchImpl(CLAUDE_IMPORT_PATH, requestInit(\"import\", cwd, sessionIds));\n if (!response.ok) {\n const body = await readJsonResponse(response);\n throw new Error(body?.message ?? `Claude import failed with HTTP ${response.status}`);\n }\n let completed = null;\n for await (const frame of ndjsonFrames(response.body)) {\n if (frame?.type === \"progress\") onProgress?.(frame);\n if (frame?.type === \"complete\") completed = frame.result;\n if (frame?.type === \"error\") throw new Error(frame.message ?? \"Claude import failed\");\n }\n if (completed === null) throw new Error(\"Claude import response ended before completion\");\n return completed;\n}\n\nexport async function refreshImportedWorkspace(sessions, workspaces) {\n await sessions.refresh();\n await workspaces.refresh();\n}\n\nexport async function* ndjsonFrames(body) {\n if (!body || typeof body.getReader !== \"function\") throw new Error(\"Claude import response has no readable body\");\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n while (true) {\n const { done, value } = await reader.read();\n buffer += decoder.decode(value, { stream: !done });\n let newline = buffer.indexOf(\"\\n\");\n while (newline !== -1) {\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (line) yield parseFrame(line);\n newline = buffer.indexOf(\"\\n\");\n }\n if (done) break;\n }\n const finalLine = buffer.trim();\n if (finalLine) yield parseFrame(finalLine);\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction requestInit(action, cwd, sessionIds) {\n return {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n action,\n cwd,\n ...(sessionIds === undefined ? {} : { sessionIds }),\n }),\n };\n}\n\nasync function readJsonResponse(response) {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\nfunction parseFrame(line) {\n try {\n return JSON.parse(line);\n } catch {\n throw new Error(\"Claude import returned malformed progress data\");\n }\n}\n","export function claudeSessionImportUiPolicy(phase, selected = 0, failed = 0) {\n if (phase === \"importing\") {\n return Object.freeze({ canClose: false, primary: \"importing\", primaryDisabled: true });\n }\n if (phase === \"summary\") {\n return Object.freeze({\n canClose: true,\n secondary: \"cancel\",\n primary: \"import-selected\",\n primaryDisabled: selected === 0,\n });\n }\n if (phase === \"error\") {\n return Object.freeze({ canClose: true, secondary: \"cancel\", primary: \"retry\", primaryDisabled: false });\n }\n if (phase === \"complete\" && failed > 0) {\n return Object.freeze({ canClose: true, secondary: \"close\", primary: \"retry\", primaryDisabled: false });\n }\n return Object.freeze({ canClose: true, primary: \"close\", primaryDisabled: false });\n}\n\nexport function claudeSessionImportUpdatedAtDate(value) {\n if (value === null || value === undefined) return null;\n const milliseconds = typeof value === \"number\" && Number.isFinite(value) && Math.abs(value) < 1e12\n ? value * 1000\n : value;\n const date = new Date(milliseconds);\n return Number.isNaN(date.getTime()) ? null : date;\n}\n","import { useRef, useState, type ReactNode } from 'react'\nimport {\n Button,\n IconDownloadOutline16,\n Modal,\n Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n InjectFace,\n PropsLocale,\n PropsRuntime,\n} from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport { resolveImportWorkspace } from './claude-session-import-client.mjs'\nimport {\n claudeSessionImportUpdatedAtDate,\n claudeSessionImportUiPolicy,\n type ClaudeSessionImportUiAction,\n} from './claude-session-import-ui-policy.mjs'\nimport css from './ClaudeSessionImportAction.module.css'\n\ninterface WorkspaceView {\n workspaceId: string\n title: string\n path: string\n sessionIds: readonly string[]\n}\n\ninterface WorkspaceState {\n items: readonly WorkspaceView[]\n recentWorkspaceId?: string\n}\n\ninterface SessionState {\n current?: string\n}\n\ninterface Summary {\n found: number\n existing: number\n recoverable: number\n ready: number\n}\n\ninterface Candidate {\n id: string\n title: string\n cwd: string\n updatedAt: number | string | null\n status: 'ready' | 'recoverable'\n}\n\ninterface ImportResult {\n found: number\n imported: number\n existing: number\n failed: number\n failures: readonly { session: string; message: string }[]\n}\n\ninterface Progress extends ImportResult {\n completed: number\n total: number\n}\n\ninterface Observable<T> {\n getSnapshot: () => T\n subscribe: (listener: () => void) => () => void\n}\n\nexport interface ClaudeSessionImportInjected {\n hooks: {\n claudeSessionImportWorkspaces: Observable<WorkspaceState>\n claudeSessionImportSessions: Observable<SessionState>\n }\n scanWorkspace: (cwd: string) => Promise<{\n workspace: { title: string; path: string }\n summary: Summary\n candidates: readonly Candidate[]\n }>\n importWorkspace: (\n cwd: string,\n sessionIds: readonly string[],\n onProgress: (progress: Progress) => void,\n ) => Promise<ImportResult>\n refreshWorkspaceState: () => Promise<void>\n}\n\ntype Props = PropsRuntime<'sidebar.footer.action'>\n & InjectFace<ClaudeSessionImportInjected>\n & PropsLocale<'relay.claude'>\n\ntype Phase = 'idle' | 'no-workspace' | 'scanning' | 'summary' | 'importing' | 'complete' | 'error'\n\nexport function ClaudeSessionImportAction({\n wide,\n useClaudeSessionImportWorkspaces,\n useClaudeSessionImportSessions,\n scanWorkspace,\n importWorkspace,\n refreshWorkspaceState,\n t,\n}: Props): ReactNode {\n const workspaces = useClaudeSessionImportWorkspaces(value => value)\n const sessions = useClaudeSessionImportSessions(value => value)\n const availableTarget = resolveImportWorkspace(workspaces, sessions) as WorkspaceView | null\n const [open, setOpen] = useState(false)\n const [target, setTarget] = useState<WorkspaceView | null>(null)\n const [phase, setPhase] = useState<Phase>('idle')\n const [summary, setSummary] = useState<Summary | null>(null)\n const [candidates, setCandidates] = useState<readonly Candidate[]>([])\n const [selectedIds, setSelectedIds] = useState<ReadonlySet<string>>(new Set())\n const [progress, setProgress] = useState<Progress | null>(null)\n const [result, setResult] = useState<ImportResult | null>(null)\n const [error, setError] = useState('')\n const request = useRef(0)\n\n const close = (): void => {\n if (!claudeSessionImportUiPolicy(phase, selectedIds.size, result?.failed).canClose) return\n request.current += 1\n setOpen(false)\n }\n\n const scan = (workspace: WorkspaceView): void => {\n const generation = ++request.current\n setPhase('scanning')\n setSummary(null)\n setCandidates([])\n setSelectedIds(new Set())\n setProgress(null)\n setResult(null)\n setError('')\n void scanWorkspace(workspace.path).then(\n response => {\n if (request.current !== generation) return\n setSummary(response.summary)\n setCandidates(response.candidates)\n setSelectedIds(new Set(response.candidates.map(candidate => candidate.id)))\n setPhase('summary')\n },\n reason => {\n if (request.current !== generation) return\n setError(messageOf(reason))\n setPhase('error')\n },\n )\n }\n\n const begin = (): void => {\n const selected = availableTarget\n setTarget(selected)\n setOpen(true)\n if (selected === null) {\n setPhase('no-workspace')\n return\n }\n scan(selected)\n }\n\n const importSelected = (): void => {\n const sessionIds = candidates\n .filter(candidate => selectedIds.has(candidate.id))\n .map(candidate => candidate.id)\n if (target === null || summary === null || sessionIds.length === 0 || phase === 'importing') return\n const generation = ++request.current\n setPhase('importing')\n setProgress({\n completed: 0,\n total: sessionIds.length,\n found: sessionIds.length,\n imported: 0,\n existing: 0,\n failed: 0,\n failures: [],\n })\n setError('')\n void (async () => {\n try {\n const completed = await importWorkspace(target.path, sessionIds, update => {\n if (request.current === generation) setProgress(update)\n })\n await refreshWorkspaceState()\n if (request.current !== generation) return\n setResult(completed)\n setPhase('complete')\n } catch (reason) {\n if (request.current !== generation) return\n setError(messageOf(reason))\n setPhase('error')\n }\n })()\n }\n\n const retry = (): void => {\n if (target !== null) scan(target)\n }\n\n return (\n <>\n <Tooltip label={t('importAction')} delayMs={500} disabled={wide}>\n <button\n type=\"button\"\n className={css.trigger}\n aria-label={t('importAction')}\n onClick={begin}\n >\n <IconDownloadOutline16 size={wide ? 16 : 18} />\n {wide && <span>{t('importAction')}</span>}\n </button>\n </Tooltip>\n <Modal\n open={open}\n onClose={close}\n title={t('importTitle')}\n closeLabel={t('close')}\n description={t('importDescription')}\n className={css.dialog}\n footer={modalFooter({\n phase,\n selectedCount: selectedIds.size,\n result,\n close,\n retry,\n importSelected,\n t,\n })}\n >\n <div className={css.body} aria-live=\"polite\">\n {target !== null && (\n <div className={css.workspace}>\n <strong>{target.title}</strong>\n <span title={target.path}>{target.path}</span>\n </div>\n )}\n {phase === 'no-workspace' && <p className={css.message}>{t('importNoWorkspace')}</p>}\n {phase === 'scanning' && <p className={css.message}>{t('importScanning')}</p>}\n {phase === 'summary' && summary !== null && (\n <SummaryView\n summary={summary}\n candidates={candidates}\n selectedIds={selectedIds}\n onSelectionChange={setSelectedIds}\n t={t}\n />\n )}\n {phase === 'importing' && progress !== null && <ProgressView progress={progress} t={t} />}\n {phase === 'complete' && result !== null && <ResultView result={result} t={t} />}\n {phase === 'error' && <p className={css.error} role=\"alert\">{error || t('importFailed')}</p>}\n </div>\n </Modal>\n </>\n )\n}\n\nfunction SummaryView({\n summary,\n candidates,\n selectedIds,\n onSelectionChange,\n t,\n}: {\n summary: Summary\n candidates: readonly Candidate[]\n selectedIds: ReadonlySet<string>\n onSelectionChange: (selected: ReadonlySet<string>) => void\n t: Props['t']\n}): ReactNode {\n const select = (id: string, checked: boolean): void => {\n const next = new Set(selectedIds)\n if (checked) next.add(id)\n else next.delete(id)\n onSelectionChange(next)\n }\n return (\n <div className={css.summary}>\n <dl className={css.metrics}>\n <Metric label={t('importFound')} value={summary.found} />\n <Metric label={t('importExisting')} value={summary.existing} />\n <Metric label={t('importRecoverable')} value={summary.recoverable} />\n <Metric label={t('importReady')} value={summary.ready} accent />\n </dl>\n {candidates.length === 0 ? (\n <p className={css.message}>{t('importEmpty')}</p>\n ) : (\n <>\n <div className={css.selectionToolbar}>\n <span>{t('importSelected')}: {selectedIds.size} / {candidates.length}</span>\n <div>\n <button type=\"button\" onClick={() => onSelectionChange(new Set(candidates.map(candidate => candidate.id)))}>\n {t('importSelectAll')}\n </button>\n <button type=\"button\" onClick={() => onSelectionChange(new Set())}>\n {t('importClearSelection')}\n </button>\n </div>\n </div>\n <ul className={css.candidates} aria-label={t('importCandidates')}>\n {candidates.map(candidate => (\n <li key={candidate.id}>\n <label>\n <input\n type=\"checkbox\"\n checked={selectedIds.has(candidate.id)}\n onChange={event => select(candidate.id, event.currentTarget.checked)}\n />\n <span className={css.candidateBody}>\n <span className={css.candidateHeading}>\n <strong>{candidate.title}</strong>\n <span>{candidate.status === 'recoverable' ? t('importStatusRecoverable') : t('importStatusReady')}</span>\n </span>\n <code>{candidate.id}</code>\n <span title={candidate.cwd}>{candidate.cwd}</span>\n <time dateTime={dateTimeValue(candidate.updatedAt)}>{formatUpdatedAt(candidate.updatedAt)}</time>\n </span>\n </label>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n )\n}\n\nfunction ProgressView({ progress, t }: { progress: Progress; t: Props['t'] }): ReactNode {\n const maximum = Math.max(1, progress.total)\n return (\n <div className={css.progress}>\n <div className={css.progressCopy}>\n <strong>{t('importImporting')}</strong>\n <span>{progress.completed} / {progress.total}</span>\n </div>\n <progress value={progress.completed} max={maximum} aria-label={t('importImporting')} />\n </div>\n )\n}\n\nfunction ResultView({ result, t }: { result: ImportResult; t: Props['t'] }): ReactNode {\n return (\n <div>\n <p className={result.failed > 0 ? css.partial : css.success}>\n {result.failed > 0 ? t('importPartial') : t('importComplete')}\n </p>\n <dl className={css.metrics}>\n <Metric label={t('importImported')} value={result.imported} accent />\n <Metric label={t('importExisting')} value={result.existing} />\n <Metric label={t('importFailures')} value={result.failed} danger={result.failed > 0} />\n </dl>\n {result.failures.length > 0 && (\n <ul className={css.failures} aria-label={t('importFailures')}>\n {result.failures.map(failure => (\n <li key={failure.session}>\n <code>{failure.session}</code>\n <span>{failure.message}</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n}\n\nfunction Metric({\n label, value, accent = false, danger = false,\n}: { label: string; value: number; accent?: boolean; danger?: boolean }): ReactNode {\n return (\n <div className={css.metric}>\n <dt>{label}</dt>\n <dd className={danger ? css.dangerValue : accent ? css.accentValue : undefined}>{value}</dd>\n </div>\n )\n}\n\nfunction modalFooter({\n phase, selectedCount, result, close, retry, importSelected, t,\n}: {\n phase: Phase\n selectedCount: number\n result: ImportResult | null\n close: () => void\n retry: () => void\n importSelected: () => void\n t: Props['t']\n}): ReactNode {\n const policy = claudeSessionImportUiPolicy(phase, selectedCount, result?.failed)\n const actions: Record<ClaudeSessionImportUiAction, (() => void) | undefined> = {\n cancel: close,\n close,\n 'import-selected': importSelected,\n importing: undefined,\n retry,\n }\n const labels: Record<ClaudeSessionImportUiAction, string> = {\n cancel: t('cancel'),\n close: t('close'),\n 'import-selected': t('importSelectedAction'),\n importing: t('importImporting'),\n retry: t('retry'),\n }\n return (\n <>\n {policy.secondary !== undefined && (\n <Button variant=\"outline\" onClick={actions[policy.secondary]}>\n {labels[policy.secondary]}\n </Button>\n )}\n <Button\n variant={policy.primary === 'close' ? 'outline' : undefined}\n disabled={policy.primaryDisabled}\n onClick={actions[policy.primary]}\n >\n {labels[policy.primary]}\n </Button>\n </>\n )\n}\n\nfunction dateTimeValue(value: Candidate['updatedAt']): string | undefined {\n const date = claudeSessionImportUpdatedAtDate(value)\n return date?.toISOString()\n}\n\nfunction formatUpdatedAt(value: Candidate['updatedAt']): string {\n const date = claudeSessionImportUpdatedAtDate(value)\n return date === null ? '-' : new Intl.DateTimeFormat(undefined, {\n dateStyle: 'medium',\n timeStyle: 'short',\n }).format(date)\n}\n\nfunction messageOf(reason: unknown): string {\n return reason instanceof Error ? reason.message : String(reason)\n}\n","import { memo, useState } from 'react'\nimport {\n DisclosureRow,\n IconCodeOutline16,\n StateDot,\n type StateDotState,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ClaudeActivityData } from './claude-activity.ts'\nimport css from './ClaudeActivityView.module.css'\n\ntype ClaudeActivityViewProps = PropsRuntime<'conversation.chat.node', 'relay-claude-activity'>\n\nfunction dotState(status: ClaudeActivityData['status']): StateDotState {\n if (status === 'running') return 'ongoing'\n if (status === 'error') return 'error'\n return 'done'\n}\n\nexport const ClaudeActivityView = memo(function ClaudeActivityView({ node }: ClaudeActivityViewProps) {\n const activity = node.data as ClaudeActivityData\n const [open, setOpen] = useState(false)\n const expandable = activity.input !== undefined || activity.output !== undefined || activity.provenance !== undefined\n return (\n <div className={css.activity} data-claude-activity={activity.type}>\n <DisclosureRow\n icon={<IconCodeOutline16 />}\n title={activity.title}\n open={open}\n expandable={expandable}\n onToggle={() => { setOpen(value => !value) }}\n expandOnRowClick\n collapsedContent={(\n <span className={css.summary}>\n <span>{activity.summary}</span>\n <StateDot state={dotState(activity.status)} size={8} />\n </span>\n )}\n >\n <div className={css.detail}>\n {activity.provenance !== undefined ? (\n <div\n className={css.provenance}\n title={`Claude Code · Session ${activity.provenance.claudeSessionId} · Turn ${activity.provenance.turnId}`}\n >\n Claude Code · Session {shortId(activity.provenance.claudeSessionId)} · Turn {shortId(activity.provenance.turnId)}\n </div>\n ) : null}\n {activity.input !== undefined ? <pre>{activity.input}</pre> : null}\n {activity.output !== undefined ? <pre>{activity.output}</pre> : null}\n </div>\n </DisclosureRow>\n </div>\n )\n})\n\nfunction shortId(value: string): string {\n return value.length > 15 ? `${value.slice(0, 8)}...${value.slice(-4)}` : value\n}\n","import type { ChatConversationViewNode, ConversationNodeDefinition } from '@deepseek-ai/dsh-client-runtime/client'\n\nexport type ClaudeActivityStatus = 'running' | 'completed' | 'error'\n\nexport interface ClaudeActivityData {\n readonly type: string\n readonly status: ClaudeActivityStatus\n readonly title: string\n readonly summary?: string\n readonly input?: string\n readonly output?: string\n readonly provenance?: {\n readonly claudeSessionId: string\n readonly turnId: string\n }\n}\n\nexport interface ClaudeActivityEventData {\n readonly version: 1\n readonly claudeSessionId: string\n readonly turnId: string\n readonly itemId: string\n readonly phase: 'started' | 'completed'\n readonly activity: ClaudeActivityData\n}\n\ndeclare module '@deepseek-ai/dsh-session/types' {\n interface SessionEventMap {\n 'relay-claude/activity': ClaudeActivityEventData\n }\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-conversation/client' {\n interface ChatNodeDataMap {\n 'relay-claude-activity': ClaudeActivityData\n }\n}\n\nexport const claudeActivityDefinition: ConversationNodeDefinition<ClaudeActivityData> = {\n kind: 'relay-claude-activity',\n target: 'chat',\n match: event => event.type === 'relay-claude/activity'\n ? { id: event.data.itemId, role: event.data.phase === 'started' ? 'start' : 'update' }\n : null,\n start: (_context, match) => {\n if (match.event.type !== 'relay-claude/activity') {\n throw new Error('Claude activity start requires relay-claude/activity')\n }\n return {\n ...match.event.data.activity,\n provenance: {\n claudeSessionId: match.event.data.claudeSessionId,\n turnId: match.event.data.turnId,\n },\n }\n },\n update: (context, match) => match.event.type === 'relay-claude/activity'\n ? {\n ...match.event.data.activity,\n provenance: {\n claudeSessionId: match.event.data.claudeSessionId,\n turnId: match.event.data.turnId,\n },\n }\n : context.state,\n buildViewNode: (context): ChatConversationViewNode | null => {\n if (context.start === undefined || context.state === undefined) return null\n return {\n key: context.key,\n kind: 'relay-claude-activity',\n id: context.id,\n target: 'chat',\n anchorSeq: context.start.event.seq,\n location: context.start.location,\n visibility: 'visible',\n data: context.state,\n }\n },\n}\n","export const en = {\n importAction: 'Import Claude Sessions',\n importTitle: 'Import Claude Sessions',\n importDescription: 'Select existing Claude terminal Sessions from this Workspace to continue in DSH.',\n importNoWorkspace: 'Open or select a Workspace before importing Sessions.',\n importScanning: 'Scanning native Claude Sessions...',\n importFound: 'Found',\n importExisting: 'Already linked',\n importRecoverable: 'Recoverable',\n importReady: 'Available',\n importEmpty: 'No unlinked Claude Sessions are available in this Workspace.',\n importSelected: 'Selected',\n importSelectAll: 'Select all',\n importClearSelection: 'Clear',\n importCandidates: 'Claude Session candidates',\n importStatusReady: 'Ready',\n importStatusRecoverable: 'Retry import',\n importSelectedAction: 'Import selected',\n importImporting: 'Importing Sessions...',\n importComplete: 'Import completed.',\n importPartial: 'Some Sessions could not be imported.',\n importImported: 'Imported',\n importFailures: 'Failed',\n importFailed: 'Claude Session import failed.',\n cancel: 'Cancel',\n close: 'Close',\n retry: 'Retry',\n} as const\n\nexport const zh: Record<keyof typeof en, string> = {\n importAction: '导入 Claude 会话',\n importTitle: '导入 Claude 会话',\n importDescription: '选择当前工作区中已有的 Claude 终端会话,并在 DSH 中继续。',\n importNoWorkspace: '请先打开或选择一个工作区。',\n importScanning: '正在扫描原生 Claude 会话...',\n importFound: '发现',\n importExisting: '已绑定',\n importRecoverable: '可恢复',\n importReady: '可导入',\n importEmpty: '当前工作区没有未绑定的 Claude 会话。',\n importSelected: '已选择',\n importSelectAll: '全选',\n importClearSelection: '清空',\n importCandidates: 'Claude 会话候选列表',\n importStatusReady: '可导入',\n importStatusRecoverable: '重试导入',\n importSelectedAction: '导入所选会话',\n importImporting: '正在导入会话...',\n importComplete: '导入完成。',\n importPartial: '部分会话未能导入。',\n importImported: '已导入',\n importFailures: '失败',\n importFailed: 'Claude 会话导入失败。',\n cancel: '取消',\n close: '关闭',\n retry: '重试',\n}\n\nexport type ClaudeLocaleKey = keyof typeof en\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-sidebar/client'\nimport { installModelSelection, type ModelSelectionContext } from '../../model-selection.mjs'\nimport { ClaudeSessionImportAction, type ClaudeSessionImportInjected } from './ClaudeSessionImportAction.tsx'\nimport { ClaudeActivityView } from './ClaudeActivityView.tsx'\nimport { claudeActivityDefinition } from './claude-activity.ts'\nimport { en, zh, type ClaudeLocaleKey } from './locales.ts'\nimport {\n importClaudeWorkspace,\n refreshImportedWorkspace,\n scanClaudeWorkspace,\n} from './claude-session-import-client.mjs'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'relay.claude': ClaudeLocaleKey\n }\n}\n\nexport const inject = ['slots', 'theme', 'locale', 'remote', 'sessions', 'workspaces', 'connection', 'conversationEvents']\n\nexport async function apply(ctx: ClientContext): Promise<() => Promise<void>> {\n ctx.effect(() => ctx.locale.register('relay.claude', { zh, en }), 'relay-claude: dictionaries')\n ctx.conversationEvents.register(claudeActivityDefinition)\n ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({\n name: 'conversation.chat.node', key: 'relay-claude-activity',\n }, ClaudeActivityView))\n applySessionImport(ctx)\n const unsubscribe = installModelSelection(ctx as ModelSelectionContext, 'relay-claude', 'relay-claude', 'relay-codex')\n return async () => { unsubscribe() }\n}\n\nfunction applySessionImport(ctx: ClientContext): void {\n const injected = (): ClaudeSessionImportInjected => ({\n hooks: {\n claudeSessionImportWorkspaces: ctx.workspaces.list,\n claudeSessionImportSessions: ctx.sessions.list,\n },\n scanWorkspace: cwd => scanClaudeWorkspace(cwd),\n importWorkspace: (cwd, sessionIds, onProgress) => importClaudeWorkspace(cwd, { sessionIds, onProgress }),\n refreshWorkspaceState: () => refreshImportedWorkspace(\n ctx.sessions as typeof ctx.sessions & { refresh(): Promise<void> },\n ctx.workspaces as typeof ctx.workspaces & { refresh(): Promise<void> },\n ),\n })\n ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({\n name: 'sidebar.footer.action',\n id: 'relay-claude-session-import',\n order: -9,\n inject: injected,\n locale: 'relay.claude',\n }, ClaudeSessionImportAction))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["IconSparkle16","Modal","css","Button","css","DisclosureRow","IconCodeOutline16","StateDot"],"sources":["../model-selection.mjs","../claude-import-contract.mjs","../src/client/claude-session-import-client.mjs","../src/client/claude-session-import-ui-policy.mjs","../src/client/ClaudeSessionImportAction.tsx","../src/client/ClaudeActivityView.tsx","../src/client/claude-activity.ts","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["export function installModelSelection(ctx, preset, provider, otherProvider) {\n const connection = ctx.get(\"connection\");\n const selecting = new Set();\n const pending = new Set();\n\n const sync = () => {\n const list = ctx.sessions.list.getSnapshot();\n const id = list.current;\n if (id === undefined || list.byId[id]?.blank !== true) return;\n if (selecting.has(id)) {\n pending.add(id);\n return;\n }\n\n const selectedPreset = list.byId[id]?.agentPreset;\n if (selectedPreset !== preset && selectedPreset === otherProvider) return;\n selecting.add(id);\n void connection.api.sessions.models({ sessionId: id }).then(async (response) => {\n const { result } = response;\n if (!result.ok) return;\n const latest = ctx.sessions.list.getSnapshot().byId[id];\n if (latest?.blank !== true || latest.agentPreset !== selectedPreset) {\n pending.add(id);\n return;\n }\n const target = selectedPreset === preset\n ? result.value.groups.find((group) => group.id === provider)\n : result.value.current.provider === provider\n ? result.value.groups.find((group) => group.id !== provider && group.id !== otherProvider)\n : undefined;\n const model = target?.models[0];\n if (!target || !model) return;\n await connection.api.sessions.selectModel({\n sessionId: id,\n provider: target.id,\n model: model.id,\n ...(model.reasoning?.defaultEffort\n ? { reasoningEffort: model.reasoning.defaultEffort }\n : {}),\n });\n }).catch(() => {}).finally(() => {\n selecting.delete(id);\n if (pending.delete(id)) sync();\n });\n };\n\n const off = ctx.sessions.list.subscribe(sync);\n sync();\n return off;\n}\n","export const CLAUDE_IMPORT_PATH = \"/api/relay/claude/import\";\n","import { CLAUDE_IMPORT_PATH } from \"../../claude-import-contract.mjs\";\n\nexport function resolveImportWorkspace(workspaces, sessions) {\n const current = sessions?.current;\n if (current !== undefined) {\n const owner = workspaces?.items?.find(workspace => workspace.sessionIds?.includes(current));\n if (owner) return owner;\n }\n const recent = workspaces?.recentWorkspaceId;\n return workspaces?.items?.find(workspace => workspace.workspaceId === recent) ?? null;\n}\n\nexport async function scanClaudeWorkspace(cwd, fetchImpl = fetch) {\n const response = await fetchImpl(CLAUDE_IMPORT_PATH, requestInit(\"scan\", cwd));\n const body = await readJsonResponse(response);\n if (!response.ok) throw new Error(body?.message ?? `Claude import scan failed with HTTP ${response.status}`);\n return body;\n}\n\nexport async function importClaudeWorkspace(cwd, { sessionIds, onProgress } = {}, fetchImpl = fetch) {\n const response = await fetchImpl(CLAUDE_IMPORT_PATH, requestInit(\"import\", cwd, sessionIds));\n if (!response.ok) {\n const body = await readJsonResponse(response);\n throw new Error(body?.message ?? `Claude import failed with HTTP ${response.status}`);\n }\n let completed = null;\n for await (const frame of ndjsonFrames(response.body)) {\n if (frame?.type === \"progress\") onProgress?.(frame);\n if (frame?.type === \"complete\") completed = frame.result;\n if (frame?.type === \"error\") throw new Error(frame.message ?? \"Claude import failed\");\n }\n if (completed === null) throw new Error(\"Claude import response ended before completion\");\n return completed;\n}\n\nexport async function refreshImportedWorkspace(sessions, workspaces) {\n await sessions.refresh();\n await workspaces.refresh();\n}\n\nexport async function* ndjsonFrames(body) {\n if (!body || typeof body.getReader !== \"function\") throw new Error(\"Claude import response has no readable body\");\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n try {\n while (true) {\n const { done, value } = await reader.read();\n buffer += decoder.decode(value, { stream: !done });\n let newline = buffer.indexOf(\"\\n\");\n while (newline !== -1) {\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (line) yield parseFrame(line);\n newline = buffer.indexOf(\"\\n\");\n }\n if (done) break;\n }\n const finalLine = buffer.trim();\n if (finalLine) yield parseFrame(finalLine);\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction requestInit(action, cwd, sessionIds) {\n return {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n action,\n cwd,\n ...(sessionIds === undefined ? {} : { sessionIds }),\n }),\n };\n}\n\nasync function readJsonResponse(response) {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\nfunction parseFrame(line) {\n try {\n return JSON.parse(line);\n } catch {\n throw new Error(\"Claude import returned malformed progress data\");\n }\n}\n","export function claudeSessionImportUiPolicy(phase, selected = 0, failed = 0, hasWorkspace = true) {\n if (phase === \"importing\") {\n return Object.freeze({ canClose: false, primary: \"importing\", primaryDisabled: true });\n }\n if (phase === \"summary\") {\n return Object.freeze({\n canClose: true,\n secondary: \"cancel\",\n primary: \"import-selected\",\n primaryDisabled: selected === 0,\n });\n }\n if (phase === \"select-workspace\") {\n return Object.freeze({\n canClose: true,\n secondary: \"cancel\",\n primary: \"scan\",\n primaryDisabled: !hasWorkspace,\n });\n }\n if (phase === \"error\") {\n return Object.freeze({ canClose: true, secondary: \"cancel\", primary: \"retry\", primaryDisabled: false });\n }\n if (phase === \"complete\" && failed > 0) {\n return Object.freeze({ canClose: true, secondary: \"close\", primary: \"retry\", primaryDisabled: false });\n }\n return Object.freeze({ canClose: true, primary: \"close\", primaryDisabled: false });\n}\n\nexport function claudeSessionImportUpdatedAtDate(value) {\n if (value === null || value === undefined) return null;\n const milliseconds = typeof value === \"number\" && Number.isFinite(value) && Math.abs(value) < 1e12\n ? value * 1000\n : value;\n const date = new Date(milliseconds);\n return Number.isNaN(date.getTime()) ? null : date;\n}\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from 'react'\nimport {\n Button,\n IconSparkle16,\n Modal,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {\n InjectFace,\n PropsLocale,\n} from '@deepseek-ai/dsh-client-ui-slots'\nimport type { SessionImportProviderOwnerProps } from 'relay-dsh-plugin-session-import/contracts'\nimport { resolveImportWorkspace } from './claude-session-import-client.mjs'\nimport {\n claudeSessionImportUpdatedAtDate,\n claudeSessionImportUiPolicy,\n type ClaudeSessionImportUiAction,\n} from './claude-session-import-ui-policy.mjs'\nimport css from './ClaudeSessionImportAction.module.css'\n\ninterface WorkspaceView {\n workspaceId: string\n title: string\n path: string\n sessionIds: readonly string[]\n}\n\ninterface WorkspaceState {\n items: readonly WorkspaceView[]\n recentWorkspaceId?: string\n}\n\ninterface SessionState {\n current?: string\n}\n\ninterface Summary {\n found: number\n existing: number\n recoverable: number\n ready: number\n}\n\ninterface Candidate {\n id: string\n title: string\n cwd: string\n updatedAt: number | string | null\n status: 'ready' | 'recoverable'\n}\n\ninterface ImportResult {\n found: number\n imported: number\n existing: number\n failed: number\n failures: readonly { session: string; message: string }[]\n}\n\ninterface Progress extends ImportResult {\n completed: number\n total: number\n}\n\ninterface Observable<T> {\n getSnapshot: () => T\n subscribe: (listener: () => void) => () => void\n}\n\nexport interface ClaudeSessionImportInjected {\n hooks: {\n claudeSessionImportWorkspaces: Observable<WorkspaceState>\n claudeSessionImportSessions: Observable<SessionState>\n }\n scanWorkspace: (cwd: string) => Promise<{\n workspace: { title: string; path: string }\n summary: Summary\n candidates: readonly Candidate[]\n }>\n importWorkspace: (\n cwd: string,\n sessionIds: readonly string[],\n onProgress: (progress: Progress) => void,\n ) => Promise<ImportResult>\n refreshWorkspaceState: () => Promise<void>\n}\n\ntype Props = SessionImportProviderOwnerProps\n & InjectFace<ClaudeSessionImportInjected>\n & PropsLocale<'relay.claude'>\n\ntype Phase = 'idle' | 'no-workspace' | 'select-workspace' | 'scanning' | 'summary' | 'importing' | 'complete' | 'error'\n\nexport function ClaudeSessionImportProvider({\n registerProvider,\n useClaudeSessionImportWorkspaces,\n useClaudeSessionImportSessions,\n scanWorkspace,\n importWorkspace,\n refreshWorkspaceState,\n t,\n}: Props): ReactNode {\n const workspaces = useClaudeSessionImportWorkspaces(value => value)\n const sessions = useClaudeSessionImportSessions(value => value)\n const availableTarget = resolveImportWorkspace(workspaces, sessions) as WorkspaceView | null\n const [open, setOpen] = useState(false)\n const [target, setTarget] = useState<WorkspaceView | null>(null)\n const [phase, setPhase] = useState<Phase>('idle')\n const [summary, setSummary] = useState<Summary | null>(null)\n const [candidates, setCandidates] = useState<readonly Candidate[]>([])\n const [selectedIds, setSelectedIds] = useState<ReadonlySet<string>>(new Set())\n const [progress, setProgress] = useState<Progress | null>(null)\n const [result, setResult] = useState<ImportResult | null>(null)\n const [error, setError] = useState('')\n const request = useRef(0)\n\n const close = (): void => {\n if (!claudeSessionImportUiPolicy(phase, selectedIds.size, result?.failed).canClose) return\n request.current += 1\n setOpen(false)\n }\n\n const scan = (workspace: WorkspaceView): void => {\n const generation = ++request.current\n setPhase('scanning')\n setSummary(null)\n setCandidates([])\n setSelectedIds(new Set())\n setProgress(null)\n setResult(null)\n setError('')\n void scanWorkspace(workspace.path).then(\n response => {\n if (request.current !== generation) return\n setSummary(response.summary)\n setCandidates(response.candidates)\n setSelectedIds(new Set(response.candidates.map(candidate => candidate.id)))\n setPhase('summary')\n },\n reason => {\n if (request.current !== generation) return\n setError(messageOf(reason))\n setPhase('error')\n },\n )\n }\n\n const begin = useCallback((): void => {\n const selected = availableTarget ?? workspaces.items[0] ?? null\n setTarget(selected)\n setOpen(true)\n if (selected === null) {\n setPhase('no-workspace')\n return\n }\n setPhase('select-workspace')\n }, [availableTarget, workspaces.items])\n\n useEffect(() => registerProvider({\n id: 'claude',\n label: t('importAction'),\n icon: <IconSparkle16 size={16} />,\n order: 20,\n open: begin,\n }), [begin, registerProvider, t])\n\n const scanSelected = (): void => {\n if (target !== null) scan(target)\n }\n\n const importSelected = (): void => {\n const sessionIds = candidates\n .filter(candidate => selectedIds.has(candidate.id))\n .map(candidate => candidate.id)\n if (target === null || summary === null || sessionIds.length === 0 || phase === 'importing') return\n const generation = ++request.current\n setPhase('importing')\n setProgress({\n completed: 0,\n total: sessionIds.length,\n found: sessionIds.length,\n imported: 0,\n existing: 0,\n failed: 0,\n failures: [],\n })\n setError('')\n void (async () => {\n try {\n const completed = await importWorkspace(target.path, sessionIds, update => {\n if (request.current === generation) setProgress(update)\n })\n await refreshWorkspaceState()\n if (request.current !== generation) return\n setResult(completed)\n setPhase('complete')\n } catch (reason) {\n if (request.current !== generation) return\n setError(messageOf(reason))\n setPhase('error')\n }\n })()\n }\n\n const retry = (): void => {\n if (target !== null) scan(target)\n }\n\n return (\n <>\n <Modal\n open={open}\n onClose={close}\n title={t('importTitle')}\n closeLabel={t('close')}\n description={t('importDescription')}\n className={css.dialog}\n footer={modalFooter({\n phase,\n selectedCount: selectedIds.size,\n result,\n close,\n scanSelected,\n retry,\n importSelected,\n t,\n })}\n >\n <div className={css.body} aria-live=\"polite\">\n {phase === 'select-workspace' && target !== null && (\n <div className={css.workspaceChoice}>\n <label htmlFor=\"claude-import-workspace\">{t('importWorkspaceLabel')}</label>\n <select\n id=\"claude-import-workspace\"\n value={target.workspaceId}\n aria-describedby=\"claude-import-workspace-help\"\n onChange={event => {\n const selected = workspaces.items.find(workspace => workspace.workspaceId === event.currentTarget.value)\n if (selected !== undefined) setTarget(selected)\n }}\n >\n {workspaces.items.map(workspace => (\n <option key={workspace.workspaceId} value={workspace.workspaceId}>{workspace.title}</option>\n ))}\n </select>\n <span id=\"claude-import-workspace-help\" className={css.message}>{t('importChooseWorkspace')}</span>\n <span className={css.workspacePath} title={target.path}>{target.path}</span>\n </div>\n )}\n {target !== null && phase !== 'select-workspace' && (\n <div className={css.workspace}>\n <strong>{target.title}</strong>\n <span title={target.path}>{target.path}</span>\n </div>\n )}\n {phase === 'no-workspace' && <p className={css.message}>{t('importNoWorkspace')}</p>}\n {phase === 'scanning' && <p className={css.message}>{t('importScanning')}</p>}\n {phase === 'summary' && summary !== null && (\n <SummaryView\n summary={summary}\n candidates={candidates}\n selectedIds={selectedIds}\n onSelectionChange={setSelectedIds}\n t={t}\n />\n )}\n {phase === 'importing' && progress !== null && <ProgressView progress={progress} t={t} />}\n {phase === 'complete' && result !== null && <ResultView result={result} t={t} />}\n {phase === 'error' && <p className={css.error} role=\"alert\">{error || t('importFailed')}</p>}\n </div>\n </Modal>\n </>\n )\n}\n\nfunction SummaryView({\n summary,\n candidates,\n selectedIds,\n onSelectionChange,\n t,\n}: {\n summary: Summary\n candidates: readonly Candidate[]\n selectedIds: ReadonlySet<string>\n onSelectionChange: (selected: ReadonlySet<string>) => void\n t: Props['t']\n}): ReactNode {\n const select = (id: string, checked: boolean): void => {\n const next = new Set(selectedIds)\n if (checked) next.add(id)\n else next.delete(id)\n onSelectionChange(next)\n }\n return (\n <div className={css.summary}>\n <dl className={css.metrics}>\n <Metric label={t('importFound')} value={summary.found} />\n <Metric label={t('importExisting')} value={summary.existing} />\n <Metric label={t('importRecoverable')} value={summary.recoverable} />\n <Metric label={t('importReady')} value={summary.ready} accent />\n </dl>\n {candidates.length === 0 ? (\n <p className={css.message}>{t('importEmpty')}</p>\n ) : (\n <>\n <div className={css.selectionToolbar}>\n <span>{t('importSelected')}: {selectedIds.size} / {candidates.length}</span>\n <div>\n <button type=\"button\" onClick={() => onSelectionChange(new Set(candidates.map(candidate => candidate.id)))}>\n {t('importSelectAll')}\n </button>\n <button type=\"button\" onClick={() => onSelectionChange(new Set())}>\n {t('importClearSelection')}\n </button>\n </div>\n </div>\n <ul className={css.candidates} aria-label={t('importCandidates')}>\n {candidates.map(candidate => (\n <li key={candidate.id}>\n <label>\n <input\n type=\"checkbox\"\n checked={selectedIds.has(candidate.id)}\n onChange={event => select(candidate.id, event.currentTarget.checked)}\n />\n <span className={css.candidateBody}>\n <span className={css.candidateHeading}>\n <strong>{candidate.title}</strong>\n <span>{candidate.status === 'recoverable' ? t('importStatusRecoverable') : t('importStatusReady')}</span>\n </span>\n <code>{candidate.id}</code>\n <span title={candidate.cwd}>{candidate.cwd}</span>\n <time dateTime={dateTimeValue(candidate.updatedAt)}>{formatUpdatedAt(candidate.updatedAt)}</time>\n </span>\n </label>\n </li>\n ))}\n </ul>\n </>\n )}\n </div>\n )\n}\n\nfunction ProgressView({ progress, t }: { progress: Progress; t: Props['t'] }): ReactNode {\n const maximum = Math.max(1, progress.total)\n return (\n <div className={css.progress}>\n <div className={css.progressCopy}>\n <strong>{t('importImporting')}</strong>\n <span>{progress.completed} / {progress.total}</span>\n </div>\n <progress value={progress.completed} max={maximum} aria-label={t('importImporting')} />\n </div>\n )\n}\n\nfunction ResultView({ result, t }: { result: ImportResult; t: Props['t'] }): ReactNode {\n return (\n <div>\n <p className={result.failed > 0 ? css.partial : css.success}>\n {result.failed > 0 ? t('importPartial') : t('importComplete')}\n </p>\n <dl className={css.metrics}>\n <Metric label={t('importImported')} value={result.imported} accent />\n <Metric label={t('importExisting')} value={result.existing} />\n <Metric label={t('importFailures')} value={result.failed} danger={result.failed > 0} />\n </dl>\n {result.failures.length > 0 && (\n <ul className={css.failures} aria-label={t('importFailures')}>\n {result.failures.map(failure => (\n <li key={failure.session}>\n <code>{failure.session}</code>\n <span>{failure.message}</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n}\n\nfunction Metric({\n label, value, accent = false, danger = false,\n}: { label: string; value: number; accent?: boolean; danger?: boolean }): ReactNode {\n return (\n <div className={css.metric}>\n <dt>{label}</dt>\n <dd className={danger ? css.dangerValue : accent ? css.accentValue : undefined}>{value}</dd>\n </div>\n )\n}\n\nfunction modalFooter({\n phase, selectedCount, result, close, scanSelected, retry, importSelected, t,\n}: {\n phase: Phase\n selectedCount: number\n result: ImportResult | null\n close: () => void\n scanSelected: () => void\n retry: () => void\n importSelected: () => void\n t: Props['t']\n}): ReactNode {\n const policy = claudeSessionImportUiPolicy(phase, selectedCount, result?.failed, phase !== 'no-workspace')\n const actions: Record<ClaudeSessionImportUiAction, (() => void) | undefined> = {\n cancel: close,\n close,\n 'import-selected': importSelected,\n importing: undefined,\n retry,\n scan: scanSelected,\n }\n const labels: Record<ClaudeSessionImportUiAction, string> = {\n cancel: t('cancel'),\n close: t('close'),\n 'import-selected': t('importSelectedAction'),\n importing: t('importImporting'),\n retry: t('retry'),\n scan: t('importScanAction'),\n }\n return (\n <>\n {policy.secondary !== undefined && (\n <Button variant=\"outline\" onClick={actions[policy.secondary]}>\n {labels[policy.secondary]}\n </Button>\n )}\n <Button\n variant={policy.primary === 'close' ? 'outline' : undefined}\n disabled={policy.primaryDisabled}\n onClick={actions[policy.primary]}\n >\n {labels[policy.primary]}\n </Button>\n </>\n )\n}\n\nfunction dateTimeValue(value: Candidate['updatedAt']): string | undefined {\n const date = claudeSessionImportUpdatedAtDate(value)\n return date?.toISOString()\n}\n\nfunction formatUpdatedAt(value: Candidate['updatedAt']): string {\n const date = claudeSessionImportUpdatedAtDate(value)\n return date === null ? '-' : new Intl.DateTimeFormat(undefined, {\n dateStyle: 'medium',\n timeStyle: 'short',\n }).format(date)\n}\n\nfunction messageOf(reason: unknown): string {\n return reason instanceof Error ? reason.message : String(reason)\n}\n","import { memo, useState } from 'react'\nimport {\n DisclosureRow,\n IconCodeOutline16,\n StateDot,\n type StateDotState,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ClaudeActivityData } from './claude-activity.ts'\nimport css from './ClaudeActivityView.module.css'\n\ntype ClaudeActivityViewProps = PropsRuntime<'conversation.chat.node', 'relay-claude-activity'>\n\nfunction dotState(status: ClaudeActivityData['status']): StateDotState {\n if (status === 'running') return 'ongoing'\n if (status === 'error') return 'error'\n return 'done'\n}\n\nexport const ClaudeActivityView = memo(function ClaudeActivityView({ node }: ClaudeActivityViewProps) {\n const activity = node.data as ClaudeActivityData\n const [open, setOpen] = useState(false)\n const expandable = activity.input !== undefined || activity.output !== undefined || activity.provenance !== undefined\n return (\n <div className={css.activity} data-claude-activity={activity.type}>\n <DisclosureRow\n icon={<IconCodeOutline16 />}\n title={activity.title}\n open={open}\n expandable={expandable}\n onToggle={() => { setOpen(value => !value) }}\n expandOnRowClick\n collapsedContent={(\n <span className={css.summary}>\n <span>{activity.summary}</span>\n <StateDot state={dotState(activity.status)} size={8} />\n </span>\n )}\n >\n <div className={css.detail}>\n {activity.provenance !== undefined ? (\n <div\n className={css.provenance}\n title={`Claude Code · Session ${activity.provenance.claudeSessionId} · Turn ${activity.provenance.turnId}`}\n >\n Claude Code · Session {shortId(activity.provenance.claudeSessionId)} · Turn {shortId(activity.provenance.turnId)}\n </div>\n ) : null}\n {activity.input !== undefined ? <pre>{activity.input}</pre> : null}\n {activity.output !== undefined ? <pre>{activity.output}</pre> : null}\n </div>\n </DisclosureRow>\n </div>\n )\n})\n\nfunction shortId(value: string): string {\n return value.length > 15 ? `${value.slice(0, 8)}...${value.slice(-4)}` : value\n}\n","import type { ChatConversationViewNode, ConversationNodeDefinition } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { SessionEventMap } from '@deepseek-ai/dsh-session/types'\n\ntype SessionEventContractAnchor = SessionEventMap\n\nexport type ClaudeActivityStatus = 'running' | 'completed' | 'error'\n\nexport interface ClaudeActivityData {\n readonly type: string\n readonly status: ClaudeActivityStatus\n readonly title: string\n readonly summary?: string\n readonly input?: string\n readonly output?: string\n readonly provenance?: {\n readonly claudeSessionId: string\n readonly turnId: string\n }\n}\n\nexport interface ClaudeActivityEventData {\n readonly version: 1\n readonly claudeSessionId: string\n readonly turnId: string\n readonly itemId: string\n readonly phase: 'started' | 'completed'\n readonly activity: ClaudeActivityData\n}\n\ndeclare module '@deepseek-ai/dsh-session/types' {\n interface SessionEventMap {\n 'relay-claude/activity': ClaudeActivityEventData\n }\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-conversation/client' {\n interface ChatNodeDataMap {\n 'relay-claude-activity': ClaudeActivityData\n }\n}\n\nexport const claudeActivityDefinition: ConversationNodeDefinition<ClaudeActivityData> = {\n kind: 'relay-claude-activity',\n target: 'chat',\n match: event => event.type === 'relay-claude/activity'\n ? { id: event.data.itemId, role: event.data.phase === 'started' ? 'start' : 'update' }\n : null,\n start: (_context, match) => {\n if (match.event.type !== 'relay-claude/activity') {\n throw new Error('Claude activity start requires relay-claude/activity')\n }\n return {\n ...match.event.data.activity,\n provenance: {\n claudeSessionId: match.event.data.claudeSessionId,\n turnId: match.event.data.turnId,\n },\n }\n },\n update: (context, match) => match.event.type === 'relay-claude/activity'\n ? {\n ...match.event.data.activity,\n provenance: {\n claudeSessionId: match.event.data.claudeSessionId,\n turnId: match.event.data.turnId,\n },\n }\n : context.state,\n buildViewNode: (context): ChatConversationViewNode | null => {\n if (context.start === undefined || context.state === undefined) return null\n return {\n key: context.key,\n kind: 'relay-claude-activity',\n id: context.id,\n target: 'chat',\n anchorSeq: context.start.event.seq,\n location: context.start.location,\n visibility: 'visible',\n data: context.state,\n }\n },\n}\n","export const en = {\n importAction: 'Import from Claude',\n importTitle: 'Import Claude Sessions',\n importDescription: 'Select existing Claude terminal Sessions from this Workspace to continue in DSH.',\n importWorkspaceLabel: 'Target Workspace',\n importChooseWorkspace: 'Choose the Workspace whose Sessions you want to scan and import.',\n importScanAction: 'Scan Sessions',\n importNoWorkspace: 'Open or select a Workspace before importing Sessions.',\n importScanning: 'Scanning native Claude Sessions...',\n importFound: 'Found',\n importExisting: 'Already linked',\n importRecoverable: 'Recoverable',\n importReady: 'Available',\n importEmpty: 'No unlinked Claude Sessions are available in this Workspace.',\n importSelected: 'Selected',\n importSelectAll: 'Select all',\n importClearSelection: 'Clear',\n importCandidates: 'Claude Session candidates',\n importStatusReady: 'Ready',\n importStatusRecoverable: 'Retry import',\n importSelectedAction: 'Import selected',\n importImporting: 'Importing Sessions...',\n importComplete: 'Import completed.',\n importPartial: 'Some Sessions could not be imported.',\n importImported: 'Imported',\n importFailures: 'Failed',\n importFailed: 'Claude Session import failed.',\n cancel: 'Cancel',\n close: 'Close',\n retry: 'Retry',\n} as const\n\nexport const zh: Record<keyof typeof en, string> = {\n importAction: '从 Claude 导入',\n importTitle: '导入 Claude 会话',\n importDescription: '选择当前工作区中已有的 Claude 终端会话,并在 DSH 中继续。',\n importWorkspaceLabel: '目标 Workspace',\n importChooseWorkspace: '选择要扫描和导入会话的 Workspace。',\n importScanAction: '扫描会话',\n importNoWorkspace: '请先打开或选择一个工作区。',\n importScanning: '正在扫描原生 Claude 会话...',\n importFound: '发现',\n importExisting: '已绑定',\n importRecoverable: '可恢复',\n importReady: '可导入',\n importEmpty: '当前工作区没有未绑定的 Claude 会话。',\n importSelected: '已选择',\n importSelectAll: '全选',\n importClearSelection: '清空',\n importCandidates: 'Claude 会话候选列表',\n importStatusReady: '可导入',\n importStatusRecoverable: '重试导入',\n importSelectedAction: '导入所选会话',\n importImporting: '正在导入会话...',\n importComplete: '导入完成。',\n importPartial: '部分会话未能导入。',\n importImported: '已导入',\n importFailures: '失败',\n importFailed: 'Claude 会话导入失败。',\n cancel: '取消',\n close: '关闭',\n retry: '重试',\n}\n\nexport type ClaudeLocaleKey = keyof typeof en\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type { ChatNodeOwnerProps } from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { installModelSelection, type ModelSelectionContext } from '../../model-selection.mjs'\nimport { ClaudeSessionImportProvider, type ClaudeSessionImportInjected } from './ClaudeSessionImportAction.tsx'\nimport { ClaudeActivityView } from './ClaudeActivityView.tsx'\nimport { claudeActivityDefinition } from './claude-activity.ts'\nimport { en, zh, type ClaudeLocaleKey } from './locales.ts'\nimport {\n importClaudeWorkspace,\n refreshImportedWorkspace,\n scanClaudeWorkspace,\n} from './claude-session-import-client.mjs'\nimport type { SessionImportProviderSlotDefinition } from 'relay-dsh-plugin-session-import/contracts'\n\ntype DshSlotContractAnchor = ChatNodeOwnerProps\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n 'relay.session-import.provider': SessionImportProviderSlotDefinition\n }\n interface LocaleNamespaceMap {\n 'relay.claude': ClaudeLocaleKey\n }\n}\n\nexport const inject = ['slots', 'theme', 'locale', 'remote', 'sessions', 'workspaces', 'connection', 'conversationEvents']\n\nexport async function apply(ctx: ClientContext): Promise<() => Promise<void>> {\n ctx.effect(() => ctx.locale.register('relay.claude', { zh, en }), 'relay-claude: dictionaries')\n ctx.conversationEvents.register(claudeActivityDefinition)\n ctx.slots.inject('conversation.chat.node', () => ctx.slots.register({\n name: 'conversation.chat.node', key: 'relay-claude-activity',\n }, ClaudeActivityView))\n applySessionImport(ctx)\n const unsubscribe = installModelSelection(ctx as ModelSelectionContext, 'relay-claude', 'relay-claude', 'relay-codex')\n return async () => { unsubscribe() }\n}\n\nfunction applySessionImport(ctx: ClientContext): void {\n const injected = (): ClaudeSessionImportInjected => ({\n hooks: {\n claudeSessionImportWorkspaces: ctx.workspaces.list,\n claudeSessionImportSessions: ctx.sessions.list,\n },\n scanWorkspace: cwd => scanClaudeWorkspace(cwd),\n importWorkspace: (cwd, sessionIds, onProgress) => importClaudeWorkspace(cwd, { sessionIds, onProgress }),\n refreshWorkspaceState: () => refreshImportedWorkspace(\n ctx.sessions as typeof ctx.sessions & { refresh(): Promise<void> },\n ctx.workspaces as typeof ctx.workspaces & { refresh(): Promise<void> },\n ),\n })\n ctx.slots.inject('relay.session-import.provider', () => ctx.slots.register({\n name: 'relay.session-import.provider',\n id: 'claude',\n order: 20,\n inject: injected,\n locale: 'relay.claude',\n }, ClaudeSessionImportProvider))\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "relay-dsh-plugin-claude",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Claude Code integration plugin for DeepSeek Harness, providing native Claude conversations powered by the Claude Agent SDK, with model selection, approvals, questions, tools, and session continuation.",
|
|
5
|
+
"keywords": ["dsh-plugin", "deepseek-harness", "dsh"],
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"main": "lib/host-plugin.js",
|
|
@@ -17,16 +18,18 @@
|
|
|
17
18
|
"postbuild": "node normalize-build.mjs",
|
|
18
19
|
"pretypecheck": "npm run prepare:dsh",
|
|
19
20
|
"typecheck": "tsc -p tsconfig.json",
|
|
20
|
-
"test": "
|
|
21
|
+
"test:unit": "node --test test/*.test.mjs",
|
|
22
|
+
"test:component": "vitest run test/*.spec.tsx",
|
|
23
|
+
"test": "npm run prepare:dsh && npm run test:unit && npm run test:component",
|
|
21
24
|
"verify": "npm run typecheck && npm test && npm run build"
|
|
22
25
|
},
|
|
23
26
|
"exports": { ".": "./lib/host-plugin.js", "./client": "./lib/client.js", "./typert": "./lib/typert.host.js", "./package.json": "./package.json" },
|
|
24
27
|
"files": ["README.zh.md", "docs/images", "docs/spec/claude-local-plugins.md", "docs/spec/claude-native-session-import.md", "docs/spec/claude-search-tools.md", "docs/spec/claude-tool-output-redaction.md", "cordis.patch.yml", "presets", "lib/client.js", "lib/client.js.map", "lib/host-plugin.js", "lib/host-plugin.js.map", "lib/typert.host.js", "lib/typert.host.js.map"],
|
|
25
28
|
"dsh": {
|
|
26
|
-
"client": { "inject": ["@deepseek-ai/dsh-api-remotes", "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-client-locale", "@deepseek-ai/dsh-client-runtime", "@deepseek-ai/dsh-client-ui-conversation", "@deepseek-ai/dsh-client-ui-primitives", "@deepseek-ai/dsh-client-ui-settings", "@deepseek-ai/dsh-client-ui-sidebar", "@deepseek-ai/dsh-client-ui-slots", "@deepseek-ai/dsh-client-ui-theme"], "platform": "web" },
|
|
29
|
+
"client": { "inject": ["@deepseek-ai/dsh-api-remotes", "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-client-locale", "@deepseek-ai/dsh-client-runtime", "@deepseek-ai/dsh-client-ui-conversation", "@deepseek-ai/dsh-client-ui-primitives", "@deepseek-ai/dsh-client-ui-settings", "@deepseek-ai/dsh-client-ui-sidebar", "@deepseek-ai/dsh-client-ui-slots", "@deepseek-ai/dsh-client-ui-theme", "relay-dsh-plugin-session-import"], "platform": "web" },
|
|
27
30
|
"bundle": { "patch": "./cordis.patch.yml" }
|
|
28
31
|
},
|
|
29
|
-
"dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.241", "@anthropic-ai/sdk": "^0.120.0", "@modelcontextprotocol/sdk": "^1.29.0", "sharp": "^0.35.3", "zod": "4.4.3" },
|
|
32
|
+
"dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.241", "@anthropic-ai/sdk": "^0.120.0", "@modelcontextprotocol/sdk": "^1.29.0", "relay-dsh-plugin-session-import": "^0.1.0", "sharp": "^0.35.3", "zod": "4.4.3" },
|
|
30
33
|
"peerDependencies": {
|
|
31
34
|
"@deepseek-ai/dsh-llm": ">=0.1.0-rc.5 <0.1.1 || >=0.1.1-rc.0 <0.2.0",
|
|
32
35
|
"@deepseek-ai/dsh-session": ">=0.1.0-rc.5 <0.1.1 || >=0.1.1-rc.0 <0.2.0",
|
|
@@ -39,5 +42,5 @@
|
|
|
39
42
|
"@deepseek-ai/dsh-typert-protocol": { "optional": true },
|
|
40
43
|
"react": { "optional": true }
|
|
41
44
|
},
|
|
42
|
-
"devDependencies": { "@types/react": "~18.3.1", "lightningcss": "1.32.0", "react": "^18.2.0", "tsdown": "0.22.2", "typescript": "6.0.3" }
|
|
45
|
+
"devDependencies": { "@testing-library/react": "^16.3.2", "@types/react": "~18.3.1", "@types/react-dom": "^18.3.7", "jsdom": "^29.1.1", "lightningcss": "1.32.0", "react": "^18.2.0", "react-dom": "^18.3.1", "tsdown": "0.22.2", "typescript": "6.0.3", "vitest": "^4.1.8" }
|
|
43
46
|
}
|