{"_id":"@dsh-client/ui-question-anchors","_rev":"2-da39d0d9a0141bb7185dc28267f19d72","name":"@dsh-client/ui-question-anchors","dist-tags":{"latest":"1.0.0"},"versions":{"0.1.0":{"name":"@dsh-client/ui-question-anchors","version":"0.1.0","keywords":["deepseek-harness","dsh","plugin","client","anchors","conversation"],"license":"MIT","_id":"@dsh-client/ui-question-anchors@0.1.0","maintainers":[{"name":"lanyincao","email":"1025687605@qq.com"}],"homepage":"https://github.com/snakeUni/dsh-question-anchors#readme","bugs":{"url":"https://github.com/snakeUni/dsh-question-anchors/issues"},"dsh":{"client":{"inject":["@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-runtime","@deepseek-ai/dsh-client-ui-layout"],"platform":"web"}},"dist":{"shasum":"82217207c0a3bad9e0f77e7fd93d9cdc38cb04dc","tarball":"https://registry.npmjs.org/@dsh-client/ui-question-anchors/-/ui-question-anchors-0.1.0.tgz","fileCount":4,"integrity":"sha512-dlAIHqDeDS0++Ha9KHJWvdwkf61MVOdLBS3etrNXgqRzhSmDJf2ON/YCO+9V1Z8eAXFlgzAMcuBu8x/uQClDlg==","signatures":[{"sig":"MEUCIQDInvBoIz61wJPyOJYsauUguEbLzt0CJ4RdIAZNrXHUkgIgHJYow8nNLm7Rh2pThD4V/hGhLAI5pWEVi8yuYPmHP8o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27204},"main":"lib/index.js","type":"module","exports":{".":"./lib/index.js","./client":"./lib/client.js","./package.json":"./package.json"},"gitHead":"8ef74bdb59db5c1d37ef69c5775d3dd61198ed88","_npmUser":{"name":"lanyincao","email":"1025687605@qq.com"},"repository":{"url":"git+https://github.com/snakeUni/dsh-question-anchors.git","type":"git"},"_npmVersion":"11.17.0","description":"DeepSeek Harness Web question-anchor plugin: a right-side floating panel listing every user question in the current conversation; clicking an item smoothly scrolls the chat to that message","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"peerDependencies":{"react":"^18.2.0","@deepseek-ai/cordis":"^4.0.1"},"_npmOperationalInternal":{"tmp":"tmp/ui-question-anchors_0.1.0_1786673473760_0.7671089969846878","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@dsh-client/ui-question-anchors","description":"DeepSeek Harness Web question-anchor plugin: a right-side floating panel listing every user question in the current conversation; clicking an item smoothly scrolls the chat to that message","version":"1.0.0","keywords":["deepseek-harness","dsh","plugin","client","anchors","conversation"],"type":"module","main":"lib/index.js","exports":{".":"./lib/index.js","./client":"./lib/client.js","./package.json":"./package.json"},"dsh":{"client":{"platform":"web","inject":["@deepseek-ai/dsh-client-locale","@deepseek-ai/dsh-client-runtime","@deepseek-ai/dsh-client-ui-layout"]}},"peerDependencies":{"@deepseek-ai/cordis":"^4.0.1","react":"^18.2.0"},"repository":{"type":"git","url":"git+https://github.com/snakeUni/dsh-question-anchors.git"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"license":"MIT","gitHead":"6b9b3e695f3cab1b3bf895a7f13d70e401e8325b","_id":"@dsh-client/ui-question-anchors@1.0.0","bugs":{"url":"https://github.com/snakeUni/dsh-question-anchors/issues"},"homepage":"https://github.com/snakeUni/dsh-question-anchors#readme","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-J2bVvuVgXtgKXEgKbNwfqp/mZOsxoJRjbCKwTRYIab1LA6lCrpuCzw3V0eEMbn3oO6FAgQjAfGkmPTjArRtxIw==","shasum":"272b87b76e766df1e5b7cf286b0f5cc9af9a1a82","tarball":"https://registry.npmjs.org/@dsh-client/ui-question-anchors/-/ui-question-anchors-1.0.0.tgz","fileCount":4,"unpackedSize":27204,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dsh-client%2fui-question-anchors@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD+inuYfae6nGgrLD+EKVaB9SpU3jMHdPSuNIURPAJoBgIgbXpdz8lFaoREXZvs8Ym0GzsVjEfmPwzXvN/l5GP9nAU="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:c15bab9b-819a-4548-a76c-534e91b289db"}},"directories":{},"maintainers":[{"name":"lanyincao","email":"1025687605@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ui-question-anchors_1.0.0_1786673857049_0.6563713228859509"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-14T02:11:13.570Z","modified":"2026-08-14T02:17:37.514Z","0.1.0":"2026-08-14T02:11:13.893Z","1.0.0":"2026-08-14T02:17:37.191Z"},"bugs":{"url":"https://github.com/snakeUni/dsh-question-anchors/issues"},"license":"MIT","homepage":"https://github.com/snakeUni/dsh-question-anchors#readme","keywords":["deepseek-harness","dsh","plugin","client","anchors","conversation"],"repository":{"type":"git","url":"git+https://github.com/snakeUni/dsh-question-anchors.git"},"description":"DeepSeek Harness Web question-anchor plugin: a right-side floating panel listing every user question in the current conversation; clicking an item smoothly scrolls the chat to that message","maintainers":[{"name":"lanyincao","email":"1025687605@qq.com"}],"readme":"# @dsh-client/ui-question-anchors\n\nDeepSeek Harness Web 客户端插件：**右侧提问锚点面板**。\n\n在当前会话的对话中，把每一个用户提问（`user` / `steering` 消息）收集为右侧浮动面板中的一个锚点条目，显示提问序号和文字预览。点击条目，聊天区平滑滚动到对应提问处并短暂高亮该消息；滚动聊天区时面板会同步高亮当前所在提问（scroll-spy）。面板可收起为右侧的小圆钮，圆钮上实时显示提问数量。\n\n## 效果\n\n- 右侧浮动卡片：标题「提问锚点」+ 提问计数 + 收起按钮\n- 每个条目：序号 + 提问文字预览（最多 3 行）\n- 点击条目：`scrollIntoView` 式平滑滚动 + 2px 品牌色描边闪烁 1.6s\n- 滚动聊天区：自动高亮当前阅读位置的提问\n- 收起后：40px 圆钮，带提问数量徽标\n- 无会话或无提问时不显示\n- 右侧详情面板打开时自动让位（测量 `data-details-collapsed` + details 列宽度）\n- 中英双语（跟随 dsh 界面语言，缺省回退中文）\n\n## 架构\n\n纯浏览器插件（host 半场为空桩），复用现有 DSH 客户端机制，无任何侵入式改动：\n\n- 通过 `dsh.client` 声明被 `@deepseek-ai/dsh-client-modules` 扫描进 `window.__DSH_BOOT__` 引导图\n- 注册进布局壳声明的 **`shell.overlay`**（root 作用域 list 槽）——AppFrame 专为浮动 UI 提供的覆盖层（`position:absolute; inset:0; z-index:20`，`pointer-events:none`，面板自身 `pointer-events:auto`）\n- 数据源：`ctx.sessions.binding(sessionId).session`（`ObservableSnapshot<ConversationSnapshot>`，与 `useSession` 同一来源），经注册时的 inject 工厂注入组件，组件用 `useSyncExternalStore` 订阅当前会话\n- 当前会话 id：标准套件 `useSessions(s => s.current)`（root 作用域自带）\n- 锚点键：`snapshot.chat.order` + `chat.nodes.get(key)`，筛选 `kind === 'user' | 'steering'`；DOM 行由 `[data-chat-anchor-key]` 标识（与 `data-chat-flow-key` 同源，均为 Conversation Context key），滚动用 `[data-conversation-scroll]` 滚动容器 + `getBoundingClientRect` 差值计算，与 `ui-conversation` 内置逻辑一致\n- 样式：自带 `<style data-plugin-css>` 标签注入（materialization 时创建，HMR 可回收），全部使用 `--dsw-alias-*` / `--dsw-shadow-lv2` 设计 token，自动适配深浅主题\n\n## 文件\n\n```\ndsh-question-anchors/\n├── package.json          # dsh.client 声明（platform: web, inject 依赖边）\n├── lib/\n│   ├── index.js          # host 半场（空桩）\n│   └── client.js         # 浏览器插件（__ModuleLoader__.load 格式，无需构建）\n├── scripts/\n│   └── install.sh        # 安装到 web profile（幂等）\n└── README.md\n```\n\n客户端 bundle 是手写的 `window.__ModuleLoader__.load({id, factory})` 格式（与仓库内其他 `lib/client.js` 产物一致），只 `require` 平台 seed 词（`react`、`react/jsx-runtime`），因此**不需要 tsdown/构建步骤**。\n\n## 安装\n\n```sh\n# 1. 把插件挂进 web profile（软链到 profile 的 node_modules，源目录保持唯一）\n./scripts/install.sh\n\n# 2. 重启 dsh web（插件集变更需重启；热更新链只覆盖已存在的 bundle 内容变更）\n#    重启 dsh web 服务后刷新页面生效\n```\n\n安装脚本做两件事（均幂等，可重复执行）：\n\n1. `node_modules/@dsh-client/ui-question-anchors` → 软链到本目录\n2. 向 profile 的 `cordis.patch.yml`（`$DSH_HOME/profiles/web/cordis.patch.yml`，默认即 `~/.dsh/profiles/web/cordis.patch.yml`）追加一行插件行：\n\n```yaml\n- insert:\n    - id: ui-question-anchors\n      name: '@dsh-client/ui-question-anchors'\n```\n\n## 卸载\n\n删除 `cordis.patch.yml` 里对应的 insert 行，删除 profile node_modules 里的软链，重启即可。\n\n## 发布插件\n\n插件就是一个标准 npm 包（`dsh.client` 声明 + `exports[\"./client\"]` 客户端 bundle），发布流程与普通 npm 包一致。\n\n### 方案 A：发布到 npm registry\n\n```sh\nnpm login                       # 需要 npm 账号；私有 registry 先 npm config set registry <url>\nnpm publish                     # scoped 包（@yourname/...）加 --access public\n```\n\n> ⚠️ **包名 = 引导图条目 id = `lib/client.js` 里 `__ModuleLoader__.load({ id })`，三者必须严格一致**（当前为 `@dsh-client/ui-question-anchors`），不一致时浏览器会报 \"bundle loaded without registering\"。改名时三处同步。\n>\n> ⚠️ 发布到公共 npm 时，**`@dsh-client` 这个 scope 必须归你的账号所有**（npmjs.com → New Organization，免费创建），否则 `npm publish` 会因 scope 权限报错。\n\n安装到任意机器 / 任意 profile：\n\n```sh\ndsh plugin --profile web add @dsh-client/ui-question-anchors\n```\n\n然后在该 profile 的 `cordis.patch.yml` 追加插件行（只装包不会注册到 Loader）：\n\n```yaml\n- insert:\n    - id: ui-question-anchors\n      name: '@dsh-client/ui-question-anchors'\n```\n\n最后重启 dsh web 并硬刷新页面。\n\n### 方案 B：不发 registry，直接分发 tarball\n\n```sh\nnpm pack    # 生成 dsh-client-ui-question-anchors-0.1.0.tgz\n```\n\n把 tgz 发给对方，对方执行：\n\n```sh\ndsh plugin --profile web add /path/to/dsh-client-ui-question-anchors-0.1.0.tgz\n```\n\n同样追加 `cordis.patch.yml` 插件行并重启。\n\n### 方案 C：本地目录直装（开发期）\n\n```sh\ndsh plugin --profile web add file:/path/to/dsh-question-anchors\n```\n\n同样追加 `cordis.patch.yml` 插件行并重启。\n\n### 自动发布：GitHub Actions\n\n仓库内置 `.github/workflows/publish.yml`：**推送到 `main` 分支自动触发 `npm publish`**（也支持手动 `workflow_dispatch` 触发）。\n\n使用前提（一次性配置）：\n\n1. 把仓库推到 GitHub（`main` 分支）\n2. 在 npmjs.com 生成 **Publish 权限**的 Access Token，添加到仓库 Secrets，命名 `NPM_TOKEN`\n3. 发布新版本前先在 `package.json` 里 `version` +1 再推送——npm 不允许覆盖已存在的版本，工作流检测到当前版本已发布会直接跳过（重复推送是绿色 no-op，不是红叉）\n\n> 包无运行时依赖（仅 peerDependencies），工作流不需要 `npm ci`，直接 `npm publish`。\n\n### 发布检查清单\n\n- [x] `package.json` 无 `private: true`（已移除）\n- [x] `files: [\"lib\"]` —— tarball 只含 `lib/`、README、package.json（`npm pack --dry-run` 已验证）\n- [x] `dsh.client.platform: \"web\"` + `exports[\"./client\"]` —— 客户端模块扫描入口\n- [x] `lib/client.js` 内 loader `id` 与包名一致（改名时注意同步）\n- [x] `peerDependencies`：`react`、`@deepseek-ai/cordis`\n- [ ] 更新版本号：npm 不允许同版本覆盖，迭代时改 `version` 再 `npm publish`\n- [ ] （可选）补充 `repository`、`author` 字段\n\n依赖说明：`dsh.client.inject` 引用的 `@deepseek-ai/dsh-client-*` 是 `dsh-web-app` bundle 自带依赖，任何 web profile 都能解析，无需额外安装。\n\n## 已知限制\n\n- 插件行加入/移除需要重启 web 服务（`dsh-client-hmr` 只监听已存在 bundle 的内容变化，不监听插件集变化）\n- 轨迹视图（trajectory tab）下聊天行未渲染，点击锚点无目标可滚（面板仍在，行不存在时点击为空操作）\n- 面板宽度 252px，极小窗口下可能遮挡聊天内容（可自行收起）\n","readmeFilename":"README.md"}