Documentation
¶
Index ¶
- Constants
- Variables
- func ArgsMap(req *mcp.CallToolRequest) (map[string]any, error)
- func EvalAssertion(operator string, obs Observation, expected any, opts CompareOptions) (bool, error)
- func NewToolResultError(text string) *mcp.CallToolResult
- func NewToolResultErrorFromErr(msg string, err error) *mcp.CallToolResult
- func NewToolResultErrorf(format string, a ...any) *mcp.CallToolResult
- func NewToolResultImage(text string, pngData []byte, mimeType string) *mcp.CallToolResult
- func NewToolResultText(text string) *mcp.CallToolResult
- func NewToolResultTextf(format string, a ...any) *mcp.CallToolResult
- func OptionalBool(args map[string]any, key string, fallback bool) bool
- func OptionalFloat(args map[string]any, key string, fallback float64) (float64, error)
- func OptionalInt(args map[string]any, key string, fallback int) (int, error)
- func OptionalIntSlice(args map[string]any, key string) ([]int, error)
- func OptionalString(args map[string]any, key, fallback string) string
- func OptionalStringEnum(args map[string]any, key, fallback string, allowed ...string) (string, error)
- func RequiredString(args map[string]any, key string) (string, error)
- func SubjectNeedsTarget(subject string) bool
- type CompareOptions
- type Observation
- type PSScript
- type Persona
- type ValueKind
Constants ¶
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.
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 ¶
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.
var AssertOperators = []any{ OpIs, OpIsNot, OpContains, OpDoesNotContain, OpStartsWith, OpEndsWith, OpMatches, OpDoesNotMatch, OpIsEmpty, OpIsNotEmpty, OpIsOneOf, OpIsNotOneOf, OpIsTrue, OpIsFalse, OpExists, OpDoesNotExist, OpGreaterThan, OpGreaterOrEqual, OpLessThan, OpLessOrEqual, }
AssertOperators is every operator the Assert tool evaluates, for its schema enum.
var AssertSubjects = []any{ SubjectScreenText, SubjectWindowTitle, SubjectWindow, SubjectElement, SubjectElementName, SubjectElementValue, SubjectElementControlType, SubjectElementEnabled, SubjectElementChecked, SubjectElementSelected, SubjectElementFocused, SubjectElementCount, SubjectResultText, }
AssertSubjects is every subject the Assert tool evaluates, for its schema enum.
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.
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 ¶
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
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 ¶
OptionalInt returns an int argument or the fallback. It accepts JSON numbers and numeric strings.
func OptionalIntSlice ¶
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 ¶
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 ¶
RequiredString returns a required string argument.
func SubjectNeedsTarget ¶ added in v1.3.0
SubjectNeedsTarget reports whether a subject reads a particular element or window and therefore needs a selector.
Types ¶
type CompareOptions ¶ added in v1.3.0
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
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 ¶
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.
func SubjectKind ¶ added in v1.3.0
SubjectKind returns the value type a subject reads, and whether the subject is one this build evaluates.