8.1 KiB
opencode_bridge 交接文档
状态速览
分支:main(已切回,在 main 上操作)
远端:http://101.43.40.124:3000/tao.chen/notebook-ai-extension.git
当前 HEAD (main):d650736 chore: bump version to 0.1.2
Tag:v0.1.2 → d650736(已推到远端,CI 会自动 build + 发 Gitea release + Bark 通知)
d650736 chore: bump version to 0.1.2 ← main HEAD, v0.1.2
f9d52f7 docs: add HANDOVER.md for next session context
310d507 fix: SSE filter no longer drops content events for a different session
⚠️ 重要分歧:main 这次的 v0.1.2 发布只包含了 version bump,没有功能改动。完整功能(per-cell → 全局 floating panel 重构)在分支 feature/floating-ai-button 上,未合并。git status 是干净的,如果你想继续 feature,先 git checkout feature/floating-ai-button。
feature/floating-ai-button HEAD:
12ec84a docs: refresh HANDOVER for floating panel work (d412130)
d412130 fix: hide+show cycles no longer accumulate prompt nodes in floating panel
c0eba7e feat: replace per-cell AI button with global floating panel
(已 push 到远端 + tracking 已设)
本次会话做了什么(按时间序)
- HANDOVER.md 初版(上一任留下的)— 已读
- 创建
feature/floating-ai-button分支 - 重构:把 per-cell 工具栏 AI 按钮(
OpenCodeCellActions)整个换成全局右下角悬浮按钮 + 弹出 panel- 新增
src/components/opencode_floating_panel.ts(Widget,挂document.body) - 删除
src/components/opencode_cell_actions.ts(逻辑搬上去) - 改
src/components/opencode_inline_prompt.ts— 加getActiveCell?: () => CodeCell | null回调,3 处 cell 引用全用回调 - 改
src/index.ts— 删toolbarRegistry.addFactory,接入 floating panel - 改
style/base.css— 删.opencode-cell-actions,新增.opencode-floating-*(fixed 定位、z-index 1000) - 重命名 + 重写
src/__tests__/opencode_floating_panel.spec.ts
- 新增
- Bug fix (
d412130):hide+show 循环累积 prompt 节点 — 用户手测报告,在_hidePrompt加 defensive DOM cleanup - Commit + push 到
feature/floating-ai-button(只到这,没合并) - 回 main:用户决定在 main 上单独发 v0.1.2(只 bump 版本号,不含功能)
- v0.1.2 tag + push
验证状态
| 检查 | 结果 |
|---|---|
| Jest | ✅ 68/68(3 suites)— 在 feature 分支验证过,main 上 0.1.2 没跑过 |
| pytest | ✅ 73/73(同上,feature 分支) |
tsc --noEmit |
✅ exit 0(feature 分支) |
| ESLint | ⚠️ 2 pre-existing 命名错(FlatProvider/BlockEntry 接口名,不符合 /^I[A-Z]/u),我没引入 |
jlpm build:prod |
⚠️ 未跑(见下) |
⚠️ 下个 agent 必须知道的几件事
1. Codex 在本会话里基本不可用 ⚠️⚠️⚠️
CLAUDE.md 强制 model: kimi/kimi-k2.7-code(或后来的 kimi/kimi-k2.6),但火山方舟 Coding Plan proxy 反复拒绝:
kimi-k2.7-code— HTTP 400 "model not valid"(模型名错)kimi/kimi-k2.7-code(CLAUDE.md 当前版本) — 同样被拒kimi-k2.6— HTTP 400 "reasoning is not supported"kimi/kimi-k2.7-codenoop 偶尔通一次,然后实际任务又失败
实际代码工作几乎全是 CC 手动做的。Codex 临死前对 spec 文件做了一次有用的部分重写(改完了 65% 然后挂了)。
建议下次:
- 先 noop 测一次 Codex,通了再用;不通直接走 CC fallback(CLAUDE.md 规则
codex-fail-3x → switch-to-cc) - 如果必须用 Codex,可能需要你这边再调一次 proxy 配置
2. d412130 bug 的防御性修复 + 测试局限
症状:点悬浮按钮 → 显示 panel。再点 → 隐藏。再点 → 看到 2 个 prompt 同时显示(节点累积)。
根因:OpenCodeFloatingPanel 用 Widget.attach(prompt, this._panelEl) 把 Lumino Widget 挂到裸 HTMLDivElement 上(host 不是 Widget),所以 prompt 的 Lumino _parent 是 null。真实 Lumino Widget.dispose() 在 parent=null 时走 Widget.detach(this) 分支按理能清 DOM,但实际有遗漏场景。
修法(src/components/opencode_floating_panel.ts 的 _hidePrompt):
if (this._prompt) {
const node = this._prompt.node;
this._prompt.dispose();
if (node.parentNode === this._panelEl) { // defensive
this._panelEl.removeChild(node);
}
this._prompt = null;
}
回归测试局限:src/__tests__/opencode_floating_panel.spec.ts 的测试 mock Widget.dispose() 直接用 node.parentNode.removeChild 清 — 比真实 Lumino 更激进,所以这个回归测试在 mock 下永远过。真实 bug 只能在真实 JupyterLab 里复现和验证。如果你看到类似累积 bug,必须真跑 JupyterLab,别只信 jest pass。
3. 几个 _onShellChanged / as any 的取舍
_onShellChanged写成 arrow function class field(= (): void => { ... })而不是 method,这样this锁定到实例上(Lumino signal 调用 slot 时this不可靠)this._app.shell as any出现过几次 — 因为JupyterFrontEnd.shell在不同 JupyterLab 版本里类型签名是JupyterShell | null,严格模式要求 cast。可以后续更精确处理,但当前能用
4. jlpm build:prod 没跑成功
.venv/bin/jlpm 是 Python 入口脚本,直接 jlpm build:prod 找不到。我试过 python -m jupyter_builder.jlpm build:prod 但也失败(参数解析对不上)。完整 labextension 打包未验证 — 只跑了 jest + tsc --noEmit 间接确认编译能过。如果发版前要打包验证,你可能要在终端手动跑。
5. v0.1.2 是个"假版本"
只 bump 了 package.json 的 version 字段(pyproject.toml 是 hatch dynamic,从 git tag 自动读),没有功能变更。发这个 tag 大概是为了占位 / 触发 CI。下次真发版时需要把 feature/floating-ai-button 合并到 main,然后重新打 tag。
仍然没做的事
- 把
feature/floating-ai-button合到 main(用户说"暂时不管",所以还没合) - 真实 JupyterLab + OpenCode Serve 端到端测试 — 没在活的 JupyterLab 里点过按钮。bug
d412130是用户手测报的 - Playwright UI tests — 项目交接文档里说写过 spec 但没跑,本次也没动
- pre-existing lint 错清理:
FlatProvider→IFlatProvider,BlockEntry→IBlockEntry(2 处改名,小 PR) jlpm build:prod— 没跑通(见上)- CI 验证:
v0.1.2tag push 触发 CI,看一下.github/workflows/build.yml跑通没
关键文件速查(给下任的 quick map)
src/components/opencode_floating_panel.ts ← 新文件,核心逻辑都在这(310+ 行)
src/components/opencode_inline_prompt.ts ← 解耦 Cell,加了 getActiveCell 选项
src/__tests__/opencode_floating_panel.spec.ts ← 重写后的测试(1556 行,68 tests)
src/index.ts ← 极简,只剩 activate() + 挂 floating panel
style/base.css ← 找 .opencode-floating-* 块
参考架构/HTTP 细节(未变)参考本仓库 HANDOVER.md 之前章节的 架构 / 主要路由 / 关键设计决策。
测试命令
# 后端
.venv/bin/pytest opencode_bridge/tests/ -q # 73 passed
# 前端
./node_modules/.bin/jest --no-coverage # 68 passed
./node_modules/.bin/tsc --noEmit # exit 0
./node_modules/.bin/eslint --ext .ts,.tsx src/ # 仅 pre-existing 错
# 在哪个分支跑? feature/floating-ai-button 上跑过了,main 上 v0.1.2 没跑
上下文管理提示
上下文快满了。新 agent 第一件事:
- 读这份 HANDOVER.md 全文(包括本节之前的所有内容)
git log --oneline -5确认 commit hash 没变- 跑上面 4 个验证命令
- 如果要继续 feature 工作 →
git checkout feature/floating-ai-button - 如果只是在 main 上发版 → 留在这里,准备好就
git merge feature/floating-ai-button(或 PR 流程)
不要:
- 不要从 main 重新开发 — 浪费时间
- 不要相信 jest 单测覆盖
d412130那类 bug — 必须在真 JupyterLab 里点 - 不要相信 Codex 能用 — 先 noop 测一下