merge: resolve SKILL.md conflicts with main

Keep the expanded command-reference tables from feat/upload-download
(including the new File Transfer section) over main's compact two-line
format.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
drakezhang
2026-09-02 16:42:15 +08:00
co-authored by Cursor
32 changed files with 1524 additions and 831 deletions
+54 -2
View File
@@ -58,8 +58,9 @@ pub struct SnapshotResult {
/// for one tab plus a fresh `@e<N>` ref-store on the extension side.
///
/// Unlike `tool.snapshot`, this path may run bounded perception probes
/// such as hover-surface discovery. It must not submit input, click,
/// navigate, or otherwise commit page state.
/// such as hover-surface discovery, but only when `probe_hover` asks for
/// them. It must not submit input, click, navigate, or otherwise commit
/// page state.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ObserveParams {
pub session_id: String,
@@ -77,6 +78,16 @@ pub struct ObserveParams {
/// Include implementation diagnostics for conditional surface probes.
#[serde(default)]
pub debug_surfaces: bool,
/// Opt in to active hover probing: the extension moves the real cursor
/// over a bounded set of controls to discover hover-only menus and
/// tooltips.
///
/// Off by default. Probing costs seconds of wall clock, mutates the live
/// page, and pays off only on pages whose content is genuinely hidden
/// behind hover. Request it when a static observation looks like it is
/// missing hover-revealed structure.
#[serde(default)]
pub probe_hover: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
@@ -102,6 +113,17 @@ pub struct ObserveDebug {
pub surface_probes: Vec<SurfaceProbeDebug>,
}
/// Reports what active hover probing did during an observation, so the agent
/// can judge how far the live page may have drifted from the returned text.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct HoverProbeReport {
/// The real cursor was moved over page content during this observation.
pub performed: bool,
/// Hovering surfaced content the static tree does not contain, so the page
/// reacts to the cursor and may not have fully reverted.
pub revealed_content: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ObserveResult {
/// Semantic VOM observation text. Refs are rendered as `@e<N>` so
@@ -118,6 +140,9 @@ pub struct ObserveResult {
pub truncated: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub dialogs: Vec<JavaScriptDialogInfo>,
/// Present only when `probe_hover` was requested and probing actually ran.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hover_probe: Option<HoverProbeReport>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub debug: Option<ObserveDebug>,
}
@@ -308,6 +333,7 @@ mod tests {
tab_id: 42,
truncated: false,
dialogs: Vec::new(),
hover_probe: None,
debug: None,
};
let v = serde_json::to_value(&r).unwrap();
@@ -315,4 +341,30 @@ mod tests {
let round: ObserveResult = serde_json::from_value(v).unwrap();
assert_eq!(round, r);
}
#[test]
fn observe_params_default_to_no_hover_probing() {
let params: ObserveParams =
serde_json::from_value(serde_json::json!({ "session_id": "s1" })).unwrap();
assert!(!params.probe_hover);
}
#[test]
fn observe_result_round_trips_with_hover_probe_report() {
let r = ObserveResult {
text: "@vom 1\n".into(),
ref_count: 0,
tab_id: 42,
truncated: false,
dialogs: Vec::new(),
hover_probe: Some(HoverProbeReport {
performed: true,
revealed_content: true,
}),
debug: None,
};
let v = serde_json::to_value(&r).unwrap();
let round: ObserveResult = serde_json::from_value(v).unwrap();
assert_eq!(round, r);
}
}