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 CHANGED
@@ -6,7 +6,7 @@
6
6
  [![GitHub stars](https://img.shields.io/github/stars/yangbobo2021/relay-dsh-plugin-claude?style=flat)](https://github.com/yangbobo2021/relay-dsh-plugin-claude/stargazers)
7
7
  [![MIT license](https://img.shields.io/github/license/yangbobo2021/relay-dsh-plugin-claude)](LICENSE)
8
8
  [![DSH compatibility](https://img.shields.io/badge/DSH-0.1.1--rc.2-2f7d68)](https://github.com/deepseek-ai/deepseek-harness)
9
- [![npm provenance](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.4)
9
+ [![npm provenance](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](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.4`. The linked
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.4`.
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.4
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. Open the target Workspace or one of its Sessions in DSH.
177
- 2. Select **Import Claude Sessions** below the Workspace list.
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 exact registered Workspace.
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. It has no runtime dependency on the
275
- Relay application, Relay Events, or another Relay plugin. It does not replace the
276
- official DSH layout or install Files and Terminal views. This separation lets a
277
- user install only Claude while the broader Relay project can compose Codex,
278
- Claude, events, waits, monitors, and workbench extensions when those capabilities
279
- are needed.
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
  [![GitHub Stars](https://img.shields.io/github/stars/yangbobo2021/relay-dsh-plugin-claude?style=flat)](https://github.com/yangbobo2021/relay-dsh-plugin-claude/stargazers)
7
7
  [![MIT 许可证](https://img.shields.io/github/license/yangbobo2021/relay-dsh-plugin-claude)](LICENSE)
8
8
  [![DSH 兼容版本](https://img.shields.io/badge/DSH-0.1.1--rc.2-2f7d68)](https://github.com/deepseek-ai/deepseek-harness)
9
- [![npm 来源证明](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.4)
9
+ [![npm 来源证明](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](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.4`。最新版本请以链接中的 npm 页面
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.4`。
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.4
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. DSH 中打开目标工作区或其中一个 Session。
168
- 2. 点击工作区列表下方的 **导入 Claude 会话**。
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
- 本插件可以独立安装。运行时不依赖 Relay 应用、Relay Events 或其他 Relay
248
- 插件,也不会替换 DSH 官方布局或安装 Files、Terminal 视图。用户可以只安装
249
- Claude;需要时,Relay 项目则可以进一步组合 Codex、Claude、事件、Wait、
250
- Monitor 和工作台扩展。
248
+ 本插件可以独立安装。唯一依赖的 Relay 包是由包管理器自动安装的中立“会话
249
+ 导入中心”;运行时不依赖 Relay 应用、Relay Events 或其他功能插件,也不会
250
+ 替换 DSH 官方布局或安装 FilesTerminal 视图。用户可以只安装 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
- 增加对 Relay 或其他功能插件的运行时依赖。
314
+ `npm run verify` 会执行类型检查、测试和生产构建。边界测试仅允许中立的会话
315
+ 导入中心依赖,并会阻止插件意外增加对 Relay 应用或其他功能插件的运行时依赖。
314
316
 
315
317
  ## 反馈
316
318
 
package/cordis.patch.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  - insert:
2
+ - id: relay-session-import-for-claude
3
+ name: 'relay-dsh-plugin-session-import'
2
4
  - id: relay-claude-host
3
5
  name: 'relay-dsh-plugin-claude'
@@ -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 Workspace choice, selection, request payloads, chunked
108
- NDJSON progress, error handling, disabled empty submission, and refresh order.
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. Typecheck, the full repository test suite, build, package-content inspection,
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 = "._8iKb1W_trigger{width:100%;min-width:0;height:34px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;letter-spacing:0;background:0 0;border:0;border-radius:6px;justify-content:flex-start;align-items:center;gap:10px;padding:0 12px;font-size:13px;display:flex}._8iKb1W_trigger:hover{background:var(--dsw-alias-fill-l2);color:var(--dsw-alias-label-primary)}._8iKb1W_trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}._8iKb1W_trigger span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._8iKb1W_dialog{width:min(700px,100vw - 32px)}._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}}";
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
- "trigger": "_8iKb1W_trigger",
209
- "workspace": "_8iKb1W_workspace"
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 ClaudeSessionImportAction({ wide, useClaudeSessionImportWorkspaces, useClaudeSessionImportSessions, scanWorkspace, importWorkspace, refreshWorkspaceState, t }) {
214
- const availableTarget = resolveImportWorkspace(useClaudeSessionImportWorkspaces((value) => value), useClaudeSessionImportSessions((value) => value));
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
- scan(selected);
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.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
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 Sessions",
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: "导入 Claude 会话",
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("sidebar.footer.action", () => ctx.slots.register({
752
- name: "sidebar.footer.action",
753
- id: "relay-claude-session-import",
754
- order: -9,
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
- }, ClaudeSessionImportAction));
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":";;;;;;;;;;EAAA,SAAgB,sBAAsB,KAAK,QAAQ,UAAU,eAAe;GAC1E,MAAM,aAAa,IAAI,IAAI,YAAY;GACvC,MAAM,4BAAY,IAAI,IAAI;GAC1B,MAAM,0BAAU,IAAI,IAAI;GAExB,MAAM,aAAa;IACjB,MAAM,OAAO,IAAI,SAAS,KAAK,YAAY;IAC3C,MAAM,KAAK,KAAK;IAChB,IAAI,OAAO,KAAA,KAAa,KAAK,KAAK,GAAG,EAAE,UAAU,MAAM;IACvD,IAAI,UAAU,IAAI,EAAE,GAAG;KACrB,QAAQ,IAAI,EAAE;KACd;IACF;IAEA,MAAM,iBAAiB,KAAK,KAAK,GAAG,EAAE;IACtC,IAAI,mBAAmB,UAAU,mBAAmB,eAAe;IACnE,UAAU,IAAI,EAAE;IAChB,WAAgB,IAAI,SAAS,OAAO,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,KAAK,OAAO,aAAa;KAC9E,MAAM,EAAE,WAAW;KACnB,IAAI,CAAC,OAAO,IAAI;KAChB,MAAM,SAAS,IAAI,SAAS,KAAK,YAAY,CAAC,CAAC,KAAK;KACpD,IAAI,QAAQ,UAAU,QAAQ,OAAO,gBAAgB,gBAAgB;MACnE,QAAQ,IAAI,EAAE;MACd;KACF;KACA,MAAM,SAAS,mBAAmB,SAC9B,OAAO,MAAM,OAAO,MAAM,UAAU,MAAM,OAAO,QAAQ,IACzD,OAAO,MAAM,QAAQ,aAAa,WAChC,OAAO,MAAM,OAAO,MAAM,UAAU,MAAM,OAAO,YAAY,MAAM,OAAO,aAAa,IACvF,KAAA;KACN,MAAM,QAAQ,QAAQ,OAAO;KAC7B,IAAI,CAAC,UAAU,CAAC,OAAO;KACvB,MAAM,WAAW,IAAI,SAAS,YAAY;MACxC,WAAW;MACX,UAAU,OAAO;MACjB,OAAO,MAAM;MACb,GAAI,MAAM,WAAW,gBACjB,EAAE,iBAAiB,MAAM,UAAU,cAAc,IACjD,CAAC;KACP,CAAC;IACH,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,cAAc;KAC/B,UAAU,OAAO,EAAE;KACnB,IAAI,QAAQ,OAAO,EAAE,GAAG,KAAK;IAC/B,CAAC;GACH;GAEA,MAAM,MAAM,IAAI,SAAS,KAAK,UAAU,IAAI;GAC5C,KAAK;GACL,OAAO;EACT;;;ECjDA,MAAa,qBAAqB;;;ECElC,SAAgB,uBAAuB,YAAY,UAAU;GAC3D,MAAM,UAAU,UAAU;GAC1B,IAAI,YAAY,KAAA,GAAW;IACzB,MAAM,QAAQ,YAAY,OAAO,MAAK,cAAa,UAAU,YAAY,SAAS,OAAO,CAAC;IAC1F,IAAI,OAAO,OAAO;GACpB;GACA,MAAM,SAAS,YAAY;GAC3B,OAAO,YAAY,OAAO,MAAK,cAAa,UAAU,gBAAgB,MAAM,KAAK;EACnF;EAEA,eAAsB,oBAAoB,KAAK,YAAY,OAAO;GAChE,MAAM,WAAW,MAAM,UAAU,oBAAoB,YAAY,QAAQ,GAAG,CAAC;GAC7E,MAAM,OAAO,MAAM,iBAAiB,QAAQ;GAC5C,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,MAAM,WAAW,uCAAuC,SAAS,QAAQ;GAC3G,OAAO;EACT;EAEA,eAAsB,sBAAsB,KAAK,EAAE,YAAY,eAAe,CAAC,GAAG,YAAY,OAAO;GACnG,MAAM,WAAW,MAAM,UAAU,oBAAoB,YAAY,UAAU,KAAK,UAAU,CAAC;GAC3F,IAAI,CAAC,SAAS,IAAI;IAChB,MAAM,OAAO,MAAM,iBAAiB,QAAQ;IAC5C,MAAM,IAAI,MAAM,MAAM,WAAW,kCAAkC,SAAS,QAAQ;GACtF;GACA,IAAI,YAAY;GAChB,WAAW,MAAM,SAAS,aAAa,SAAS,IAAI,GAAG;IACrD,IAAI,OAAO,SAAS,YAAY,aAAa,KAAK;IAClD,IAAI,OAAO,SAAS,YAAY,YAAY,MAAM;IAClD,IAAI,OAAO,SAAS,SAAS,MAAM,IAAI,MAAM,MAAM,WAAW,sBAAsB;GACtF;GACA,IAAI,cAAc,MAAM,MAAM,IAAI,MAAM,gDAAgD;GACxF,OAAO;EACT;EAEA,eAAsB,yBAAyB,UAAU,YAAY;GACnE,MAAM,SAAS,QAAQ;GACvB,MAAM,WAAW,QAAQ;EAC3B;EAEA,gBAAuB,aAAa,MAAM;GACxC,IAAI,CAAC,QAAQ,OAAO,KAAK,cAAc,YAAY,MAAM,IAAI,MAAM,6CAA6C;GAChH,MAAM,SAAS,KAAK,UAAU;GAC9B,MAAM,UAAU,IAAI,YAAY;GAChC,IAAI,SAAS;GACb,IAAI;IACF,OAAO,MAAM;KACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;KAC1C,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC;KACjD,IAAI,UAAU,OAAO,QAAQ,IAAI;KACjC,OAAO,YAAY,IAAI;MACrB,MAAM,OAAO,OAAO,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK;MAC3C,SAAS,OAAO,MAAM,UAAU,CAAC;MACjC,IAAI,MAAM,MAAM,WAAW,IAAI;MAC/B,UAAU,OAAO,QAAQ,IAAI;KAC/B;KACA,IAAI,MAAM;IACZ;IACA,MAAM,YAAY,OAAO,KAAK;IAC9B,IAAI,WAAW,MAAM,WAAW,SAAS;GAC3C,UAAU;IACR,OAAO,YAAY;GACrB;EACF;EAEA,SAAS,YAAY,QAAQ,KAAK,YAAY;GAC5C,OAAO;IACL,QAAQ;IACR,SAAS,EAAE,gBAAgB,mBAAmB;IAC9C,MAAM,KAAK,UAAU;KACnB;KACA;KACA,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;IACnD,CAAC;GACH;EACF;EAEA,eAAe,iBAAiB,UAAU;GACxC,IAAI;IACF,OAAO,MAAM,SAAS,KAAK;GAC7B,QAAQ;IACN,OAAO;GACT;EACF;EAEA,SAAS,WAAW,MAAM;GACxB,IAAI;IACF,OAAO,KAAK,MAAM,IAAI;GACxB,QAAQ;IACN,MAAM,IAAI,MAAM,gDAAgD;GAClE;EACF;;;EC3FA,SAAgB,4BAA4B,OAAO,WAAW,GAAG,SAAS,GAAG;GAC3E,IAAI,UAAU,aACZ,OAAO,OAAO,OAAO;IAAE,UAAU;IAAO,SAAS;IAAa,iBAAiB;GAAK,CAAC;GAEvF,IAAI,UAAU,WACZ,OAAO,OAAO,OAAO;IACnB,UAAU;IACV,WAAW;IACX,SAAS;IACT,iBAAiB,aAAa;GAChC,CAAC;GAEH,IAAI,UAAU,SACZ,OAAO,OAAO,OAAO;IAAE,UAAU;IAAM,WAAW;IAAU,SAAS;IAAS,iBAAiB;GAAM,CAAC;GAExG,IAAI,UAAU,cAAc,SAAS,GACnC,OAAO,OAAO,OAAO;IAAE,UAAU;IAAM,WAAW;IAAS,SAAS;IAAS,iBAAiB;GAAM,CAAC;GAEvG,OAAO,OAAO,OAAO;IAAE,UAAU;IAAM,SAAS;IAAS,iBAAiB;GAAM,CAAC;EACnF;EAEA,SAAgB,iCAAiC,OAAO;GACtD,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;GAClD,MAAM,eAAe,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,eAC1F,QAAQ,MACR;GACJ,MAAM,OAAO,IAAI,KAAK,YAAY;GAClC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO;EAC/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECkEA,SAAgB,0BAA0B,EACxC,MACA,kCACA,gCACA,eACA,iBACA,uBACA,KACmB;GAGnB,MAAM,kBAAkB,uBAFL,kCAAiC,UAAS,KAEL,GADvC,gCAA+B,UAAS,KACS,CAAC;GACnE,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,SAAA,CAAoB,KAAK;GACtC,MAAM,CAAC,QAAQ,cAAA,GAAA,MAAA,SAAA,CAA4C,IAAI;GAC/D,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,SAAA,CAA4B,MAAM;GAChD,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,SAAA,CAAuC,IAAI;GAC3D,MAAM,CAAC,YAAY,kBAAA,GAAA,MAAA,SAAA,CAAgD,CAAC,CAAC;GACrE,MAAM,CAAC,aAAa,mBAAA,GAAA,MAAA,SAAA,iBAAgD,IAAI,IAAI,CAAC;GAC7E,MAAM,CAAC,UAAU,gBAAA,GAAA,MAAA,SAAA,CAAyC,IAAI;GAC9D,MAAM,CAAC,QAAQ,cAAA,GAAA,MAAA,SAAA,CAA2C,IAAI;GAC9D,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,SAAA,CAAqB,EAAE;GACrC,MAAM,WAAA,GAAA,MAAA,OAAA,CAAiB,CAAC;GAExB,MAAM,cAAoB;IACxB,IAAI,CAAC,4BAA4B,OAAO,YAAY,MAAM,QAAQ,MAAM,CAAC,CAAC,UAAU;IACpF,QAAQ,WAAW;IACnB,QAAQ,KAAK;GACf;GAEA,MAAM,QAAQ,cAAmC;IAC/C,MAAM,aAAa,EAAE,QAAQ;IAC7B,SAAS,UAAU;IACnB,WAAW,IAAI;IACf,cAAc,CAAC,CAAC;IAChB,+BAAe,IAAI,IAAI,CAAC;IACxB,YAAY,IAAI;IAChB,UAAU,IAAI;IACd,SAAS,EAAE;IACX,cAAmB,UAAU,IAAI,CAAC,CAAC,MACjC,aAAY;KACV,IAAI,QAAQ,YAAY,YAAY;KACpC,WAAW,SAAS,OAAO;KAC3B,cAAc,SAAS,UAAU;KACjC,eAAe,IAAI,IAAI,SAAS,WAAW,KAAI,cAAa,UAAU,EAAE,CAAC,CAAC;KAC1E,SAAS,SAAS;IACpB,IACA,WAAU;KACR,IAAI,QAAQ,YAAY,YAAY;KACpC,SAAS,UAAU,MAAM,CAAC;KAC1B,SAAS,OAAO;IAClB,CACF;GACF;GAEA,MAAM,cAAoB;IACxB,MAAM,WAAW;IACjB,UAAU,QAAQ;IAClB,QAAQ,IAAI;IACZ,IAAI,aAAa,MAAM;KACrB,SAAS,cAAc;KACvB;IACF;IACA,KAAK,QAAQ;GACf;GAEA,MAAM,uBAA6B;IACjC,MAAM,aAAa,WAChB,QAAO,cAAa,YAAY,IAAI,UAAU,EAAE,CAAC,CAAC,CAClD,KAAI,cAAa,UAAU,EAAE;IAChC,IAAI,WAAW,QAAQ,YAAY,QAAQ,WAAW,WAAW,KAAK,UAAU,aAAa;IAC7F,MAAM,aAAa,EAAE,QAAQ;IAC7B,SAAS,WAAW;IACpB,YAAY;KACV,WAAW;KACX,OAAO,WAAW;KAClB,OAAO,WAAW;KAClB,UAAU;KACV,UAAU;KACV,QAAQ;KACR,UAAU,CAAC;IACb,CAAC;IACD,SAAS,EAAE;IACX,CAAM,YAAY;KAChB,IAAI;MACF,MAAM,YAAY,MAAM,gBAAgB,OAAO,MAAM,aAAY,WAAU;OACzE,IAAI,QAAQ,YAAY,YAAY,YAAY,MAAM;MACxD,CAAC;MACD,MAAM,sBAAsB;MAC5B,IAAI,QAAQ,YAAY,YAAY;MACpC,UAAU,SAAS;MACnB,SAAS,UAAU;KACrB,SAAS,QAAQ;MACf,IAAI,QAAQ,YAAY,YAAY;MACpC,SAAS,UAAU,MAAM,CAAC;MAC1B,SAAS,OAAO;KAClB;IACF,EAAA,CAAG;GACL;GAEA,MAAM,cAAoB;IACxB,IAAI,WAAW,MAAM,KAAK,MAAM;GAClC;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,SAAD;IAAS,OAAO,EAAE,cAAc;IAAG,SAAS;IAAK,UAAU;cACzD,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;KACE,MAAK;KACL,WAAWC,6CAAI;KACf,cAAY,EAAE,cAAc;KAC5B,SAAS;eAJX,CAME,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,uBAAD,EAAuB,MAAM,OAAO,KAAK,GAAK,CAAA,GAC7C,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,cAAc,EAAQ,CAAA,CAClC;;GACD,CAAA,GACT,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,OAAD;IACQ;IACN,SAAS;IACT,OAAO,EAAE,aAAa;IACtB,YAAY,EAAE,OAAO;IACrB,aAAa,EAAE,mBAAmB;IAClC,WAAWF,6CAAI;IACf,QAAQ,YAAY;KAClB;KACA,eAAe,YAAY;KAC3B;KACA;KACA;KACA;KACA;IACF,CAAC;cAED,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,6CAAI;KAAM,aAAU;eAApC;MACG,WAAW,QACV,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAWA,6CAAI;iBAApB,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAA,UAAS,OAAO,MAAc,CAAA,GAC9B,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,OAAO,OAAO;kBAAO,OAAO;OAAW,CAAA,CAC1C;;MAEN,UAAU,kBAAkB,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAWA,6CAAI;iBAAU,EAAE,mBAAmB;MAAK,CAAA;MAClF,UAAU,cAAc,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAWA,6CAAI;iBAAU,EAAE,gBAAgB;MAAK,CAAA;MAC3E,UAAU,aAAa,YAAY,QAClC,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;OACW;OACG;OACC;OACb,mBAAmB;OAChB;MACJ,CAAA;MAEF,UAAU,eAAe,aAAa,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAD;OAAwB;OAAa;MAAI,CAAA;MACvF,UAAU,cAAc,WAAW,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;OAAoB;OAAW;MAAI,CAAA;MAC9E,UAAU,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAWA,6CAAI;OAAO,MAAK;iBAAS,SAAS,EAAE,cAAc;MAAK,CAAA;KACxF;;GACA,CAAA,CACP,EAAA,CAAA;EAEN;EAEA,SAAS,YAAY,EACnB,SACA,YACA,aACA,mBACA,KAOY;GACZ,MAAM,UAAU,IAAY,YAA2B;IACrD,MAAM,OAAO,IAAI,IAAI,WAAW;IAChC,IAAI,SAAS,KAAK,IAAI,EAAE;SACnB,KAAK,OAAO,EAAE;IACnB,kBAAkB,IAAI;GACxB;GACA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWA,6CAAI;cAApB,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;KAAI,WAAWA,6CAAI;eAAnB;MACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,aAAa;OAAG,OAAO,QAAQ;MAAQ,CAAA;MACxD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,gBAAgB;OAAG,OAAO,QAAQ;MAAW,CAAA;MAC9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,mBAAmB;OAAG,OAAO,QAAQ;MAAc,CAAA;MACpE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,aAAa;OAAG,OAAO,QAAQ;OAAO,QAAA;MAAQ,CAAA;KAC7D;QACH,WAAW,WAAW,IACrB,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;KAAG,WAAWA,6CAAI;eAAU,EAAE,aAAa;IAAK,CAAA,IAEhD,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,6CAAI;eAApB,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD,EAAA,UAAA;MAAO,EAAE,gBAAgB;MAAE;MAAG,YAAY;MAAK;MAAI,WAAW;KAAa,EAAA,CAAA,GAC3E,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MAAQ,MAAK;MAAS,eAAe,kBAAkB,IAAI,IAAI,WAAW,KAAI,cAAa,UAAU,EAAE,CAAC,CAAC;gBACtG,EAAE,iBAAiB;KACd,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MAAQ,MAAK;MAAS,eAAe,kCAAkB,IAAI,IAAI,CAAC;gBAC7D,EAAE,sBAAsB;KACnB,CAAA,CACL,EAAA,CAAA,CACF;QACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;KAAI,WAAWA,6CAAI;KAAY,cAAY,EAAE,kBAAkB;eAC5D,WAAW,KAAI,cACd,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,SAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;MACE,MAAK;MACL,SAAS,YAAY,IAAI,UAAU,EAAE;MACrC,WAAU,UAAS,OAAO,UAAU,IAAI,MAAM,cAAc,OAAO;KACpE,CAAA,GACD,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAWA,6CAAI;gBAArB;OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;QAAM,WAAWA,6CAAI;kBAArB,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAA,UAAS,UAAU,MAAc,CAAA,GACjC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,UAAU,WAAW,gBAAgB,EAAE,yBAAyB,IAAI,EAAE,mBAAmB,EAAQ,CAAA,CACpG;;OACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,UAAU,GAAS,CAAA;OAC1B,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,OAAO,UAAU;kBAAM,UAAU;OAAU,CAAA;OACjD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,UAAU,cAAc,UAAU,SAAS;kBAAI,gBAAgB,UAAU,SAAS;OAAQ,CAAA;MAC5F;OACD,EAAA,CAAA,EACL,GAjBK,UAAU,EAiBf,CACL;IACC,CAAA,CACJ,EAAA,CAAA,CAED;;EAET;EAEA,SAAS,aAAa,EAAE,UAAU,KAAuD;GACvF,MAAM,UAAU,KAAK,IAAI,GAAG,SAAS,KAAK;GAC1C,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWA,6CAAI;cAApB,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,6CAAI;eAApB,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAA,UAAS,EAAE,iBAAiB,EAAU,CAAA,GACtC,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD,EAAA,UAAA;MAAO,SAAS;MAAU;MAAI,SAAS;KAAY,EAAA,CAAA,CAChD;QACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;KAAU,OAAO,SAAS;KAAW,KAAK;KAAS,cAAY,EAAE,iBAAiB;IAAI,CAAA,CACnF;;EAET;EAEA,SAAS,WAAW,EAAE,QAAQ,KAAyD;GACrF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA;IACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;KAAG,WAAW,OAAO,SAAS,IAAIA,6CAAI,UAAUA,6CAAI;eACjD,OAAO,SAAS,IAAI,EAAE,eAAe,IAAI,EAAE,gBAAgB;IAC3D,CAAA;IACH,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;KAAI,WAAWA,6CAAI;eAAnB;MACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,gBAAgB;OAAG,OAAO,OAAO;OAAU,QAAA;MAAQ,CAAA;MACpE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,gBAAgB;OAAG,OAAO,OAAO;MAAW,CAAA;MAC7D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAQ,OAAO,EAAE,gBAAgB;OAAG,OAAO,OAAO;OAAQ,QAAQ,OAAO,SAAS;MAAI,CAAA;KACpF;;IACH,OAAO,SAAS,SAAS,KACxB,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;KAAI,WAAWA,6CAAI;KAAU,cAAY,EAAE,gBAAgB;eACxD,OAAO,SAAS,KAAI,YACnB,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,QAAQ,QAAc,CAAA,GAC7B,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,QAAQ,QAAc,CAAA,CAC3B,EAAA,GAHK,QAAQ,OAGb,CACL;IACC,CAAA;GAEH,EAAA,CAAA;EAET;EAEA,SAAS,OAAO,EACd,OAAO,OAAO,SAAS,OAAO,SAAS,SAC2C;GAClF,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWA,6CAAI;cAApB,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAA,UAAK,MAAU,CAAA,GACf,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;KAAI,WAAW,SAASA,6CAAI,cAAc,SAASA,6CAAI,cAAc,KAAA;eAAY;IAAU,CAAA,CACxF;;EAET;EAEA,SAAS,YAAY,EACnB,OAAO,eAAe,QAAQ,OAAO,OAAO,gBAAgB,KAShD;GACZ,MAAM,SAAS,4BAA4B,OAAO,eAAe,QAAQ,MAAM;GAC/E,MAAM,UAAyE;IAC7E,QAAQ;IACR;IACA,mBAAmB;IACnB,WAAW,KAAA;IACX;GACF;GACA,MAAM,SAAsD;IAC1D,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,OAAO;IAChB,mBAAmB,EAAE,sBAAsB;IAC3C,WAAW,EAAE,iBAAiB;IAC9B,OAAO,EAAE,OAAO;GAClB;GACA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACG,OAAO,cAAc,KAAA,KACpB,iBAAA,GAAA,kBAAA,IAAA,CAACG,sCAAAA,QAAD;IAAQ,SAAQ;IAAU,SAAS,QAAQ,OAAO;cAC/C,OAAO,OAAO;GACT,CAAA,GAEV,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;IACE,SAAS,OAAO,YAAY,UAAU,YAAY,KAAA;IAClD,UAAU,OAAO;IACjB,SAAS,QAAQ,OAAO;cAEvB,OAAO,OAAO;GACT,CAAA,CACR,EAAA,CAAA;EAEN;EAEA,SAAS,cAAc,OAAmD;GAExE,OADa,iCAAiC,KACpC,CAAC,EAAE,YAAY;EAC3B;EAEA,SAAS,gBAAgB,OAAuC;GAC9D,MAAM,OAAO,iCAAiC,KAAK;GACnD,OAAO,SAAS,OAAO,MAAM,IAAI,KAAK,eAAe,KAAA,GAAW;IAC9D,WAAW;IACX,WAAW;GACb,CAAC,CAAC,CAAC,OAAO,IAAI;EAChB;EAEA,SAAS,UAAU,QAAyB;GAC1C,OAAO,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM;EACjE;;;;;;;;;;;;;;;;;;;;ECnaA,SAAS,SAAS,QAAqD;GACrE,IAAI,WAAW,WAAW,OAAO;GACjC,IAAI,WAAW,SAAS,OAAO;GAC/B,OAAO;EACT;EAEA,MAAa,sBAAA,GAAA,MAAA,KAAA,CAA0B,SAAS,mBAAmB,EAAE,QAAiC;GACpG,MAAM,WAAW,KAAK;GACtB,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,SAAA,CAAoB,KAAK;GACtC,MAAM,aAAa,SAAS,UAAU,KAAA,KAAa,SAAS,WAAW,KAAA,KAAa,SAAS,eAAe,KAAA;GAC5G,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAWC,sCAAI;IAAU,wBAAsB,SAAS;cAC3D,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,eAAD;KACE,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,mBAAD,CAAoB,CAAA;KAC1B,OAAO,SAAS;KACV;KACM;KACZ,gBAAgB;MAAE,SAAQ,UAAS,CAAC,KAAK;KAAE;KAC3C,kBAAA;KACA,kBACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;MAAM,WAAWF,sCAAI;gBAArB,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,SAAS,QAAc,CAAA,GAC9B,iBAAA,GAAA,kBAAA,IAAA,CAACG,sCAAAA,UAAD;OAAU,OAAO,SAAS,SAAS,MAAM;OAAG,MAAM;MAAI,CAAA,CAClD;;eAGR,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWH,sCAAI;gBAApB;OACG,SAAS,eAAe,KAAA,IACvB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QACE,WAAWA,sCAAI;QACf,OAAO,yBAAyB,SAAS,WAAW,gBAAgB,UAAU,SAAS,WAAW;kBAFpG;SAGC;SACwB,QAAQ,SAAS,WAAW,eAAe;SAAE;SAAS,QAAQ,SAAS,WAAW,MAAM;QAC5G;YACH;OACH,SAAS,UAAU,KAAA,IAAY,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAA,UAAM,SAAS,MAAW,CAAA,IAAI;OAC7D,SAAS,WAAW,KAAA,IAAY,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAA,UAAM,SAAS,OAAY,CAAA,IAAI;MAC7D;;IACQ,CAAA;GACZ,CAAA;EAET,CAAC;EAED,SAAS,QAAQ,OAAuB;GACtC,OAAO,MAAM,SAAS,KAAK,GAAG,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,MAAM,MAAM,EAAE,MAAM;EAC3E;;;ECpBA,MAAa,2BAA2E;GACtF,MAAM;GACN,QAAQ;GACR,QAAO,UAAS,MAAM,SAAS,0BAC3B;IAAE,IAAI,MAAM,KAAK;IAAQ,MAAM,MAAM,KAAK,UAAU,YAAY,UAAU;GAAS,IACnF;GACJ,QAAQ,UAAU,UAAU;IAC1B,IAAI,MAAM,MAAM,SAAS,yBACvB,MAAM,IAAI,MAAM,sDAAsD;IAExE,OAAO;KACL,GAAG,MAAM,MAAM,KAAK;KACpB,YAAY;MACV,iBAAiB,MAAM,MAAM,KAAK;MAClC,QAAQ,MAAM,MAAM,KAAK;KAC3B;IACF;GACF;GACA,SAAS,SAAS,UAAU,MAAM,MAAM,SAAS,0BAC7C;IACE,GAAG,MAAM,MAAM,KAAK;IACpB,YAAY;KACV,iBAAiB,MAAM,MAAM,KAAK;KAClC,QAAQ,MAAM,MAAM,KAAK;IAC3B;GACF,IACA,QAAQ;GACZ,gBAAgB,YAA6C;IAC3D,IAAI,QAAQ,UAAU,KAAA,KAAa,QAAQ,UAAU,KAAA,GAAW,OAAO;IACvE,OAAO;KACL,KAAK,QAAQ;KACb,MAAM;KACN,IAAI,QAAQ;KACZ,QAAQ;KACR,WAAW,QAAQ,MAAM,MAAM;KAC/B,UAAU,QAAQ,MAAM;KACxB,YAAY;KACZ,MAAM,QAAQ;IAChB;GACF;EACF;;;EC9EA,MAAa,KAAK;GAChB,cAAc;GACd,aAAa;GACb,mBAAmB;GACnB,mBAAmB;GACnB,gBAAgB;GAChB,aAAa;GACb,gBAAgB;GAChB,mBAAmB;GACnB,aAAa;GACb,aAAa;GACb,gBAAgB;GAChB,iBAAiB;GACjB,sBAAsB;GACtB,kBAAkB;GAClB,mBAAmB;GACnB,yBAAyB;GACzB,sBAAsB;GACtB,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;GACf,gBAAgB;GAChB,gBAAgB;GAChB,cAAc;GACd,QAAQ;GACR,OAAO;GACP,OAAO;EACT;EAEA,MAAa,KAAsC;GACjD,cAAc;GACd,aAAa;GACb,mBAAmB;GACnB,mBAAmB;GACnB,gBAAgB;GAChB,aAAa;GACb,gBAAgB;GAChB,mBAAmB;GACnB,aAAa;GACb,aAAa;GACb,gBAAgB;GAChB,iBAAiB;GACjB,sBAAsB;GACtB,kBAAkB;GAClB,mBAAmB;GACnB,yBAAyB;GACzB,sBAAsB;GACtB,iBAAiB;GACjB,gBAAgB;GAChB,eAAe;GACf,gBAAgB;GAChB,gBAAgB;GAChB,cAAc;GACd,QAAQ;GACR,OAAO;GACP,OAAO;EACT;;;ECnCA,MAAa,SAAS;GAAC;GAAS;GAAS;GAAU;GAAU;GAAY;GAAc;GAAc;EAAoB;EAEzH,eAAsB,MAAM,KAAkD;GAC5E,IAAI,aAAa,IAAI,OAAO,SAAS,gBAAgB;IAAE;IAAI;GAAG,CAAC,GAAG,4BAA4B;GAC9F,IAAI,mBAAmB,SAAS,wBAAwB;GACxD,IAAI,MAAM,OAAO,gCAAgC,IAAI,MAAM,SAAS;IAClE,MAAM;IAA0B,KAAK;GACvC,GAAG,kBAAkB,CAAC;GACtB,mBAAmB,GAAG;GACtB,MAAM,cAAc,sBAAsB,KAA8B,gBAAgB,gBAAgB,aAAa;GACrH,OAAO,YAAY;IAAE,YAAY;GAAE;EACrC;EAEA,SAAS,mBAAmB,KAA0B;GACpD,MAAM,kBAA+C;IACnD,OAAO;KACL,+BAA+B,IAAI,WAAW;KAC9C,6BAA6B,IAAI,SAAS;IAC5C;IACA,gBAAe,QAAO,oBAAoB,GAAG;IAC7C,kBAAkB,KAAK,YAAY,eAAe,sBAAsB,KAAK;KAAE;KAAY;IAAW,CAAC;IACvG,6BAA6B,yBAC3B,IAAI,UACJ,IAAI,UACN;GACF;GACA,IAAI,MAAM,OAAO,+BAA+B,IAAI,MAAM,SAAS;IACjE,MAAM;IACN,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,QAAQ;GACV,GAAG,yBAAyB,CAAC;EAC/B"}
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.4",
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": "npm run prepare:dsh && node --test test/*.test.mjs",
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
  }