Fix maximum-clear bubble rendering
This commit is contained in:
1 parent
6ed4647143
commit
92e901f844
6 files changed
+77
-60
No files matched your search
@@ -305,7 +305,7 @@ private struct ConversationBubble: View {
|
||||
cornerRadius: OverlayGeometry.bubbleCornerRadius,
|
||||
style: .continuous
|
||||
),
|
||||
interactive: false
|
||||
interactive: true
|
||||
)
|
||||
.contentShape(RoundedRectangle(cornerRadius: OverlayGeometry.bubbleCornerRadius, style: .continuous))
|
||||
}
|
||||
@@ -335,7 +335,7 @@ private struct SessionBubbleRow: View {
|
||||
if !session.statusText.isEmpty {
|
||||
Text(session.statusText)
|
||||
.font(.system(size: 9.5, weight: .semibold))
|
||||
.foregroundStyle(statusColor)
|
||||
.foregroundStyle(BubbleForegroundStyle.text)
|
||||
.apcBubbleTextContrast()
|
||||
.lineLimit(1)
|
||||
.fixedSize(horizontal: true, vertical: false)
|
||||
@@ -343,11 +343,11 @@ private struct SessionBubbleRow: View {
|
||||
.padding(.vertical, 1)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(statusColor.opacity(0.10))
|
||||
.fill(statusColor.opacity(0.24))
|
||||
)
|
||||
.overlay {
|
||||
Capsule()
|
||||
.stroke(statusColor.opacity(0.28), lineWidth: 0.75)
|
||||
.stroke(statusColor.opacity(0.62), lineWidth: 0.75)
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,21 +128,16 @@ private struct APCLiquidGlassModifier<S: Shape>: ViewModifier {
|
||||
|
||||
enum APCBubbleGlassStyle {
|
||||
/// Clear Liquid Glass is the most transparent public system treatment on
|
||||
/// macOS 26. Keep the normal path free of supplemental fills and borders
|
||||
/// so the system can sample the desktop directly.
|
||||
/// macOS 26. Keep the normal path free of supplemental fills, borders, and
|
||||
/// post-compositing opacity so the system can sample the desktop directly.
|
||||
static let backdropOpacity = 0.0
|
||||
static let borderOpacity = 0.0
|
||||
/// Keep a visible trace of the native Clear lens while allowing the
|
||||
/// desktop beneath a large conversation bubble to remain recognizable.
|
||||
/// The glass is rendered on its own background layer, so this opacity
|
||||
/// never attenuates labels, icons, or controls.
|
||||
static let opticalOpacity = 0.24
|
||||
static let legacyBackdropOpacity = 0.10
|
||||
static let legacyBackdropOpacity = 0.18
|
||||
static let legacyBorderOpacity = 0.18
|
||||
static let increasedContrastBackdropOpacity = 0.30
|
||||
static let increasedContrastBorderOpacity = 0.34
|
||||
static let increasedContrastBackdropOpacity = 0.42
|
||||
static let increasedContrastBorderOpacity = 0.52
|
||||
static let reducedTransparencyBackdropOpacity = 0.86
|
||||
static let reducedTransparencyBorderOpacity = 0.42
|
||||
static let reducedTransparencyBorderOpacity = 0.62
|
||||
|
||||
static func resolvedBackdropOpacity(
|
||||
reduceTransparency: Bool,
|
||||
@@ -177,27 +172,23 @@ enum APCBubbleForegroundStyle {
|
||||
/// Transparency belongs to the glass surface, not to labels or icons.
|
||||
static let contentOpacity = 1.0
|
||||
static let secondaryContentOpacity = 0.86
|
||||
static let lightHaloOpacity = 0.28
|
||||
static let darkHaloOpacity = 0.96
|
||||
static let lightHaloOpacity = 0.16
|
||||
static let darkHaloOpacity = 0.82
|
||||
}
|
||||
|
||||
/// The native Clear glass is intentionally kept on a background-only layer.
|
||||
/// `BubbleOverlayRootView` doesn't wrap these surfaces in a
|
||||
/// `GlassEffectContainer`: that container elevates descendant glass views and
|
||||
/// can place the optical layer above SwiftUI foreground content in a
|
||||
/// The native Clear glass is applied directly to the content hierarchy. This
|
||||
/// is the public maximum-clear treatment and keeps SwiftUI foreground content
|
||||
/// in the glass view's guaranteed content layer. `BubbleOverlayRootView` does
|
||||
/// not add a `GlassEffectContainer`: that container elevates descendant glass
|
||||
/// views and can place the optical layer above foreground content in a
|
||||
/// transparent `NSPanel`.
|
||||
private struct APCTransparentBubbleGlassModifier<S: Shape>: ViewModifier {
|
||||
@Environment(\.accessibilityReduceTransparency) private var reduceTransparency
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@Environment(\.colorSchemeContrast) private var colorSchemeContrast
|
||||
|
||||
let shape: S
|
||||
let interactive: Bool
|
||||
|
||||
private var backdropColor: Color {
|
||||
colorScheme == .dark ? .black : .white
|
||||
}
|
||||
|
||||
private var backdropOpacity: Double {
|
||||
APCBubbleGlassStyle.resolvedBackdropOpacity(
|
||||
reduceTransparency: reduceTransparency,
|
||||
@@ -209,23 +200,18 @@ private struct APCTransparentBubbleGlassModifier<S: Shape>: ViewModifier {
|
||||
func body(content: Content) -> some View {
|
||||
if #available(macOS 26.0, *) {
|
||||
if reduceTransparency {
|
||||
accessibleFallback(content, supportsLiquidGlass: true)
|
||||
accessibilityFallback(content, supportsLiquidGlass: true)
|
||||
} else {
|
||||
content
|
||||
.background {
|
||||
Color.clear
|
||||
.glassEffect(
|
||||
interactive ? .clear.interactive() : .clear,
|
||||
in: shape
|
||||
)
|
||||
.opacity(APCBubbleGlassStyle.opticalOpacity)
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
.background {
|
||||
if colorSchemeContrast == .increased {
|
||||
shape.fill(backdropColor.opacity(backdropOpacity))
|
||||
shape.fill(Color.black.opacity(backdropOpacity))
|
||||
}
|
||||
}
|
||||
.glassEffect(
|
||||
interactive ? .clear.interactive() : .clear,
|
||||
in: shape
|
||||
)
|
||||
.overlay {
|
||||
if colorSchemeContrast == .increased {
|
||||
bubbleBorder(supportsLiquidGlass: true)
|
||||
@@ -233,24 +219,37 @@ private struct APCTransparentBubbleGlassModifier<S: Shape>: ViewModifier {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accessibleFallback(content, supportsLiquidGlass: false)
|
||||
legacyFallback(content)
|
||||
}
|
||||
}
|
||||
|
||||
private func accessibleFallback(
|
||||
private func accessibilityFallback(
|
||||
_ content: Content,
|
||||
supportsLiquidGlass: Bool
|
||||
) -> some View {
|
||||
let opacity = if reduceTransparency || colorSchemeContrast == .increased {
|
||||
return content
|
||||
.background(Color.black.opacity(backdropOpacity), in: shape)
|
||||
.overlay {
|
||||
bubbleBorder(supportsLiquidGlass: supportsLiquidGlass)
|
||||
}
|
||||
}
|
||||
|
||||
private func legacyFallback(_ content: Content) -> some View {
|
||||
let supplementalOpacity = if reduceTransparency || colorSchemeContrast == .increased {
|
||||
backdropOpacity
|
||||
} else {
|
||||
APCBubbleGlassStyle.legacyBackdropOpacity
|
||||
}
|
||||
|
||||
return content
|
||||
.background(backdropColor.opacity(opacity), in: shape)
|
||||
.background {
|
||||
ZStack {
|
||||
shape.fill(.ultraThinMaterial)
|
||||
shape.fill(Color.black.opacity(supplementalOpacity))
|
||||
}
|
||||
}
|
||||
.overlay {
|
||||
bubbleBorder(supportsLiquidGlass: supportsLiquidGlass)
|
||||
bubbleBorder(supportsLiquidGlass: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,13 +278,13 @@ private struct APCBubbleTextContrastModifier: ViewModifier {
|
||||
.opacity(APCBubbleForegroundStyle.contentOpacity)
|
||||
.shadow(
|
||||
color: .white.opacity(APCBubbleForegroundStyle.lightHaloOpacity),
|
||||
radius: 0.45,
|
||||
y: 0.1
|
||||
radius: 0.3,
|
||||
y: 0.05
|
||||
)
|
||||
.shadow(
|
||||
color: .black.opacity(APCBubbleForegroundStyle.darkHaloOpacity),
|
||||
radius: 1.35,
|
||||
y: 0.4
|
||||
radius: 0.85,
|
||||
y: 0.25
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ struct BubbleGlassRegressionTests {
|
||||
func maximumClearSurfaceAddsNoSolidBackdrop() {
|
||||
#expect(APCBubbleGlassStyle.backdropOpacity == 0)
|
||||
#expect(APCBubbleGlassStyle.borderOpacity == 0)
|
||||
#expect(APCBubbleGlassStyle.opticalOpacity > 0)
|
||||
#expect(APCBubbleGlassStyle.opticalOpacity <= 0.25)
|
||||
#expect(APCBubbleGlassStyle.legacyBackdropOpacity > 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -17,5 +16,22 @@ struct BubbleGlassRegressionTests {
|
||||
#expect(APCBubbleForegroundStyle.secondaryContentOpacity >= 0.85)
|
||||
#expect(APCBubbleForegroundStyle.lightHaloOpacity > 0)
|
||||
#expect(APCBubbleForegroundStyle.darkHaloOpacity > 0)
|
||||
#expect(APCBubbleForegroundStyle.darkHaloOpacity > APCBubbleForegroundStyle.lightHaloOpacity)
|
||||
}
|
||||
|
||||
@Test
|
||||
func accessibilityFallbacksRemainDarkerThanLegacyMaterial() {
|
||||
#expect(
|
||||
APCBubbleGlassStyle.increasedContrastBackdropOpacity
|
||||
> APCBubbleGlassStyle.legacyBackdropOpacity
|
||||
)
|
||||
#expect(
|
||||
APCBubbleGlassStyle.reducedTransparencyBackdropOpacity
|
||||
> APCBubbleGlassStyle.increasedContrastBackdropOpacity
|
||||
)
|
||||
#expect(
|
||||
APCBubbleGlassStyle.reducedTransparencyBorderOpacity
|
||||
> APCBubbleGlassStyle.legacyBorderOpacity
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ App、PetCore、CLI 和连接器不再只比较 RPC 版本。每个 bundle 携
|
||||
| 功能域 | 当前状态 |
|
||||
|---|---|
|
||||
| 三入口导航、Studio 双页签、本地宠物库 | 已实现 |
|
||||
| 原生 UI | 控制中心、状态栏、桌宠控制、右击菜单和消息气泡使用 macOS 原生 clear Liquid Glass;macOS 14–15 使用系统 `ultraThinMaterial` 回退。 |
|
||||
| 原生 UI | 控制中心、状态栏、桌宠控制、右击菜单和消息气泡使用 macOS 原生 clear Liquid Glass。消息气泡在 macOS 26 使用无 tint、无填充、无边框、无附加 opacity 的最高透明 clear interactive glass,并把前景直接置于玻璃内容层;macOS 14–15 使用系统 `ultraThinMaterial` 回退。 |
|
||||
| 桌宠渲染 | Metal-backed;12/20 FPS;高/超清 eager cache、原画 ring cache;左键拖动与宠物右侧缩放;缩放手柄与气泡开关同列且命中区独立;左键单击无额外响应、仅右击显示原生菜单;不显示拖动标签或脚下玻璃底座。 |
|
||||
| 会话气泡 | 每个 Agent 一个气泡;同 Agent 多会话分行;标题、最多两行的当前公开活动/回复、状态和唯一「打开」操作;两行渲染与 Panel 高度测量一致;默认 15 分钟普通会话收起。 |
|
||||
| 状态内容 | Running 优先显示公开思考摘要/计划或本地化工具活动;已完成工具不再冒充当前活动,公开 revision 停滞但任务时钟推进时清除旧摘要;Ready 显示最新 Agent 回复;Needs input/Blocked 显示当前交互或错误。 |
|
||||
@@ -92,7 +92,7 @@ V1 仍不包含公共素材库、分享/社区、Petdex 导入、Codex 内置宠
|
||||
| 验证 | 结果 |
|
||||
|---|---:|
|
||||
| `script/test_all.sh` 默认 deterministic/simulated/security/bounded-stress 门禁 | PASS |
|
||||
| Swift tests | PASS,95 tests / 10 suites(含旧 `apc.runtime-manifest.v1` 新增字段重建回归) |
|
||||
| Swift tests | PASS,96 tests / 10 suites(含玻璃辅助功能回退与旧 `apc.runtime-manifest.v1` 新增字段重建回归) |
|
||||
| Rust workspace tests、fmt、clippy `-D warnings` | PASS |
|
||||
| App lifecycle contract | PASS,8/8 |
|
||||
| Swift overlay/UI offline contract | PASS,10/10 |
|
||||
@@ -106,6 +106,7 @@ V1 仍不包含公共素材库、分享/社区、Petdex 导入、Codex 内置宠
|
||||
| 桌宠紧凑布局回归 | PASS:Computer Use 优先完成新版启动与旧实例退出;气泡按宠物内容带重新锚定,气泡开关下移并与缩放手柄保持同列。两个控件各自由 36/38 pt 透明原生控制 panel 承载,不再受宠物主体鼠标穿透影响;系统命中检查、收起→展开、缩放增量→恢复、Overlay 10/10 离线契约与当前 Swift 套件均通过。 |
|
||||
| 桌宠点击与菜单语义 | PASS:左键策略单测确认不打开菜单,AppKit 左键事件仅保留拖动生命周期;Computer Use 实机读取到“桌宠”辅助元素及“按住左键拖动,右击打开快捷菜单”说明,系统 AX 只为该元素公开 `AXShowMenu` 菜单动作;悬浮“拖动”标签已移除。 |
|
||||
| Codex 气泡活动回归 | PASS:Rust 单元/transport 覆盖工具分类、完成项、稳定状态记录和 reasoning revision;实机验证新思考摘要、完成会话无残留活动、收起后再次展开。当前机器 Hook Trust 仍为用户待确认,故精确 PreToolUse 实机项不伪报通过。 |
|
||||
| 最大透明气泡回归 | PASS:Computer Use 完成旧 UI Host 退出与新 bundle 启动,运行进程晚于新构建且 build ID 为 `0.1.0.1.20260716031517.53137`;静默窗口像素检查确认标题、当前活动和状态均可见,气泡后方浅色界面文字/分隔线仍可辨认。正常态无 tint、填充、边框或玻璃 opacity;Reduce Transparency/Increase Contrast 使用深色可读性回退。 |
|
||||
| `.petpack` producer schemas | PASS:manifest/source/brief/source-event/validation 五组 Draft 2020-12 schema 正反 fixtures;当前 Studio 元数据逐文件/逐事件 schema 验证。 |
|
||||
| Portable Skill 真实前向测试 | PASS:真实图像工具生成 `Lunari` 月兔,7 状态 × 2 张透明 192×208 PNG、14 帧均有状态内变化,384×416 cover/14 帧 WebP,最终 CLI validation `ok=true`、0 warning。 |
|
||||
| Portable Skill 真实修改测试 | PASS:对月兔仅重绘 `tool` 两帧为星锤动作;其余 6 状态、12 帧与基线 byte-identical,完整包通过 PetCore validation,14 frames、0 warning。 |
|
||||
@@ -117,8 +118,8 @@ V1 仍不包含公共素材库、分享/社区、Petdex 导入、Codex 内置宠
|
||||
|
||||
- `dist/AgentPetCompanion.app`:构建产物;若仓库位于 File Provider 管理目录,Finder 元数据可能随后改变裸 bundle 的严格签名判断。
|
||||
- `dist/AgentPetCompanion-develop.zip`:当前支持的非正式 develop 交付物。App 在非 File Provider 临时目录完成组装、签名和归档;ZIP 排除资源 fork/xattr,并在另一临时目录解压后再次做严格签名校验。
|
||||
- 当前 develop build:`0.1.0.1.20260715184943.78233`。
|
||||
- ZIP SHA-256:`4219f188cd2cbb4fff969145d793fa8fef2f61ae7cc1af79adfd3c0690ad086b`。
|
||||
- 当前 develop build:`0.1.0.1.20260716031517.53137`。
|
||||
- ZIP SHA-256:`0d67cb080debd39e1725916cc1b687ba30e3a645a56c51c65dff4b0a3fb46739`。
|
||||
|
||||
该包不是 Developer ID 分发包,不承诺 Gatekeeper、公证或正式升级渠道。
|
||||
|
||||
|
||||
@@ -195,14 +195,14 @@ Agent 连接
|
||||
| 拖动 | AppKit 处理拖拽 |
|
||||
| 缩放 | 宠物右侧 resize handle,与气泡开关纵向排列在同一控制列 |
|
||||
| 透明背景 | premultiplied alpha texture |
|
||||
| 消息气泡材质 | macOS 26 `Glass.clear.interactive()` + `GlassEffectContainer`;macOS 14–15 原生 `ultraThinMaterial` 回退 |
|
||||
| 消息气泡材质 | macOS 26 将无 tint、无附加 opacity 的 `Glass.clear.interactive()` 直接施加到气泡内容;macOS 14–15 原生 `ultraThinMaterial` 回退 |
|
||||
| 桌宠控制材质 | 缩放手柄、缩放值和气泡开关共享 clear glass;不显示拖动标签、不绘制脚下底座,宠物帧位于无遮挡内容层;视觉控件紧凑但命中区独立保留 |
|
||||
| 右击菜单 | 原生 `NSMenu` + SF Symbols,不自绘菜单背景 |
|
||||
| 动画播放 | Metal texture swap |
|
||||
| 鼠标穿透 | 行为页开关控制 |
|
||||
| 收起 | 菜单栏或悬浮层按钮 |
|
||||
|
||||
宠物本体与消息气泡分别由透明、无边框、non-activating `NSPanel` 承载;气泡开关和缩放手柄进一步各自使用与 36/38 pt 命中区等大的透明控制 panel,避免宠物主体的鼠标穿透状态让首个点击或拖拽落到下层 App。所有 panel 都属于同一个 macOS App 进程;Rust PetCore LaunchAgent 只负责状态、事件与数据,不绘制桌宠。气泡 panel 保持 `isOpaque=false` 和透明背景,SwiftUI 内容不再铺不透明白底:macOS 26 使用 clear Liquid Glass,附近气泡通过同一 `GlassEffectContainer` 采样;旧系统只使用系统超薄材质,保证原生可访问性与 Reduce Transparency 行为。
|
||||
宠物本体与消息气泡分别由透明、无边框、non-activating `NSPanel` 承载;气泡开关和缩放手柄进一步各自使用与 36/38 pt 命中区等大的透明控制 panel,避免宠物主体的鼠标穿透状态让首个点击或拖拽落到下层 App。所有 panel 都属于同一个 macOS App 进程;Rust PetCore LaunchAgent 只负责状态、事件与数据,不绘制桌宠。气泡 panel 保持 `isOpaque=false` 和透明背景,SwiftUI 内容不再铺不透明白底:macOS 26 把最高透明度的 clear interactive glass 直接施加到包含前景的气泡内容,不加 tint、填充、边框或事后 opacity;透明 Panel 中不再包裹会提升后代玻璃层级的 `GlassEffectContainer`,避免光学层覆盖文字。旧系统使用系统超薄材质;Reduce Transparency 与 Increase Contrast 改用深色高对比回退,保证白色前景可读。
|
||||
|
||||
宠物输入由最小 `NSViewRepresentable` 桥接:左键按下/拖动/抬起只维护移动生命周期,未发生拖动的左键单击不执行额外动作;只有 `rightMouseDown` 在开关允许时构造原生 `NSMenu`。菜单不再同时挂在 SwiftUI 根视图,避免左右键语义重复或一次右击出现两个入口。
|
||||
|
||||
@@ -831,11 +831,12 @@ V1 固定遵守:
|
||||
3. 开启事件会触发桌宠动作。
|
||||
4. 关闭事件不会触发动作,但事件仍入库。
|
||||
5. 每个 Agent 使用一个独立气泡;同一 Agent 的多个会话在气泡内按会话标题、右对齐状态和 Agent 回复正文分行展示,正文最多两行且布局测量使用同一限制,运行中尚无回复时显示「思考中」。连接器未提供标题时,PetCore 按事件时间和持久化序号读取该会话第一条 user 消息,折叠为空格并截为最多 80 个字符作为稳定标题;后续 user 消息只更新当前消息,不改写降级标题。若官方标题随后出现,始终覆盖该降级标题。
|
||||
6. 普通会话默认在最近用户激活 15 分钟后收起且能配置为 1–1440 分钟;新用户消息使其重新出现。仍 active 的 Needs input 与 Blocked 不因普通超时消失,已关闭 Waiting 不长期占位。
|
||||
7. 宠物动作能区分 Running、Needs input、Ready、Blocked,并按 Needs input > Blocked > Ready > Running 仲裁唯一主状态;气泡同时显示最多 8 个会话。
|
||||
8. Codex 气泡能显示会话标题及受控的最新 Agent 回复;UserPromptSubmit 提供标题回退,Stop 提供最终回复,缺失时可按明确 session_id 通过 App Server 只读补全;ChatGPT 桌面任务即使 hooks 暂未触发也能由有界近期活动同步在 1 秒轮询周期内出现;已完成工具不得继续显示为当前活动,持久化层省略实时 item 时不得复活旧摘要;PermissionRequest/`activeFlags` 显示明确交互提示且不泄露工具参数。精确实时工具类别的验收以用户已信任的 `PreToolUse` 为前提。
|
||||
9. 点击或右击任一会话行都路由到该行的 source/session,按钮文案仅为「打开」,关闭热区与会话热区不重叠;Warp 优先精确聚焦原 pane,其他 CLI 至少激活原终端 App;Codex 只对确认属于 ChatGPT 桌面 surface 的任务使用 `codex://threads/<session_id>`,未知/CLI surface 不盲用深链;明确关闭的会话不再提供打开操作。
|
||||
10. 新 ChatGPT 桌面 App 内嵌 Codex CLI 优先于 PATH 旧 CLI;PetCore RPC 协议或构建 ID 不匹配时 App 强制替换旧守护进程。
|
||||
6. macOS 26 气泡使用最高透明度 `Glass.clear.interactive()` 且文字、图标、状态和操作必须位于玻璃内容层;明亮、暗色和混合背景上前景均可辨认,正常模式仍能识别气泡后的桌面内容。Reduce Transparency 与 Increase Contrast 下使用更强的系统/深色回退,不能出现白字白底。
|
||||
7. 普通会话默认在最近用户激活 15 分钟后收起且能配置为 1–1440 分钟;新用户消息使其重新出现。仍 active 的 Needs input 与 Blocked 不因普通超时消失,已关闭 Waiting 不长期占位。
|
||||
8. 宠物动作能区分 Running、Needs input、Ready、Blocked,并按 Needs input > Blocked > Ready > Running 仲裁唯一主状态;气泡同时显示最多 8 个会话。
|
||||
9. Codex 气泡能显示会话标题及受控的最新 Agent 回复;UserPromptSubmit 提供标题回退,Stop 提供最终回复,缺失时可按明确 session_id 通过 App Server 只读补全;ChatGPT 桌面任务即使 hooks 暂未触发也能由有界近期活动同步在 1 秒轮询周期内出现;已完成工具不得继续显示为当前活动,持久化层省略实时 item 时不得复活旧摘要;PermissionRequest/`activeFlags` 显示明确交互提示且不泄露工具参数。精确实时工具类别的验收以用户已信任的 `PreToolUse` 为前提。
|
||||
10. 点击或右击任一会话行都路由到该行的 source/session,按钮文案仅为「打开」,关闭热区与会话热区不重叠;Warp 优先精确聚焦原 pane,其他 CLI 至少激活原终端 App;Codex 只对确认属于 ChatGPT 桌面 surface 的任务使用 `codex://threads/<session_id>`,未知/CLI surface 不盲用深链;明确关闭的会话不再提供打开操作。
|
||||
11. 新 ChatGPT 桌面 App 内嵌 Codex CLI 优先于 PATH 旧 CLI;PetCore RPC 协议或构建 ID 不匹配时 App 强制替换旧守护进程。
|
||||
|
||||
### 14.4 性能
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ Agent 连接页、行为页和桌宠消息气泡必须共用同一品牌图标
|
||||
- 左键单击宠物不触发额外 UI;按住左键拖动仍用于移动位置,仅右击宠物打开快捷菜单。
|
||||
- Agent 事件触发对应动作。
|
||||
- 每个 Agent 使用独立气泡;同一 Agent 的多个会话放在同一个气泡中,并以分隔行区分。
|
||||
- 消息气泡整体使用 macOS 系统原生 Liquid Glass;macOS 26 采用最高透明度的 clear interactive glass,多气泡共享同一玻璃容器。旧系统使用原生 ultra-thin material 回退,不绘制不透明白色卡片。
|
||||
- 消息气泡整体使用 macOS 系统原生 Liquid Glass;macOS 26 采用最高透明度的 clear interactive glass,不加 tint、不透明填充、边框或玻璃层 opacity。气泡内容直接位于玻璃内容层;透明 `NSPanel` 不再额外使用会提升后代玻璃层级的共享容器,避免光学层遮住文字。旧系统使用原生 ultra-thin material 回退,不绘制不透明白色卡片。
|
||||
- 缩放手柄、缩放值、会话收起/展开按钮和悬浮操作统一使用原生透明玻璃;不额外显示“拖动”悬浮标签,宠物帧素材保持无遮挡,脚下不绘制玻璃底座或装饰承托层。控制视觉尺寸保持紧凑,但缩放与收起/展开按钮保留独立的可访问命中区。右击操作固定使用系统 `NSMenu`,不自绘仿系统菜单。
|
||||
- 每个会话行左侧显示会话标题,右侧显示运行状态,下方显示当前信息;正文最多显示两行并在末尾截断,气泡测量高度与两行限制保持一致。运行中优先显示上游公开的实时活动摘要(例如 Codex 的 reasoning summary、计划、搜索、文件修改或工具类别);没有新实时信号时保留最近公开信息,再退回 Agent 回复或「思考中」。已完成的工具项不得继续冒充当前活动,Ready/完成态显示最终 Agent 回复,Needs input/Blocked 显示交互或错误状态提示,不能用旧回复掩盖当前状态。Codex 精确的实时 Shell/读取/搜索切换来自用户已信任的官方 hooks;未信任时 App Server 有损快照只做标题、消息、公开摘要和有限状态兜底,不伪造被省略的具体工具。标题不可用时固定退回该会话第一条用户消息的单行摘要;若首条消息也不可用,再退回项目标识和 Agent 会话占位名。后续用户消息不得改写已形成的降级标题。
|
||||
- 活跃会话没有新事件时继续保留当前状态与消息,不退回“等待 Agent 事件”。普通会话从最近一次可观测活动起超过配置时长后收起,默认 15 分钟;用户发送新消息或 Agent 产生新活动后重新展示。ChatGPT 桌面 Codex 在 hooks 暂未触发时由官方 App Server 的有界近期任务查询兜底,不要求用户先重启任务。
|
||||
|
||||
Reference in new issue
Block a user