Upgrade the pinned driver, validate menu and taskbar focus ownership, patch untitled Shell resolution, and remove duplicate scroll scaling. Publish package provenance, verification boundaries and matching marketplace checksum. Go tests, vet, build and byte-level package verification passed.
96 lines
3.6 KiB
Go
96 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
)
|
|
|
|
// Optional filters must remain optional across JSON-schema clients. In
|
|
// particular, null means unspecified; zero is not a wildcard process ID.
|
|
func windowQuery(args obj) (obj, error) {
|
|
query := obj{}
|
|
for key, value := range args {
|
|
if value != nil {
|
|
query[key] = value
|
|
}
|
|
}
|
|
if value, ok := query["app"]; ok {
|
|
app, valid := value.(string)
|
|
if !valid {
|
|
return nil, errors.New("app must be an application name or null")
|
|
}
|
|
if app = strings.TrimSpace(app); app == "" {
|
|
delete(query, "app")
|
|
} else {
|
|
query["app"] = app
|
|
}
|
|
}
|
|
if value, ok := query["pid"]; ok {
|
|
valid := num(value) > 0 && num(value) <= math.MaxUint32
|
|
switch n := value.(type) {
|
|
case float64:
|
|
valid = valid && n == math.Trunc(n)
|
|
case int, int64:
|
|
default:
|
|
valid = false
|
|
}
|
|
if !valid {
|
|
return nil, errors.New("pid must be a positive Windows process ID from a matching list_windows result. If unknown, omit pid or use null and search by app, e.g. {\"app\":\"Brave\",\"on_screen_only\":true}. Never use 0 or a different app's foreground PID")
|
|
}
|
|
}
|
|
return query, nil
|
|
}
|
|
|
|
// Upstream's empty-result hint names the unrelated foreground process. Do not
|
|
// present that PID as a recovery candidate. Keep the exact filters and provide
|
|
// a separate suggested query; never silently widen the caller's PID scope.
|
|
func windowListing(result obj, query obj) obj {
|
|
if result["isError"] == true {
|
|
return result
|
|
}
|
|
data := object(result["structuredContent"])
|
|
windows, ok := data["windows"].([]any)
|
|
if !ok {
|
|
return failure("Driver returned no window list; this is an observation error, not evidence that the application is absent", "not_started", "none", "invalid_window_list")
|
|
}
|
|
lookup := obj{"status": "matched", "filters": query, "count": len(windows)}
|
|
lines := []string{fmt.Sprintf("Found %d matching window(s).", len(windows))}
|
|
for _, value := range windows {
|
|
window := object(value)
|
|
lines = append(lines, fmt.Sprintf("- %s (pid %d), window_id %d, title %q", str(window["app_name"]), num(window["pid"]), num(window["window_id"]), str(window["title"])))
|
|
if kind := str(window["window_kind"]); kind != "" {
|
|
lines[len(lines)-1] += fmt.Sprintf(" [%s, class %s]", kind, str(window["class_name"]))
|
|
}
|
|
}
|
|
if len(windows) == 0 {
|
|
lookup["status"] = "no_match"
|
|
lines = append(lines, "No windows match these filters. This alone does not prove the application is unavailable or screenshot capture is broken. Do not substitute another application's foreground PID.")
|
|
if str(query["app"]) != "" && query["pid"] != nil {
|
|
next := obj{}
|
|
for key, value := range query {
|
|
if key != "pid" {
|
|
next[key] = value
|
|
}
|
|
}
|
|
lookup["suggested_arguments"] = next
|
|
lines = append(lines, "app and pid are combined filters. Retry list_windows for the same app with pid omitted; use only a PID returned for that app.")
|
|
} else if query["on_screen_only"] == true {
|
|
next := obj{}
|
|
for key, value := range query {
|
|
next[key] = value
|
|
}
|
|
next["on_screen_only"] = false
|
|
lookup["suggested_arguments"] = next
|
|
lines = append(lines, "Retry the same filters with on_screen_only=false to check for minimized/off-screen windows. A listed window still needs a fresh get_window_state before interaction.")
|
|
} else {
|
|
lines = append(lines, "Verify the requested application name or PID. When the PID is unknown, search by the known app name with pid omitted. Do not guess a PID or operate an unrelated window.")
|
|
}
|
|
}
|
|
data["lookup"] = lookup
|
|
result["structuredContent"] = data
|
|
result["content"] = []any{textBlock(strings.Join(lines, "\n"))}
|
|
return result
|
|
}
|