dsh-mobile-flow 0.1.0
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/LICENSE +21 -0
- package/README.md +63 -0
- package/README.zh.md +63 -0
- package/cordis.patch.yml +6 -0
- package/lib/client.js +67 -0
- package/lib/index.js +10 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 roc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# dsh-mobile-flow
|
|
2
|
+
|
|
3
|
+
**English** | [简体中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
Mobile in-flow composer for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) Web UI: on narrow screens (≤720px) the input bar and AI confirmation cards scroll with the page instead of pinning to the viewport floor — swipe up to read and the message transcript gets the full screen back.
|
|
6
|
+
|
|
7
|
+
A pure client-side CSS overlay. No product source is modified; removing the plugin restores the stock behavior exactly.
|
|
8
|
+
|
|
9
|
+
## The problem
|
|
10
|
+
|
|
11
|
+
The stock Web UI pins the composer seat with `position: sticky; bottom: 0`. That seat hosts not only the input bar but also the interactive cards the AI raises mid-conversation — `ask_user_question` option cards, approval prompts, plan review. On a phone all of them stay glued to the bottom of the screen, permanently eating a chunk of the viewport while you scroll back through replies.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
On viewports ≤720px (the same breakpoint the official question card uses):
|
|
16
|
+
|
|
17
|
+
1. **The composer seat joins the document flow** — input bar and confirmation cards now live at the end of the transcript. Swipe up and they scroll out of view; the transcript becomes full-screen.
|
|
18
|
+
2. **Short conversations still dock to the bottom** — when the transcript is shorter than one screen, the message area stretches so the composer stays flush with the viewport floor, visually identical to the stock behavior. Long conversations get the full-screen treatment.
|
|
19
|
+
3. **Floating controls re-anchor** — the back-to-bottom button and turn navigator no longer reserve height for the sticky seat and sit close to the viewport floor again.
|
|
20
|
+
|
|
21
|
+
Desktop (wide viewports) is completely unaffected.
|
|
22
|
+
|
|
23
|
+
## How it works
|
|
24
|
+
|
|
25
|
+
The plugin ships a browser half (`exports["./client"]`, declared via `dsh.client.platform: "web"`), discovered by the client-modules scanner and loaded from the boot manifest. It injects one `<style>` tag with `@media (max-width: 720px)` overrides and removes the tag on unload — fully reversible.
|
|
26
|
+
|
|
27
|
+
All selectors target the product's stable `data-*` attributes (`data-composer-seat`, `data-conversation-scroll`, `data-phase`, `data-slot`), never CSS-Modules-hashed class names. The sticky-to-static switch is guarded with `:not(:has([data-conversation-composer-overlay]))` so views that own their composer overlay (e.g. trajectory) keep the official absolute positioning. On engines without `:has()` the rules degrade safely back to the stock sticky behavior.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- DeepSeek Harness Web profile (`dsh web`), any recent 0.1.x release
|
|
32
|
+
- Selectors verified against 0.1.2-rc.1; they target product slot contracts that are stable within a version line but may need small updates after a major product revamp
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
### From npm
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
dsh plugin --profile web add dsh-mobile-flow
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### From GitHub
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
dsh plugin --profile web add github:imroc/dsh-mobile-flow
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Restart `dsh web`, then refresh the browser page.
|
|
49
|
+
|
|
50
|
+
## Verify
|
|
51
|
+
|
|
52
|
+
Open a session on a phone (or a desktop DevTools window narrowed to ≤720px): swipe up a few screens — the input bar and confirmation cards should scroll away with the messages. Trigger a tool that asks a question (or just check the input bar with a long transcript): the card sits at the end of the transcript instead of the screen bottom. Widen the window and the stock behavior returns.
|
|
53
|
+
|
|
54
|
+
## Rollback
|
|
55
|
+
|
|
56
|
+
- Bundle install: `dsh plugin --profile web remove dsh-mobile-flow`
|
|
57
|
+
- Manual: remove the dependency and the `dsh.profile.bundles` entry, restart `dsh web`
|
|
58
|
+
|
|
59
|
+
No product source is modified; upgrades do not overwrite it.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# dsh-mobile-flow
|
|
2
|
+
|
|
3
|
+
[English](README.md) | **简体中文**
|
|
4
|
+
|
|
5
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)Web UI 的手机端 in-flow composer 插件:窄屏(≤720px)时输入框与 AI 确认选择框随页面滚动,而不是钉死在屏幕底部——上滑阅读时消息区拿回全屏空间。
|
|
6
|
+
|
|
7
|
+
纯客户端 CSS overlay,不修改产品源码;卸载插件即完全还原官方行为。
|
|
8
|
+
|
|
9
|
+
## 解决的问题
|
|
10
|
+
|
|
11
|
+
官方 Web UI 用 `position: sticky; bottom: 0` 把 composer 座位钉在视口底。这个座位承载的不只是输入框,还有 AI 会话中途弹出的交互卡片——`ask_user_question` 选项卡、approval 权限确认框、plan review。手机上它们全部粘在屏幕底部,往回翻阅回复时永久遮挡一块视口。
|
|
12
|
+
|
|
13
|
+
## 实际效果
|
|
14
|
+
|
|
15
|
+
≤720px 视口(与官方问题卡片的断点一致)下:
|
|
16
|
+
|
|
17
|
+
1. **composer 座位回归文档流** —— 输入框和确认卡片位于消息流末尾。上滑时随内容滚出视口,消息全屏可读。
|
|
18
|
+
2. **短会话仍然贴底** —— 消息不足一屏时消息区自动拉伸,输入框保持贴视口底,视觉与官方行为完全一致;长会话则享受全屏阅读。
|
|
19
|
+
3. **浮动控件重新锚定** —— 回到底部按钮、轮次导航不再为吸底座位预留高度,回到贴近视口底的位置。
|
|
20
|
+
|
|
21
|
+
桌面端(宽视口)完全不受影响。
|
|
22
|
+
|
|
23
|
+
## 工作原理
|
|
24
|
+
|
|
25
|
+
插件带浏览器半(`exports["./client"]`,经 `dsh.client.platform: "web"` 声明),由 client-modules 扫描器发现并从 boot manifest 装载到每个页面。注入一个 `<style>` 标签(`@media (max-width: 720px)` 覆盖),卸载时移除标签——完全可逆。
|
|
26
|
+
|
|
27
|
+
所有选择器都瞄准产品的稳定 `data-*` 属性(`data-composer-seat`、`data-conversation-scroll`、`data-phase`、`data-slot`),绝不依赖 CSS Modules 哈希类名。sticky→static 切换用 `:not(:has([data-conversation-composer-overlay]))` 排除了自带 composer overlay 的视图(如 trajectory),保持官方 absolute 定位。不支持 `:has()` 的引擎上规则安全退回官方 sticky 行为。
|
|
28
|
+
|
|
29
|
+
## 环境要求
|
|
30
|
+
|
|
31
|
+
- DeepSeek Harness Web profile(`dsh web`),任意较新的 0.1.x 版本
|
|
32
|
+
- 选择器已在 0.1.2-rc.1 上验证;它们瞄准产品 slot 契约,同一版本线内稳定,产品大改版后可能需要小幅更新
|
|
33
|
+
|
|
34
|
+
## 安装
|
|
35
|
+
|
|
36
|
+
### npm
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
dsh plugin --profile web add dsh-mobile-flow
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### GitHub
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
dsh plugin --profile web add github:imroc/dsh-mobile-flow
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
重启 `dsh web`,然后刷新浏览器页面。
|
|
49
|
+
|
|
50
|
+
## 验证
|
|
51
|
+
|
|
52
|
+
手机上(或桌面 DevTools 缩到 ≤720px 窄窗)打开一个会话:往上滑几屏——输入框和确认卡片应随消息滚出屏幕。触发一个会提问的工具(或直接看长会话里的输入框):卡片位于消息流末尾而非屏幕底部。拉宽窗口即恢复官方行为。
|
|
53
|
+
|
|
54
|
+
## 回退
|
|
55
|
+
|
|
56
|
+
- Bundle 安装:`dsh plugin --profile web remove dsh-mobile-flow`
|
|
57
|
+
- 手动:移除依赖与 `dsh.profile.bundles` 条目,重启 `dsh web`
|
|
58
|
+
|
|
59
|
+
不修改产品源码;升级不会覆盖。
|
|
60
|
+
|
|
61
|
+
## 许可证
|
|
62
|
+
|
|
63
|
+
MIT
|
package/cordis.patch.yml
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-mobile-flow",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
|
|
7
|
+
/* Mobile in-flow composer: on narrow viewports the composer seat (input
|
|
8
|
+
bar + AI confirmation takeovers) joins the document flow, so swiping
|
|
9
|
+
up scrolls it out of view and the transcript gets the full screen.
|
|
10
|
+
|
|
11
|
+
The 720px breakpoint matches the official ui-user-questions
|
|
12
|
+
QuestionComposer narrow-screen breakpoint. On engines without :has()
|
|
13
|
+
the rules fail closed and the stock sticky behavior stays.
|
|
14
|
+
|
|
15
|
+
Selectors target the product's stable data-* attributes
|
|
16
|
+
(data-composer-seat / data-conversation-scroll / data-phase /
|
|
17
|
+
data-slot), never CSS-Modules-hashed class names; all hooks verified
|
|
18
|
+
against the 0.1.2-rc.1 shipped bundles. */
|
|
19
|
+
var CSS = [
|
|
20
|
+
"/* ── dsh-mobile-flow: in-flow composer (≤720px) ── */",
|
|
21
|
+
"@media (max-width: 720px) {",
|
|
22
|
+
" /* 1) Composer seat sticky -> static: the seat hosts the input bar",
|
|
23
|
+
" fallback AND confirmation takeovers (ask_user_question /",
|
|
24
|
+
" approval / plan review); one rule frees them all together.",
|
|
25
|
+
" Overlay mode is excluded: views like trajectory keep the",
|
|
26
|
+
" official absolute seat positioning. */",
|
|
27
|
+
" [data-conversation-scroll]:not(:has([data-conversation-composer-overlay])) > [data-composer-seat] {",
|
|
28
|
+
" position: static !important;",
|
|
29
|
+
" z-index: auto !important;",
|
|
30
|
+
" }",
|
|
31
|
+
" /* 2) Active-phase transcript stretch (flex-grow): with a short",
|
|
32
|
+
" transcript the seat still lands flush with the viewport floor",
|
|
33
|
+
" (visually identical to the stock docked bar); once the content",
|
|
34
|
+
" exceeds one screen there is no free space left to distribute,",
|
|
35
|
+
" the rule stops contributing, and the seat stays in the flow.",
|
|
36
|
+
" hero/settling phases are unaffected. */",
|
|
37
|
+
" [data-phase='active'] [data-conversation-scroll] > [data-slot='conversation.session'] {",
|
|
38
|
+
" flex: 1 0 auto;",
|
|
39
|
+
" }",
|
|
40
|
+
" /* 3) Floating controls stop reserving height for the sticky seat:",
|
|
41
|
+
" zeroing the variable drops the back-to-bottom button and the",
|
|
42
|
+
" turn navigator back to the viewport floor (overrides the seat",
|
|
43
|
+
" ResizeObserver's inline publication). Overlay mode excluded so",
|
|
44
|
+
" trajectory's bottom-clearance is untouched. */",
|
|
45
|
+
" [data-conversation-scroll]:not(:has([data-conversation-composer-overlay])) {",
|
|
46
|
+
" --dsh-composer-height: 0px !important;",
|
|
47
|
+
" }",
|
|
48
|
+
"}",
|
|
49
|
+
].join("\n");
|
|
50
|
+
|
|
51
|
+
function apply(ctx) {
|
|
52
|
+
var tag = document.createElement("style");
|
|
53
|
+
tag.dataset.plugin = "dsh-mobile-flow";
|
|
54
|
+
tag.textContent = CSS;
|
|
55
|
+
document.head.append(tag);
|
|
56
|
+
|
|
57
|
+
ctx.effect(function () {
|
|
58
|
+
return function () {
|
|
59
|
+
tag.remove();
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
exports.apply = apply;
|
|
65
|
+
return module.exports;
|
|
66
|
+
}
|
|
67
|
+
});
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-mobile-flow host half. Pure UI plugin: the empty apply exists so the
|
|
3
|
+
* plugin appears in the web profile's cordis.yml / Loader; the browser half
|
|
4
|
+
* ships via exports["./client"], discovered through the package.json
|
|
5
|
+
* dsh.client declaration.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Host plugin body — no host-side behavior for this surface plugin. */
|
|
9
|
+
function apply() {}
|
|
10
|
+
export { apply }
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-mobile-flow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Mobile in-flow composer for the DeepSeek Harness Web UI: on narrow (≤720px) screens the input bar and AI confirmation cards scroll with the page instead of pinning to the viewport floor. Pure client-side CSS overlay.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "lib/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./lib/index.js",
|
|
10
|
+
"./client": "./lib/client.js",
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"lib",
|
|
15
|
+
"cordis.patch.yml"
|
|
16
|
+
],
|
|
17
|
+
"dsh": {
|
|
18
|
+
"bundle": {
|
|
19
|
+
"patch": "./cordis.patch.yml"
|
|
20
|
+
},
|
|
21
|
+
"client": {
|
|
22
|
+
"platform": "web"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"author": "roc <i@roc.im>",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/imroc/dsh-mobile-flow.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/imroc/dsh-mobile-flow#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/imroc/dsh-mobile-flow/issues"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"deepseek-harness",
|
|
36
|
+
"dsh",
|
|
37
|
+
"dsh-plugin",
|
|
38
|
+
"mobile",
|
|
39
|
+
"web-ui",
|
|
40
|
+
"css"
|
|
41
|
+
]
|
|
42
|
+
}
|