windows

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const (
	SubjectScreenText         = "screen.text"
	SubjectWindowTitle        = "window.title"
	SubjectWindow             = "window"
	SubjectElement            = "element"
	SubjectElementName        = "element.name"
	SubjectElementValue       = "element.value"
	SubjectElementControlType = "element.control_type"
	SubjectElementEnabled     = "element.enabled"
	SubjectElementChecked     = "element.checked"
	SubjectElementSelected    = "element.selected"
	SubjectElementFocused     = "element.focused"
	SubjectElementCount       = "element.count"
	SubjectResultText         = "result.text"
)

Assertion subjects. The set is closed and matches the journey vocabulary.

View Source
const (
	OpIs             = "is"
	OpIsNot          = "is_not"
	OpContains       = "contains"
	OpDoesNotContain = "does_not_contain"
	OpStartsWith     = "starts_with"
	OpEndsWith       = "ends_with"
	OpMatches        = "matches"
	OpDoesNotMatch   = "does_not_match"
	OpIsEmpty        = "is_empty"
	OpIsNotEmpty     = "is_not_empty"
	OpIsOneOf        = "is_one_of"
	OpIsNotOneOf     = "is_not_one_of"
	OpIsTrue         = "is_true"
	OpIsFalse        = "is_false"
	OpExists         = "exists"
	OpDoesNotExist   = "does_not_exist"
	OpGreaterThan    = "greater_than"
	OpGreaterOrEqual = "greater_or_equal"
	OpLessThan       = "less_than"
	OpLessOrEqual    = "less_or_equal"
)

Assertion operators.

Variables

View Source
var (
	// ToolsetScreen: read-only perception of the desktop.
	ToolsetScreen = inventory.ToolsetMetadata{
		ID:          "screen",
		Description: "Read-only perception of the desktop: UI-tree snapshots, screenshots, and display inventory.",
		Default:     true,
		Icon:        "device-desktop",
	}
	// ToolsetInteraction: synthetic input and UI interaction.
	ToolsetInteraction = inventory.ToolsetMetadata{
		ID:          "interaction",
		Description: "Mouse and keyboard interaction: click, type, scroll, move, shortcuts, waits, and multi-element actions.",
		Default:     true,
		Icon:        "pointer",
	}
	// ToolsetApps: application and window lifecycle.
	ToolsetApps = inventory.ToolsetMetadata{
		ID:          "apps",
		Description: "Launch, switch, resize, and manage applications and windows.",
		Default:     true,
		Icon:        "browser",
	}
	// ToolsetSystem: local system state and objects.
	ToolsetSystem = inventory.ToolsetMetadata{
		ID:          "system",
		Description: "Local system operations: process list/kill, clipboard, and notifications.",
		Default:     true,
		Icon:        "gear",
	}
	// ToolsetSystemAdmin: persistence and machine-configuration tools.
	//
	// Separate from ToolsetSystem, and non-default, because these outlive the
	// session. ScheduledTask create/run registers a program on logon or startup and
	// Registry set writes Run keys, so either survives the session, the kill switch
	// and a reboot — a different class of risk from listing processes or reading the
	// clipboard, and not something a persona should carry implicitly.
	ToolsetSystemAdmin = inventory.ToolsetMetadata{
		ID: "system-admin",
		Description: "Registry read/write and scheduled-task management. These change machine " +
			"configuration and can persist across reboots; disabled by default.",
		Icon: "gear",
	}
	// ToolsetShell: arbitrary PowerShell execution (powerful; non-default).
	ToolsetShell = inventory.ToolsetMetadata{
		ID:          "shell",
		Description: "Execute arbitrary PowerShell commands. Powerful and potentially destructive; disabled by default.",
		Icon:        "terminal",
	}
	// ToolsetFilesystem: file operations (non-default).
	ToolsetFilesystem = inventory.ToolsetMetadata{
		ID:          "filesystem",
		Description: "Read, write, copy, move, delete, list, and search files. Disabled by default.",
		Icon:        "file-directory",
	}
	// ToolsetWeb: web scraping (non-default).
	ToolsetWeb = inventory.ToolsetMetadata{
		ID:          "web",
		Description: "Fetch and extract web page content, optionally via the active browser's DOM. Disabled by default.",
		Icon:        "globe",
	}
	// ToolsetDiagnostics: system diagnostics for support workflows (non-default).
	ToolsetDiagnostics = inventory.ToolsetMetadata{
		ID: "diagnostics",
		Description: "System diagnostics: OS/hardware inventory, Windows service control, event-log queries, and " +
			"network inspection, for support and troubleshooting. Disabled by default.",
		Icon: "pulse",
	}
	// ToolsetTesting: assertions and evidence capture for QA (non-default).
	ToolsetTesting = inventory.ToolsetMetadata{
		ID:          "testing",
		Description: "UI test assertions and evidence capture, for authoring and running automated tests. Disabled by default.",
		Icon:        "beaker",
	}
	// ToolsetPlanning: propose a sequence of tool calls for whole-plan
	// adjudication, then apply it (non-default). Opt-in because it is a distinct
	// way of working — the agent proposes, the plan is reviewed and adjudicated as
	// a whole, then executed — rather than an extra tool for the usual loop.
	ToolsetPlanning = inventory.ToolsetMetadata{
		ID: "planning",
		Description: "Propose a whole sequence of tool calls as a reviewable plan, adjudicated up front, then " +
			"apply it. Disabled by default.",
		Icon: "checklist",
	}
	// ToolsetPackages: software install/removal via winget and MSI (non-default).
	// Opt-in and in no persona: it downloads and runs installers from the network,
	// outside the egress proxy, so it stays off the default surface until an
	// operator deliberately asks for it.
	ToolsetPackages = inventory.ToolsetMetadata{
		ID: "packages",
		Description: "Install, remove, list, and search software via winget and MSI. Downloads run installers " +
			"from the network, outside the egress proxy. Disabled by default and in no persona.",
		Icon: "package",
	}
	// ToolsetCredentials: use of credentials installed at init (non-default).
	// Enabled automatically when --credentials-file is supplied; there is nothing
	// to use without it.
	ToolsetCredentials = inventory.ToolsetMetadata{
		ID: "credentials",
		Description: "Sign-in using credentials supplied to the server at startup and held in the Windows " +
			"Credential Manager. Secrets can be injected into fields but never read back. Disabled by " +
			"default; enabled automatically with --credentials-file.",
		Icon: "key",
	}
)

Toolset metadata. Each tool declares membership in exactly one of these. The Default flag marks toolsets included when the caller asks for the "default" configuration (or passes no --toolsets selection). These groupings are also the building blocks of the persona presets below.

AssertOperators is every operator the Assert tool evaluates, for its schema enum.

AssertSubjects is every subject the Assert tool evaluates, for its schema enum.

View Source
var ErrAssertionShape = fmt.Errorf("the assertion cannot be evaluated as written")

ErrAssertionShape reports an assertion that cannot be evaluated as written — an operator that does not apply to the subject, or a missing or mistyped expected value. It is distinct from a failed assertion: the first is a broken document, the second is a broken application.

View Source
var Personas = map[string]Persona{
	"first-line-support": {
		ID:          "first-line-support",
		Description: "1st-line support engineer: perceive and drive the desktop, manage apps and system state, run diagnostics, and control services.",

		Toolsets: []string{"screen", "interaction", "apps", "system", "system-admin", "shell", "diagnostics"},
		ReadOnly: false,
		Instructions: "You are assisting a 1st-line support engineer troubleshooting a Windows machine. " +
			"Diagnose before you act: take a Snapshot to see the desktop, and use SystemInfo, Process, and Service " +
			"to gather state before making changes. Use PowerShell for deeper diagnostics. Before any destructive or " +
			"disruptive action (killing a process, stopping a service, editing the registry), state what you will do " +
			"and why. Report findings and the steps you took in clear, non-jargon language the end user can follow.",
	},
	"qa-test-engineer": {
		ID:          "qa-test-engineer",
		Description: "QA test engineer: full desktop automation for authoring and running UI tests, with assertions, evidence capture, filesystem, and web access.",
		Toolsets:    []string{"screen", "interaction", "apps", "system", "filesystem", "web", "testing"},
		ReadOnly:    false,
		Instructions: "You are automating and verifying UI tests as a QA engineer. Work deterministically: take a " +
			"Snapshot before each interaction and target elements by their label rather than raw coordinates, since " +
			"labels are stable across DPI, theme, and window position. Verify every expected outcome with Assert or " +
			"WaitFor, and treat a failed Assert as a test failure to report — do not silently continue. Capture " +
			"evidence with CaptureEvidence at key steps and on failure. Re-Snapshot after the UI changes.",
	},
	"business-user": {
		ID: "business-user",
		Description: "Business end-user & user-journey testing: drive everyday applications and browse the web through " +
			"the real UI, verify outcomes, and capture evidence — without shell, registry, or file-system access.",
		Toolsets: []string{"screen", "interaction", "apps", "web", "testing"},
		ReadOnly: false,
		Instructions: "You are driving a Windows device as a business end-user, to complete everyday tasks and to test " +
			"user journeys through the real application UI. Work one observable step at a time: take a Snapshot, act on " +
			"an element by its label (Click, Type, or the UIA actions Invoke/SetValue/Toggle/Select), then verify the " +
			"result with Assert or WaitFor before moving on — treat a failed Assert as a failed journey step and report " +
			"it. Prefer the UIA actions (Invoke/SetValue) over raw Click/Type where available: they are more reliable and " +
			"do not depend on window focus. Capture evidence with CaptureEvidence at key steps and on failure. You have " +
			"no shell, registry, or file-system access — stay within the open applications and browser. " +
			"Note: the Windows sign-in screen, lock screen, and UAC elevation prompts run on a protected desktop that " +
			"cannot be automated; assume you are already in an unlocked, signed-in session. Explain each step in plain " +
			"language and confirm before anything a user might not expect (submitting forms, deleting content, closing apps).",
	},
}

Personas is the registry of built-in personas.

These are intentionally coarse starting points for the persona work; the tool surface each one exposes will be tuned once feature parity is proven. They demonstrate that persona = (toolset selection + read-only stance) over the same underlying tool manifest.

Functions

func ArgsMap

func ArgsMap(req *mcp.CallToolRequest) (map[string]any, error)

ArgsMap unmarshals a tool call's raw arguments into a generic map. Tools that need the Python-parity coercions below (bool-or-string, list-or-string) use this rather than a typed struct, because some MCP clients (notably Claude Desktop) strip anyOf schemas and send booleans and arrays as JSON strings.

func EvalAssertion added in v1.3.0

func EvalAssertion(operator string, obs Observation, expected any, opts CompareOptions) (bool, error)

EvalAssertion decides whether an observation satisfies operator/expected.

It returns an error only for an assertion that is malformed; a condition that simply does not hold returns (false, nil). An absent subject never satisfies anything except does_not_exist, and never errors — the control not having a toggle state is a fact about the application, which is what the run is testing.

func NewToolResultError

func NewToolResultError(text string) *mcp.CallToolResult

NewToolResultError returns a tool-level error result (IsError set). Per the MCP convention, expected/user-facing errors are returned this way — with a nil Go error — so the model can see the message and self-correct. Reserve a real Go error for infrastructure failures.

func NewToolResultErrorFromErr

func NewToolResultErrorFromErr(msg string, err error) *mcp.CallToolResult

NewToolResultErrorFromErr returns a tool-level error result combining a message and an underlying error.

func NewToolResultErrorf

func NewToolResultErrorf(format string, a ...any) *mcp.CallToolResult

NewToolResultErrorf is NewToolResultError with fmt formatting.

func NewToolResultImage

func NewToolResultImage(text string, pngData []byte, mimeType string) *mcp.CallToolResult

NewToolResultImage returns a successful tool result carrying a PNG (or other) image plus an optional leading text block. Pass empty text to omit it.

func NewToolResultText

func NewToolResultText(text string) *mcp.CallToolResult

NewToolResultText returns a successful tool result carrying a single text block.

func NewToolResultTextf

func NewToolResultTextf(format string, a ...any) *mcp.CallToolResult

NewToolResultTextf is NewToolResultText with fmt formatting.

func OptionalBool

func OptionalBool(args map[string]any, key string, fallback bool) bool

OptionalBool returns a bool argument or the fallback. It accepts real JSON booleans and the strings "true"/"false" (case-insensitive), matching how some MCP clients encode booleans.

func OptionalFloat added in v1.3.0

func OptionalFloat(args map[string]any, key string, fallback float64) (float64, error)

OptionalFloat returns a float argument or the fallback. It accepts JSON numbers and numeric strings, for the same reason OptionalInt does: some MCP clients stringify numbers.

Timeouts are fractional (a 0.4-second poll interval is the default), so they cannot go through OptionalInt without silently truncating to zero.

func OptionalInt

func OptionalInt(args map[string]any, key string, fallback int) (int, error)

OptionalInt returns an int argument or the fallback. It accepts JSON numbers and numeric strings.

func OptionalIntSlice

func OptionalIntSlice(args map[string]any, key string) ([]int, error)

OptionalIntSlice returns an []int argument. It accepts a JSON array of numbers or a JSON string containing such an array (e.g. "[10, 20]"), matching clients that stringify array parameters.

func OptionalString

func OptionalString(args map[string]any, key, fallback string) string

OptionalString returns a string argument or the fallback when absent.

func OptionalStringEnum

func OptionalStringEnum(args map[string]any, key, fallback string, allowed ...string) (string, error)

OptionalStringEnum returns a string argument constrained to allowed values, falling back when absent. It errors on a present-but-invalid value.

func RequiredString

func RequiredString(args map[string]any, key string) (string, error)

RequiredString returns a required string argument.

func SubjectNeedsTarget added in v1.3.0

func SubjectNeedsTarget(subject string) bool

SubjectNeedsTarget reports whether a subject reads a particular element or window and therefore needs a selector.

Types

type CompareOptions added in v1.3.0

type CompareOptions struct {
	IgnoreCase         bool
	Trim               bool
	CollapseWhitespace bool
}

CompareOptions are the text-comparison modifiers, all defaulting off so behaviour is never implicit. The behaviour they replace folded case for window titles and for nothing else, and said so nowhere.

type Observation added in v1.3.0

type Observation struct {
	Kind   ValueKind
	Text   string
	Number float64
	Bool   bool
	Exists bool

	Absent bool
	// AbsentReason explains what was missing, and is what the failure reports.
	AbsentReason string
}

Observation is what was actually read from the desktop. Absent marks a subject that could not be read at all — a toggle state on a control that has none — so a failure can say that rather than reporting a misleading false.

func (Observation) Render added in v1.3.0

func (o Observation) Render() string

Render renders the observed value for a failure message and for the run record's journey.assertion.observed attribute. It is the thing a text log never carried: a failure that reports only the condition name says a test broke, one that reports what was on screen usually says why.

type PSScript added in v1.2.0

type PSScript = psdata.Builder

PSScript builds a PowerShell script binding every model-supplied value as data instead of interpolating it as source text — the defence against a value closing its own string literal and starting a new statement.

It is an alias rather than a wrapper so the tool layer and the desktop engine share one implementation; see internal/psdata for why quoting cannot do this job and what makes binding safe.

Use it for every model-supplied value that reaches PowerShell:

var ps PSScript
cmd := ps.Script("Get-Item -Path " + ps.Arg(path))

type Persona

type Persona struct {
	// ID is the persona's selector value (e.g. "first-line-support").
	ID string
	// Description explains who the persona is for.
	Description string
	// Toolsets is the toolset selection this persona enables (values accepted by
	// Builder.WithToolsets, including "all"/"default").
	Toolsets []string
	// ReadOnly is the persona's default read-only stance. A caller may still
	// override it explicitly.
	ReadOnly bool
	// Instructions is guidance injected into the MCP server's Instructions so
	// the agent adopts this persona's workflow and mindset.
	Instructions string
}

Persona is a named preset that resolves to a toolset selection and a read-only default. Personas make the toolset engine's persona goal concrete: each is simply a fixed WithToolsets configuration a caller can select with a single flag, rather than enumerating toolsets by hand.

func LookupPersona

func LookupPersona(id string) (Persona, bool)

LookupPersona returns the named persona and whether it exists.

type ValueKind added in v1.3.0

type ValueKind string

ValueKind is the type of value a subject reads.

const (
	KindText      ValueKind = "text"
	KindNumber    ValueKind = "number"
	KindBoolean   ValueKind = "boolean"
	KindExistence ValueKind = "existence"
)

func SubjectKind added in v1.3.0

func SubjectKind(subject string) (ValueKind, bool)

SubjectKind returns the value type a subject reads, and whether the subject is one this build evaluates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL