Skip to content

Commit 3f58552

Browse files
authored
Merge pull request #35 from spencerkit/develop
Merge develop into main
2 parents ac81840 + 1ceaac9 commit 3f58552

109 files changed

Lines changed: 7202 additions & 559 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/green-schools-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@spencer-kit/coder-studio": patch
3+
---
4+
5+
Improve theme-owned workspace icon styling so file tree, mobile workspace dock, settings navigation, and Git footer icons stay consistent across themes, while also hardening workspace target restore behavior and mobile terminal paste and upload flows.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 移动端终端自定义虚拟按键会重新唤起系统软键盘
2+
3+
## 标题
4+
5+
`fix(web): 移动端终端自定义虚拟按键不应重新唤起系统软键盘`
6+
7+
## 问题描述
8+
9+
`coder-studio` 的移动端 terminal 场景下,用户先让终端进入可输入状态,再手动收起系统软键盘,随后点击终端底部我们自己实现的虚拟按键行,例如 `Ctrl``Shift``Esc``Tab`、方向键或 `Enter`,系统软键盘会再次被唤起。
10+
11+
这排按键的设计目标是补足移动端终端缺失的控制键,不应该在用户已经手动收起系统软键盘后,又把键盘重新拉起。
12+
13+
## 复现步骤
14+
15+
1. 在手机或平板上打开 `coder-studio` 的 terminal。
16+
2. 点击 terminal,让系统软键盘弹出。
17+
3. 手动收起系统软键盘。
18+
4. 点击 terminal 底部自定义虚拟按键行中的任意键,例如 `Ctrl``Shift``Esc` 或方向键。
19+
5. 观察系统软键盘重新弹出。
20+
21+
## 预期行为
22+
23+
- 当系统软键盘已经打开时,点击自定义虚拟按键不应强制把它收掉。
24+
- 当系统软键盘已经被用户手动收起时,点击自定义虚拟按键也不应再次把它唤起。
25+
- 自定义虚拟按键应只向终端发送控制输入,而不改变当前系统软键盘的可见状态。
26+
27+
## 实际行为
28+
29+
用户手动收起系统软键盘后,点击自定义虚拟按键仍会导致系统软键盘再次弹出。
30+
31+
## 已确认事实
32+
33+
- 该问题涉及的是 terminal 内部我们自己实现的移动端虚拟按键行,不是系统软键盘本身。
34+
- 自定义虚拟按键的数据链路是:
35+
- `MobileTerminalInputBar`
36+
- `handleSoftKeyPress`
37+
- `handleInput`
38+
- `wsClient.sendTerminalInput`
39+
- 自定义虚拟按键并不是通过 `xterm.onData(...)` 触发输入;它们不会先走 xterm 的浏览器键盘事件采集路径。
40+
- `xterm` 在浏览器里依赖隐藏的 `textarea``.xterm-helper-textarea`)承接键盘、IME 与移动端输入。
41+
- `xterm` 自身维护这个隐藏 `textarea` 的焦点状态,并通过 `focus()` / `blur()` 管理终端输入上下文。
42+
- 在移动端浏览器里,用户“收起软键盘”不一定等价于输入元素真正 `blur`;隐藏 `textarea` 可能仍保持焦点。
43+
- 当前自定义虚拟按键在 `pointerdown` 上使用了 `preventDefault()`,因此按钮本身不会接管焦点。
44+
- 当按钮不接管焦点,而 `xterm` 的隐藏 `textarea` 仍处于焦点上下文时,浏览器可能在下一次触摸交互时重新恢复系统软键盘。
45+
46+
## 当前判断
47+
48+
问题更像是:
49+
50+
- `xterm` 的隐藏 `textarea` 在用户收起软键盘后仍保持焦点或可恢复的输入上下文
51+
- 自定义虚拟按键由于 `preventDefault()` 没有改变当前焦点归属
52+
- 浏览器在后续触摸时将该焦点中的文本输入上下文重新激活,于是系统软键盘再次弹出
53+
54+
也就是说,根因不在“自定义虚拟按键错误地走进了 xterm 的 `onData`”,而在 `xterm` 隐藏输入层的焦点生命周期与移动端浏览器软键盘策略之间的耦合。
55+
56+
## 已排除方向
57+
58+
- 不是自定义虚拟按键通过 `xterm.onData(...)` 间接触发的输入问题。
59+
- 不是 PTY / WebSocket 数据发送链路导致系统软键盘弹出。
60+
- 直接对 `document.activeElement` 做全局 `blur()` 虽然能验证问题与焦点有关,但方案过粗,可能引入键盘闪烁、误伤其他输入元素等副作用,不适合作为最终修复。
61+
62+
## 后续排查方向
63+
64+
- 在真实移动端浏览器上记录以下事件时序:
65+
- 用户手动收起软键盘前后
66+
- 点击自定义虚拟按键前后
67+
- `document.activeElement`
68+
- `xterm.textarea``focus` / `blur`
69+
- `visualViewport.height` 变化
70+
- 确认“软键盘收起但 `xterm.textarea` 仍保持焦点”是否稳定可复现,以及在不同浏览器上的差异。
71+
- 评估是否需要在移动端引入更精确的终端输入状态机,例如区分:
72+
- 系统键盘打开
73+
- 系统键盘已被用户收起
74+
- 仅使用自定义虚拟按键输入
75+
- 如果需要修复,优先考虑:
76+
- 仅围绕 `xterm.textarea` 做精确的 `focus` / `blur` 管理
77+
- 避免对全局 `activeElement` 做无条件处理
78+
- 保证“键盘开着时不强制收掉,键盘关着时不重新拉起”

docs/promotion/releases/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ Add a release narrative when a version is published to GitHub and npm, especiall
1818

1919
## Current releases
2020

21+
- [v0.3.6](v0.3.6.md)
2122
- [v0.3.5](v0.3.5.md)

docs/promotion/releases/v0.3.6.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Coder Studio v0.3.6
2+
3+
## Why this patch matters
4+
5+
`v0.3.6` looks like a small patch from the package changelog, but the shipped product changes are much broader. This release makes Coder Studio more dependable on phones and tablets, reduces session conflicts when the same workspace is opened in multiple tabs, and gives the supervisor workflow better scheduling controls.
6+
7+
In practice, this release means:
8+
9+
- mobile terminal lines can be copied directly with a long press, without entering a separate copy mode
10+
- only one active browser session keeps control of a workspace at a time, with cleaner recovery after reconnects or tab handoff
11+
- supervisor scheduling is easier to use with a built-in date and time picker plus stronger execution policy persistence
12+
- theme and UI polish improvements make the workspace feel more intentional across desktop and mobile
13+
14+
## Included in v0.3.6
15+
16+
- add mobile terminal long-press line copy with stronger touch hit testing and E2E coverage
17+
- add single-active session gating and activation recovery to prevent stale tabs from holding the live workspace session
18+
- add a date and time picker for supervisor scheduled execution, plus persistence and backend handling for execution policy settings
19+
- add the new theme skin system and shared icon styling improvements across the workspace UI
20+
- fix several mobile and settings UI regressions, including switch alignment, popover visibility, session reentry, and worktree refresh behavior
21+
- refresh the README, demo assets, and release narrative structure so the published project materials match the current product
22+
23+
## Who benefits most
24+
25+
- users who primarily access Coder Studio from mobile browsers
26+
- developers who keep the same workspace open across multiple devices or tabs
27+
- anyone relying on supervisor automation for longer-running coding workflows
28+
- evaluators deciding whether Coder Studio is mature enough for day-to-day AI-assisted development
29+
30+
## Install or upgrade
31+
32+
```bash
33+
npm install -g @spencer-kit/coder-studio
34+
coder-studio open
35+
```
36+
37+
## Full changelog
38+
39+
- [Compare `v0.3.5...v0.3.6`](https://github.com/spencerkit/coder-studio/compare/v0.3.5...v0.3.6)
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
# AI Agent 都会写代码了,为什么我还得像监工一样盯着它?
2+
3+
> 发布渠道:掘金
4+
>
5+
> 文章目标:围绕 `Supervisor` 建立“AI 驱动 AI、目标驱动自动推进”的认知,并带动 `GitHub Star / 安装试用`
6+
7+
## 摘要
8+
9+
AI 编程越来越强,但很多长任务里,开发者反而更像个监工:AI 改一会儿 `CR` 就回来问要不要继续,补一半单测就停住,睡前挂的任务醒来只做完 `task 1`。我后来发现,问题不只是模型能力,而是缺一个能围绕目标持续推进的 `Supervisor`。它不是简单地“盯任务”,而是你先设定目标,再让 AI 去驱动 AI,让执行中的 Agent 持续朝目标推进,把中间那段最像“监工”的过程自动化掉。
10+
11+
## 正文
12+
13+
最近我越来越常遇到一种很烦的场景。
14+
15+
我让 AI 去改一轮 `CR`、补一组单测,或者顺手把下一个功能做掉。
16+
17+
本来以为终于能放手十几分钟,结果它干一会儿就回来问我一句:`要不要继续?`
18+
19+
比如我让 AI 去改一轮 `CR`。需求其实很明确:把 review 里提到的几个问题改掉,顺手清理一下重复逻辑,补上缺的单测,最后跑一遍测试,确认这轮改动可以收口。
20+
21+
按理说,这已经是很适合交给 AI 的活了。
22+
23+
结果没过一会儿,它来一句:
24+
25+
“已经处理了 4 条 review comment,剩下 2 条涉及状态流转调整和命名统一,要不要继续?”
26+
27+
你看着这句话,第一反应通常不是“挺智能”,而是烦。
28+
29+
因为这说明它不是在替你把事情做完,它只是做了一段,然后停下来,把球踢回给你。你只能回一句:继续。
30+
31+
过几分钟,它又来了:
32+
33+
“我已经把重复逻辑抽出来了,下一步建议把相关单测补上,要不要继续?”
34+
35+
你再回:继续。
36+
37+
再过一会儿,它又停住:
38+
39+
“单测已经补了 3 个 case,还有 2 个边界场景需要处理,是否继续?”
40+
41+
你还是得回:继续。
42+
43+
最烦的不是它不会做。
44+
45+
最烦的是,它明明已经知道目标,也大致知道下一步该干什么,却还是总在半路回来问你一句。
46+
47+
这种感觉在补单测的时候尤其明显。你让它给一个 service 或 hook 把测试补齐。它会分析逻辑、建测试文件、写几个 happy path、顺手跑一下测试。看起来一切都很顺,结果很快又停下来:
48+
49+
“基础场景已补完,异常分支和空数据分支还没覆盖,下一步建议继续补齐,要不要继续?”
50+
51+
看到这种话,人是真的会有一种被绑在电脑前的感觉。
52+
53+
因为这些根本不是必须由你拍板的大决策。很多时候,无非就是继续做,把这一轮事情做完整,把该补的补完,把该跑的跑完,把该收的尾收掉。
54+
55+
但它偏偏不一口气往下推。
56+
57+
更让人破防的是那种“睡前交任务,醒来只做了 task 1”的场景。
58+
59+
比如你让它做一个下一个功能:
60+
61+
“把这个设置页的筛选功能做掉,包含前端交互、接口调用和基础测试,最后整理到可提交状态。”
62+
63+
它先给你写了一个像模像样的 plan:
64+
65+
- task 1:搭筛选面板 UI
66+
- task 2:接接口和状态管理
67+
- task 3:补测试并收尾验证
68+
69+
你看着这份 plan,会很自然地觉得:行,这次应该能自己一路做下去了。甚至你会想,今晚睡前把任务挂着,说不定明天醒来这个功能就差不多了。
70+
71+
结果第二天一看,现实经常是:
72+
73+
它只做了 task 1。
74+
75+
UI 确实搭出来了,按钮也有了,交互壳子也在。然后它停住了。最后留给你一句特别客气的话:
76+
77+
“task 1 已完成。下一步建议开始接接口和状态管理,请确认是否继续。”
78+
79+
那一瞬间真的很容易烦。
80+
81+
因为你期待的是:既然目标已经说清楚了,那就继续往下做。UI 搭完就接接口,接口接完就补测试,测试跑完再检查一遍改动,有问题继续修,没问题就收尾。
82+
83+
结果它不是没干活。
84+
85+
它干了,但只干了一小段。然后停在那里,等你下一句。
86+
87+
于是最尴尬的事情就发生了:AI 已经开始帮你改 `CR`、补单测、做功能了,但你反而更离不开电脑了。
88+
89+
以前自己写代码,累归累,至少节奏在自己手里。你知道下一步该改哪、查哪、跑哪,想一口气做完就做完,想停下来休息也能停。
90+
91+
现在换成 Agent 之后,很多时候你进入的是另一种累法。
92+
93+
你不是全程亲手干活,但你得全程待命。
94+
95+
去接杯水,不踏实。去吃个饭,不踏实。回个消息,不踏实。晚上想把任务挂着睡觉,也不踏实。
96+
97+
因为你知道它大概率不会一路做到底。它很可能改完一半 `CR` 回来问你,补完一半单测回来问你,做完功能的 task 1 又回来等你确认 task 2。
98+
99+
你表面上像是把任务交给了 AI,实际上你根本走不开。
100+
101+
你不是在“让 AI 干活”,你是在电脑前陪 AI 干活。
102+
103+
这才是现在很多 AI 编程体验里最消耗人的地方。
104+
105+
不是 AI 完全不会做,而是它太容易在半路把你叫回来。你以为自己获得了一个 Agent,最后却越来越像一个监工:盯进度、补指令、做确认、催下一步。
106+
107+
真正烦人的,不是写代码本身。
108+
109+
而是你明明已经把目标交代清楚了,却还是得守在电脑前,等 AI 一次次来问你:
110+
111+
“下一步呢?”
112+
113+
![Coder Studio 工作区总览](../help/assets/screenshot-workspace-overview.png)
114+
115+
*图:真实承载场景不是一个聊天框,而是 Agent、文件、Git、终端和 Supervisor 同处一个工作台。*
116+
117+
## 我后来意识到,我缺的不是一个更会聊天的 AI
118+
119+
我缺的,是把“继续往下做”这件事也自动化。
120+
121+
这也是我做 `Supervisor` 的原因。
122+
123+
很多人一听这个名字,第一反应会觉得它像是一个“盯着 Agent 有没有卡住”的东西。但我后来越来越确定,`Supervisor` 最核心的价值根本不是“盯任务”。
124+
125+
它真正有意思的地方在于:
126+
127+
你先设定一个目标,然后让 AI 去驱动 AI,让执行中的 Agent 持续朝目标推进。
128+
129+
不是我每隔几分钟回来补一句“继续”。不是我一直守在电脑前等它问“要不要往下做”。而是我先把目标讲清楚,再让另一个 AI 站在更高一层,围绕这个目标持续评估、持续判断、持续续推。
130+
131+
也就是说,`Supervisor` 干的不是简单的监控。
132+
133+
它做的是目标驱动的自动推进。
134+
135+
比如我给它一个目标:改完这轮 `CR`,把 review 里的问题收干净;给某个模块补齐关键单测,跑过验证;把一个功能从实现、测试一路推进到可提交状态。
136+
137+
那接下来我要的就不是“Agent 做一段,回来问我一次”。
138+
139+
我要的是它围绕这个目标一直往下走。
140+
141+
如果当前进展离目标还远,那就继续推进。
142+
如果还有明显遗漏,那就继续补齐。
143+
如果任务停在一个半成品状态,那就继续往前推。
144+
直到目标完成,或者真的到了必须由我介入做决策的时候,再把我叫回来。
145+
146+
这才是我想要的自动化。
147+
148+
不是“AI 帮我做了一点点”,而是“我给出目标,然后 AI 去驱动 AI,把中间那段反复催促、反复确认、反复续推的过程接过去”。
149+
150+
人不应该寸步不离地盯着 Agent。
151+
152+
人更适合做三件事:设定目标,在关键分叉点做决策,最后验收结果。
153+
154+
至于中间那段“不断把任务往前推”的过程,本来就更适合交给 AI 去完成。
155+
156+
> TODO(supervisor-image-1): 在这里补一张 Supervisor 目标配置 / 状态卡片截图。
157+
>
158+
> 预期图片内容:
159+
> - 桌面端工作区中的 Supervisor 卡片
160+
> - 清晰展示 objective 文案
161+
> - 能看到 evaluator / state / enable 或 trigger 等关键信息中的至少两项
162+
> - 最好能让读者一眼理解“这是围绕目标自动推进的能力,不是普通聊天面板”
163+
164+
## Supervisor 解决的,不是能力问题,而是工作流问题
165+
166+
现在的 Agent,单点能力其实已经不差了。改个函数、修个 bug、补几段测试,很多都能做。
167+
168+
但一旦任务变成长链路,真正让人崩的,往往不是“它不会”,而是“它老停”。
169+
170+
它不是没有能力往下走,它只是缺一个持续围绕目标去驱动执行的机制。
171+
172+
所以 `Supervisor` 想补上的,不是模型会不会写代码,而是任务能不能持续自动推进。
173+
174+
“会写”解决的是能力。
175+
“能一路推到目标”解决的是工作流。
176+
177+
而对已经开始重度使用 `Claude Code``Codex` 这类工具的人来说,后者往往更影响真实体验。
178+
179+
因为开发者最贵的,不只是编码能力,还有注意力。
180+
181+
如果每个长任务都要你守在电脑前,等着 AI 一次次问你“要不要继续”,那模型越能做长任务,人反而越容易被拖进一种低效的待命状态里。
182+
183+
这听起来很反直觉,但现在其实已经很常见了。
184+
185+
> TODO(supervisor-image-2): 在这里补一张能够体现“AI 驱动 AI 持续推进”的过程型截图。
186+
>
187+
> 预期图片内容:
188+
> - Supervisor 最近 cycle / 历史记录 / 状态变化区域
189+
> - 最好能看到至少一次“评估 -> 续推/注入 -> 继续执行”的痕迹
190+
> - 如果单张图信息不够,可以考虑后续换成 2 张图或短 gif
191+
> - 目标是让读者理解:不是人每次手动回复“继续”,而是 Supervisor 在围绕目标推进
192+
193+
## 为什么我会把它放进 Coder Studio 里
194+
195+
`Supervisor` 如果只是一个单独能力,当然也有价值。
196+
197+
但我更想把它放进 `Coder Studio` 这个浏览器里的 AI 编程工作台里,因为真实开发里,目标推进从来不是一句对话能承载完的。
198+
199+
你看的不只是 Agent 说了什么。
200+
201+
你还要看它改了哪些文件,Git 变更长什么样,测试有没有跑过,当前任务到底离目标还有多远。
202+
203+
所以我想把 `Agent + 文件 + Git + 终端 + Supervisor` 放回同一个界面里。
204+
205+
这样当你回来看的时候,你看到的不是一条“要不要继续”的消息,而是整个任务现场:目标是什么,进度到哪了,改动落在哪,验证有没有做,结果离交付还有多远,都在一个工作台里。
206+
207+
`Supervisor` 在这里的角色,也不是“提醒你回来继续点按钮”。
208+
209+
它是让这条链路尽可能自动往前跑,让你不用全程守在电脑前,寸步不离地看着 Agent。
210+
211+
![Coder Studio 桌面端工作区](../help/assets/screenshot-pc.png)
212+
213+
*图:桌面端工作区把 Agent、文件、Git 和终端收拢到同一个界面里,Supervisor 才真正有了承载场景。*
214+
215+
如果你离开工位,也不一定非要等回到电脑前才能知道任务推进到了哪。
216+
217+
同一个工作区可以在手机或平板上继续打开,至少先把状态、输出和变更看清楚,而不是靠一条通知猜任务到底有没有跑完。
218+
219+
![Coder Studio 移动端工作区](../help/assets/screenshot-mobile.png)
220+
221+
*图:移动端不是主战场,但至少不用再寸步不离守着电脑看 Agent 下一句。*
222+
223+
## 最后
224+
225+
如果你现在只是偶尔拿 AI 补几行代码,那你可能还没那么强烈地感受到这个问题。
226+
227+
但只要你开始让 AI 改 `CR`、补单测、做功能、跑验证,而且一跑就是几分钟、十几分钟,甚至希望它能在你离开电脑时自己继续往下做,你迟早会遇到这个痛点:
228+
229+
不是它不会写。
230+
而是它总在半路停下来,把你叫回来。
231+
232+
所以我想做的,不只是让 AI 更能干一点。
233+
234+
我更想做的是:你给出目标之后,让 AI 去驱动 AI,让 Agent 持续朝目标推进,把中间那段最烦、最碎、最像监工的过程自动化掉。
235+
236+
这也是 `Supervisor` 对我来说真正有价值的地方。
237+
238+
如果你也受够了总得守在电脑前、等 AI 一次次问你“下一步要不要继续”,可以看看这个项目:
239+
240+
GitHub:`https://github.com/spencerkit/coder-studio`
241+
242+
```bash
243+
npm install -g @spencer-kit/coder-studio
244+
coder-studio open
245+
```
246+
247+
如果这个方向你也认同,欢迎试试,也欢迎顺手点个 `Star`

0 commit comments

Comments
 (0)