docs: clarify shell observation and window-local tab contracts

This commit is contained in:
2026-11-12 20:58:37 +08:00
parent 2d5138c7ad
commit b15d0872d7
4 changed files with 18 additions and 7 deletions
+7 -2
View File
@@ -1,5 +1,5 @@
//! 有界 HTTP 活动记录。保存请求/响应的可显示预览供 Network 工具读取,不负责执行请求。
//! 正文预览和允许显示的头部受限制,避免活动面板成为无限日志或暴露不必要数据的通道。
//! 本模块限制预览字节数与记录条数;请求头白名单由 runtime/api::ObservedRequest 提前筛选。
//!
//! Bounded observation of this process's local HTTP API, never external traffic.
use std::{
@@ -20,10 +20,11 @@ const MAX_RECORDS: usize = 80;
pub struct Exchange {
// 由 begin 分配的日志身份,HTTP worker 后续只携带此 ID 更新,不持有队列元素引用。
pub id: u64,
// 请求方法和来源标签由本地 API 观察器传入;origin 只供显示,不授予执行权限。
// 请求方法由本地 API 观察器传入,按原文本保存;这里不校验或执行 HTTP 方法。
pub method: String,
// 请求 URL 的受限预览,不在此解析路由或读取所指文件。
pub path: String,
// ObservedRequest 传入 HTTP/Console 显示标签;本字段不参与认证或路由,也不在此截断。
pub origin: String,
// 开始时刻的 UTC 时分秒文本,不含日期;耗时另用 started 单调时钟计算。
pub timestamp: String,
@@ -35,7 +36,9 @@ pub struct Exchange {
pub status: Option<u16>,
// 初始为零,finish 时从 begin 起累计毫秒;不在界面每次绘制时持续刷新。
pub elapsed_ms: u128,
// 请求头已经过观察器白名单筛选,这里再截断文本;ActivityLog 自身不检查头名称。
pub request_headers: String,
// respond 提供已构造响应的全部头部文本,本模块仅限长,不沿用请求头的白名单。
pub response_headers: String,
// 使用单调时钟计算耗时,不受系统时间调整影响;timestamp 则用于显示 UTC 时刻。
started: Instant,
@@ -46,6 +49,7 @@ pub struct Exchange {
pub struct ActivityLog {
// 开始顺序队列,Network/Console 工具通过共享锁读取或复制;完成顺序不会重排记录。
pub records: VecDeque<Exchange>,
// 默认从零开始,begin 先递增再使用;计数仅属此日志实例,不是跨进程请求身份。
next_id: u64,
}
impl ActivityLog {
@@ -100,6 +104,7 @@ impl ActivityLog {
// 仅更新仍保留的请求,响应正文和头部都重新截断;耗时从 begin 起计算。
// ObservedRequest::respond 在真实响应发送前调用,状态和耗时表示已构造响应,不证明客户端接收成功。
pub fn finish(&mut self, id: u64, status: u16, body: &str, headers: String) {
// finish 可能晚于容量淘汰,找不到 ID 时整个更新跳过;不为旧响应另建记录。
if let Some(record) = self.records.iter_mut().find(|r| r.id == id) {
record.status = Some(status);
record.response = preview(body);
+2 -2
View File
@@ -15,7 +15,7 @@ fn command(program: &str) -> std::process::Command {
cmd
}
/// 取得系统剪贴板的 UTF-8 文本,失败作为可显示错误返回。
// shell/app 处理开发工具粘贴快捷键时调用;失败由工具 input_error 展示,不用空字符串冒充成功。
// shell/app 处理开发工具粘贴快捷键时同步调用;等待 pbpaste 结束后才插入文本,失败由 input_error 展示。
pub fn read() -> Result<String> {
#[cfg(target_os = "macos")]
{
@@ -39,7 +39,7 @@ pub fn read() -> Result<String> {
}
}
/// 将提供的文本交给系统剪贴板命令,不执行文本内容。
// shell/app 的复制与剪切路径调用;只有成功返回后剪切才会删除编辑器中的选中文本。
// shell/app 的复制与剪切快捷键同步调用;仅非空选区才进入这里,成功返回后剪切才删除编辑器选中文本。
pub fn write(value: &str) -> Result<()> {
#[cfg(target_os = "macos")]
{
+6 -1
View File
@@ -24,15 +24,21 @@ pub const CONTROLS: f32 = if cfg!(target_os = "macos") { 86.0 } else { 0.0 };
/// 侧栏释放激活后要执行的管理动作,绘制本身只登记它。
// app::sidebar_action 执行这些已确认动作;页面 ID 来自本窗口的 Tab 投影,不是 VM 对象引用。
pub enum Action {
// app 就地切换侧栏占用宽度并发布视口,不向 VM 发送标签事件。
Toggle,
// app 通过 open_developer_tool("New tab") 提交新页请求,不在 draw 内创建页面。
NewPage,
// 固定工具名称交给同一打开入口,是否复用已有工具页由运行时处理。
Tool(&'static str),
// app 将当前窗口标签 ID 放进 Input.mount,并以 tab-activate 交给 worker 校验与切页。
Activate(u64),
// 与激活使用相同身份通道,但事件种类为 tab-close,不能按列表行号关闭页面。
Close(u64),
}
/// 侧栏开合、控件交互和本帧目标集合,决定实际占用页面宽度。
pub struct State {
// 仅属宿主 UI 的开合状态;决定 left/covers/draw,不是托管页面中的可响应属性。
pub open: bool,
// 跨帧保存悬停、键盘焦点和按下捕获;目标矩形则由每次 draw 重建。
pub interaction: Interaction,
@@ -154,7 +160,6 @@ impl State {
let y = area.y + index as f32 * 36.0 - self.scroll;
// Register only fully visible rows: paint clipping must match input.
// 当前实现完全跳过部分可见行,绘制与注册都不发生;Clip 仍保护其他原语不溢出列表区域。
// 部分可见行整行跳过,既不产生切页按钮也不产生关闭按钮,防止不可见片段仍可激活。
if y < area.y || y + 32.0 > area.y + area.height {
continue;
}
+3 -2
View File
@@ -1,14 +1,15 @@
//! 发布页面标签的数据结构。保留稳定页面身份、标题、选中状态和开发工具类别;页面的托管所有权由模型层管理。
//!
//! Immutable page registry projections. Host navigation is rendered in sidebar.
//! IDs are session-local data and never own managed VM objects.
//! IDs are local to each window presentation and never own managed VM objects.
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
/// 托管页面注册表的不可变投影,原生工具只使用稳定 ID 与显示元数据。
// ui_bridge::project_tabs 从当前窗口页面注册表生成;sidebar 画标签,scene 用 developer_tool 标记选择宿主管理页。
pub struct Tab {
// 会话内稳定 ID,供原生侧发起切页/关闭操作;不能直接当作 VM 对象地址。
// 当前窗口展示内稳定的 ID,不保证跨窗口唯一;输入还需携带窗口、session 和 layout_version。
// project_tabs 按 Page 弱身份复用 ID;移出窗口后映射删除,再加入时可获得新 ID,不能当作 VM 地址。
pub id: u64,
// 本次发布的标题文本副本,原生界面显示时无需读取 VM。
pub title: String,