OpenProgram · UI design specification

内置浏览器、资料导入与新建 Pane

新建 Pane 只负责选择内容类型;进入 Browser 后才显示网页导航、书签、History 和资料导入。浏览器工具栏只处理当前网页和浏览资料,整个窗口的菜单只处理 OpenProgram 与 Pane。两类设置共用同一 Settings 页面,但使用不同入口。

当前基线已实现桌面 App独立浏览器 profileBrowser chrome 已对齐
本页目录
范围Pane 层级 · Browser chrome · Profile import
平台桌面 App · 独立 profile · 源数据只读
实现状态资料导入 · Browser chrome · Browser settings 已实现
01

产品决策

当前问题来自内容入口、浏览器主页和资料管理共用一个页面。设计先分离职责,再定义每个页面出现的控件。

New pane 只做选择

空白 Pane 只显示 Files、New chat、Browser、Terminal。地址栏、快捷网站、Bookmarks 和 History 不出现在这里。

四个入口使用同级彩色识别

Files、New chat、Browser、Terminal 都使用相同尺寸的圆角图标容器和 Lucide 线性图标;Files 使用蓝色、New chat 使用绿色、Browser 保留橙紫色、Terminal 使用紫色。颜色只帮助识别内容类型,不改变卡片层级、交互状态或可访问名称,也不引入品牌 Logo、外部素材和额外动画。

Browser home 复用完整 Browser chrome

选择 Browser 后原位进入浏览器主页;主页与实际网页使用同一套地址栏和书签栏结构。主页中无当前网页语义的 Back、Forward、Reload、Home、Bookmark 和外部打开保持可见但禁用,地址输入、Bookmarks、Import 和 Browser 可用。

书签分为保存与管理

地址栏右侧的星标只保存或移除当前页;相邻的 Bookmarks 按钮打开完整书签页。Browser home 只显示用户维护的快捷网站,不展开全部书签。

Bookmarks manager 采用 Chrome 式两栏结构

完整书签页顶部固定页面标题、搜索框和页级菜单;左栏只显示可折叠的文件夹树并高亮当前目录,右栏只显示当前目录的直接子项。书签行使用 favicon、标题和单一 菜单,文件夹行进入对应目录;不再把整棵树、URL 和编辑/删除按钮同时铺在一个列表里。左右列表行统一为 36px,搜索框沿用全局 30px 控件高度,行内图标按钮为 28px,页头为 52px;右侧列表的首屏内边距为 16px。Pane 变窄时目录树移到内容列表上方,不能直接消失。

书签栏默认显示

Browser home 和实际网页默认在地址栏下方显示同一行书签。用户可以从 Browser 或 Settings 关闭;窄分屏临时隐藏该行,仍可通过 Browser 中的 Bookmarks 访问全部内容。

书签栏显示来源目录的内容

Chromium 的 Bookmarks bar 是书签栏容器,不作为普通文件夹按钮显示。该容器的直接子项按原顺序进入栏内;Other bookmarksMobile bookmarks 作为右侧文件夹入口,仅在非空时显示。普通根级书签继续作为栏内项目。

书签菜单保留 Chrome 式层级

单行书签栏不出现水平滚动条;被宽度截断的项目由右侧溢出入口列出。菜单固定为 280px 宽,过长标题使用省略号;文件夹以右箭头进入下一级菜单,不把完整路径拼进一行。每一级菜单高度受当前窗口约束,并支持鼠标、触控板与键盘操作。

设置只有一个数据源

窗口菜单的 Settings 打开 OpenProgram 设置;Browser 的 直接打开其中的 Browser 分区。工具栏不增加常驻齿轮,也不实现第二套浏览器设置存储。

分屏属于 Pane

分屏、退出分屏和 Pane 排列适用于 Files、Chat、Browser、Terminal,不属于当前网页动作。它们放在 Tab/Pane 控件或 Tab 上下文菜单,不出现在浏览器工具栏。

导入保留来源结构

Chromium 的 bookmark bar、other bookmarks 以及嵌套文件夹按原有层级和顺序进入 OpenProgram bookmark tree;导入不得把书签压平成主页下方的独立条目。

菜单分别绑定触发按钮

Browser 和窗口 都使用各自触发按钮的实际屏幕矩形定位,菜单右边缘与按钮右边缘对齐,垂直间距为 4px;二者不能共用位置或内容。

History 使用紧凑行

记录按本地日期分组,每行只显示时间、favicon、标题、域名和操作;完整 URL 不再单独占用第二行。

导入必须显式触发

来源浏览器、profile 和数据类型分别确认。OpenProgram 不读取或修改用户正在使用的源 profile。

02

工具栏与菜单归属

浏览器区域分为当前网页、浏览器资料和整个窗口三层。按钮是否常驻由操作频率、当前页面相关性和窄分屏占用共同决定。

目标 Browser chrome

标准:完整网页导航常驻;书签栏默认显示。星标负责当前页,Bookmarks 按钮负责浏览与管理。分屏和全局 Settings 不在这一行。

按钮顺序与收缩规则

位置常驻动作窄分屏规则
地址栏左侧Back · Forward · Reload/Stop · Home520–719px 将 Home 移入 ;低于 520px 再将 Forward 移入 。Back 与 Reload/Stop 始终保留。
地址栏URL、搜索输入与安全状态;加载期间 Reload 原位变为 Stop。始终占据剩余宽度,最低可用宽度 160px;不换行。
地址栏右侧Bookmark current page · Bookmarks · Open externally · Browser menu520–719px 将 Bookmarks 与 Open externally 移入 ;星标和 始终保留。
地址栏下方用户可选的单行 bookmarks bar,直接显示 Bookmarks bar 的子项;非空的 Other bookmarks / Mobile bookmarks 固定在右侧,末尾是溢出入口。低于 560px 不渲染该行,从 Browser 中打开 Bookmarks;禁止水平滚动条。文件夹与溢出菜单的最大高度不得超过当前窗口可用高度,并允许纵向滚动。

Browser toolbar

只放与当前网页直接相关且频繁使用的动作:导航、地址、保存当前页、打开书签、外部打开和 Browser

Browser

New browser tab、Bookmarks、History、Show bookmarks bar、Import browser data、Clear browsing data、Browser settings。

Window menu

New pane/window、Pane 布局、OpenProgram Settings、Help 与 About。它不再直接放 Bookmarks、History 或网页级设置。

03

三个可见状态

下面是信息结构验收图。切换状态即可检查控件是否出现在正确层级。

New pane
FFiles浏览当前项目文件⌘P
CNew chat创建独立对话⌥⌘S
WBrowser打开内置浏览器主页⌘T
>_Terminal打开项目终端⌃`
04

参考行为与取舍

参考产品用于确认可见行为,平台文档用于确认可实现边界。OpenProgram 不复制完整 Chromium importer。

Content hierarchy

Codex 的 Pane 入口

Files、New chat、Browser、Terminal 作为一级内容类型;浏览器控件只在 Browser 内显示。

采用
Browser profile

独立浏览状态

内置浏览器保持自己的 profile。需要既有资料时,由用户明确发起导入。

修改后采用
Bookmark access

Chrome 的分层入口

星标保存当前页;书签栏可开关;完整管理器独立存在。OpenProgram 保留三层,但针对分屏定义更严格的收缩规则。

修改后采用
Settings ownership

OpenAI 的 App Settings

内置浏览器保持独立状态,Cookies 与历史清理归桌面 App Settings。OpenProgram 增加 Browser 深链,但不复制设置存储。

修改后采用
Importer

Chromium C++ importer

组件不作为 Electron JavaScript API 暴露,且不提供通用 Cookies import 实现。

不复制
05

导入架构与数据流

renderer 只传递 main 进程签发的 opaque source/profile id。文件路径、源浏览器可执行路径和 Cookie 值都不能通过 renderer 自由指定。

浏览器资料导入数据流 用户从桌面界面选择来源,main 进程发现 profile 并只读复制到临时目录。History 和 Bookmarks 由解析器读取,Cookies 由源浏览器临时进程解密,最终分别写入 OpenProgram history store、bookmark tree 和 persist webtabs session。 Import dialogsource · profile · types desktop/main.jsbrowser-import:* · opaque ids browser-profile-import.js0700 dir · 0600 files IPCcopy only bounded parsersHistory SQLite · Bookmarks JSON source browser + CDPtemporary process · cookies browsing-history-store.jsweb/lib/bookmarks.ts persist:webtabsElectron cookies.set SOURCE PROFILE · READ ONLY1. 发现已安装浏览器和 profile 名称2. 解析真实路径并拒绝符号链接逃逸3. 复制需要的文件,不锁定活动数据库4. 正常或失败后删除临时目录
一般资料路径Cookie 敏感路径

History

  • 读取 Chromium History SQLite 副本
  • 只接受 http/https
  • 按 URL + visitedAt 去重
  • 错误时保留现有记录

Bookmarks

  • 解析 Chromium Bookmarks JSON
  • 保留根目录、嵌套文件夹与同级顺序
  • 同 URL 不重复添加并删除空文件夹
  • 只在 Bookmarks 页面展示和管理

Cookies

  • 禁止直接复制 Cookie 数据库
  • 由源浏览器临时进程解密
  • 逐条校验后写入 partition
  • 任何日志都不记录值
06

信任边界与失败行为

导入不是 profile 迁移。它只复制已选择的数据,并且不承诺所有网站登录态都能恢复。

边界约束失败结果
renderer → mainsource/profile 使用 main 返回的 opaque id;数据类型使用 allowlist;renderer 不能传文件路径或可执行路径。拒绝请求
源 profile只读发现;真实路径必须位于已发现 browser root 内;拒绝符号链接逃逸。source_invalid
临时数据目录 0700、文件 0600;成功、失败或超时后都删除;日志只记录来源标签、类型、计数和错误码。cleanup + stable error
目标 profileHistory 和 Bookmarks 合并;Cookies 通过 Electron API 写入,不替换目标数据库。保留导入前数据
并发全 App 同时只允许一个导入任务;当前基线不提供执行中取消。import_busy
不导入 Passwords、支付信息、地址、扩展、下载记录、缓存、localStorage 或 Service Workers。
不实现密码管理器、系统 Credential Store、自动填充或对运行中的源浏览器进行远程调试。
Cookie 导入可以减少重复登录,但设备绑定、过期、二次验证或服务端撤销仍会要求重新登录。
本地浏览器导入仅属于桌面 App;Web-only 模式不得显示为可用能力。
07

验收与实现状态

每项验收都对应一个外部可观察结果。设计状态和实现证据分列,不以文档存在本身证明功能完成。

可观察结果当前状态实现证据
新建 Pane 只显示 Files、New chat、Browser、Terminal;四个入口使用同尺寸、不同语义色的圆角图标容器,DOM 中不存在浏览器专属控件。已实现并通过默认 App 深浅主题验收new-tab-page.tsxcheck-built-in-browser.mjs 的有效级联与语义色 mutation 检查
选择 Browser 后原位显示与网页页签相同的地址栏和书签栏结构、导入入口和快捷网站;无当前网页语义的动作保持可见但禁用。已实现并通过默认 App 验收browser-home-page.tsxcheck-built-in-browser.mjs;实际 App 中 toolbar / bookmarks bar 为 40px / 30px
标准宽度的 Browser toolbar 按顺序显示 Back、Forward、Reload/Stop、Home、地址栏、当前页星标、Bookmarks、外部打开和 Browser ;不显示分屏与 Settings 齿轮。已实现web-tab-pane.tsxcheck-built-in-browser.mjscheck-web-split.mjs
Browser 提供 Bookmarks、History、书签栏开关、Import、Clear browsing data 和 Browser settings;窗口主菜单只保留 App、窗口与 Pane 操作。桌面弹层按菜单的 scrollWidth/scrollHeight 回报固有尺寸,不能按当前裁剪高度递归缩小。已实现并通过默认 App 弹层验收browser-controls.tsxmenu-overlay/context-menu/page.tsxcheck-built-in-browser.mjs;实际 Browser 菜单 7 行展开后高度稳定为约 196px,History 动作可点击并打开对应页
书签栏默认显示;用户关闭后保持关闭;直接显示 Bookmarks bar 的子项,非空的其他根目录位于右侧;末尾溢出入口可访问被截断的项目。文件夹菜单固定为 280px 宽,标题省略,嵌套文件夹逐级展开;Pane 低于 560px 时隐藏书签栏,但 Bookmarks 页面仍可到达。已实现并通过默认 App 验收check-bookmarks.mjscheck-built-in-browser.mjs;默认 profile 中书签栏实际可见,高度 30px
Bookmarks manager 使用顶部搜索、左侧文件夹树和右侧当前目录列表;普通行只保留 favicon/文件夹图标、标题和 。左右列表行均为 36px,页头为 52px,窄 Pane 改为上下布局。已实现并通过默认 App 密度验收builtin-tab-pane.tsxcenter-tabs.module.csscheck-bookmarks.mjs;默认 App 实测页头、文件夹行、内容行、搜索框、图标按钮分别为 52 / 36 / 36 / 30 / 28px
Browser settings 与窗口 Settings 使用同一路由和同一配置源;Browser 直接打开 Browser 分区,toolbar 不显示常驻齿轮。已实现/settings/browserbrowser-settings.tsxbrowser-prefs.ts
导入对话框列出来源浏览器、profile 和支持的数据类型;关闭对话框不产生目标变更。已实现desktop/main.jsbrowser-import:* IPC;check-built-in-browser.mjs
History 按日期分组,至少 1000 条时保持 36–40px 行高,搜索和滚动可用。实现完成,规模验收待补web-history.css 为 38px;History 分页上限 5000,搜索在 main 进程完成;存储 self-check 覆盖 5000 条上限,尚未记录 1000 条可见 UI 性能数据。
Bookmarks 保留来源根目录、最多 64 层文件夹和同级顺序;无效 URL 被过滤,重复导入不产生重复 URL 或空文件夹。已实现web/lib/bookmarks.tscheck-bookmarks.mjs
窗口主菜单在桌面 App 和 Web 中都与触发按钮右对齐,按钮底部到菜单顶部的间距为 4px。桌面主菜单、Browser 菜单、书签菜单和 tab 右键菜单从 renderer 传入的 CSS 像素坐标必须按发送页面的 zoom factor 转换为 Electron DIP;在 80%、100%、125% 缩放下都保持贴近原触发按钮。已实现main-menu.tsxcheck-center-tabs.mjscheck-webtab-zoom-bounds.js
Cookies 只进入 persist:webtabs;IPC、日志、History 和 renderer 不出现 Cookie 值。已实现browser-profile-import.js self-check;desktop/main.js
来源损坏、浏览器缺失、临时进程超时和 Cookie 部分失败返回稳定错误码并保留原数据。已实现browser-profile-import.jsbrowsing-history-store.js self-check
依赖 PTY 的全屏终端程序以及执行中取消浏览器导入。当前限制产品边界,不作为当前验收缺口。
Passwords、自动填充、支付/地址数据和源浏览器接管。明确排除browser-profile-import.js 的导入类型 allowlist。

验证环境

可见验收只使用安装的 /Applications/OpenProgram.app、默认 18100 worker 和 ~/.openprogram。文档更新不改变 Agent 的网页控制协议。

本页是当前设计的规范性说明。实现发生变化时直接更新本页;历史修订由 Git 保存。