From d8bf39ac03e076f60b72049da17347b8b696a741 Mon Sep 17 00:00:00 2001 From: JeffreyChen Date: Tue, 10 Nov 2026 01:08:36 +0800 Subject: [PATCH 1/3] docs: simplify READMEs and move detailed guides into docs --- README.md | 1590 +-------------------- README/README_zh-CN.md | 1331 +---------------- README/README_zh-TW.md | 1333 +---------------- docs/README.md | 19 + docs/guides/en/development.md | 98 ++ docs/guides/en/evidence.md | 151 ++ docs/guides/en/implementation-notes.md | 658 +++++++++ docs/guides/en/integrations.md | 130 ++ docs/guides/en/setup.md | 355 +++++ docs/guides/en/usage.md | 216 +++ docs/guides/zh-CN/development.md | 90 ++ docs/guides/zh-CN/evidence.md | 121 ++ docs/guides/zh-CN/implementation-notes.md | 516 +++++++ docs/guides/zh-CN/integrations.md | 125 ++ docs/guides/zh-CN/setup.md | 294 ++++ docs/guides/zh-CN/usage.md | 203 +++ docs/guides/zh-TW/development.md | 90 ++ docs/guides/zh-TW/evidence.md | 121 ++ docs/guides/zh-TW/implementation-notes.md | 515 +++++++ docs/guides/zh-TW/integrations.md | 126 ++ docs/guides/zh-TW/setup.md | 294 ++++ docs/guides/zh-TW/usage.md | 203 +++ 22 files changed, 4410 insertions(+), 4169 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/guides/en/development.md create mode 100644 docs/guides/en/evidence.md create mode 100644 docs/guides/en/implementation-notes.md create mode 100644 docs/guides/en/integrations.md create mode 100644 docs/guides/en/setup.md create mode 100644 docs/guides/en/usage.md create mode 100644 docs/guides/zh-CN/development.md create mode 100644 docs/guides/zh-CN/evidence.md create mode 100644 docs/guides/zh-CN/implementation-notes.md create mode 100644 docs/guides/zh-CN/integrations.md create mode 100644 docs/guides/zh-CN/setup.md create mode 100644 docs/guides/zh-CN/usage.md create mode 100644 docs/guides/zh-TW/development.md create mode 100644 docs/guides/zh-TW/evidence.md create mode 100644 docs/guides/zh-TW/implementation-notes.md create mode 100644 docs/guides/zh-TW/integrations.md create mode 100644 docs/guides/zh-TW/setup.md create mode 100644 docs/guides/zh-TW/usage.md diff --git a/README.md b/README.md index 3532f6259..4b90b365e 100644 --- a/README.md +++ b/README.md @@ -1,1590 +1,56 @@ # AutoControl -Transfer management now shares `manage_agent_transfer(operation, request)`, `AC_agent_transfer`, -`ac_agent_transfer`, authenticated `POST /agent/transfer`, and Script Builder metadata. The CLI uses -`agent-task transfer --operation review_export --request request.json`. Review returns an approval -token; creation requires that token, the original request key and an explicit note. Export/import -management and portable evidence management support registered hosts, with source-local authority checks. -The Transfers page exposes these operations through explicit Actions, editable JSON and four locales. -Review never sends approval; preparing approval preserves the original host, review token and request -key with an empty note. Changed selections and closed views reject late replies; accepted imports -remain service-owned. Routed evidence consent is persisted before forwarding; exact retries after lost -replies or a coordinator -restart reuse the same grant. Passive diagnostics describe only the local contract, not a live grant -or verified remote/native capability. Read-only completion grants revalidate their retained private -consent at creation and resolution, without reviving original input authority. -Implementation verification is recorded in docs/updates/README.md; remaining delivery and acceptance -are tracked in Progress.md. -Editable request templates are provided in examples/agent_transfer_export_review.json, -agent_transfer_import_review.json and agent_transfer_evidence_review.json, with separate create templates. +[English](README.md) | [繁體中文](README/README_zh-TW.md) | [简体中文](README/README_zh-CN.md) -Experimental source-host skill operations may select a portable grant with the existing -`handoff_id` and explicit completion/execution task. The source rechecks its actual consent, -recipient and private proof in the skill transaction, including after candidate/publication writes. -Original actions, the candidate's own validation trial and explicit version approval remain required. -New skill trials receive a fresh service-generated request key; legacy unkeyed trials are not backfilled. -Selected evidence retains the source host's actual actions, trials and versions under current authority. -Remaining cross-host acceptance and production delivery are tracked in Progress.md. -Runtime ownership is retained throughout the selected-evidence skill operation and released afterward. +AutoControl is a Python framework for automating desktop applications. Control the mouse and keyboard, capture screens, and find interface elements with images, OCR or accessibility APIs. Use it from Python, JSON action files, the desktop GUI or an MCP client. -Destination import remains experimental. An explicitly started service accepts -`review_import` / `create_import` / `get_import` / `run_import` / `cancel_import` / `list_imports` -through its runtime transfer controller and authenticated `/agent/transfer` route. A coordinator can -route these finite operations through its own opaque consent token. The destination resolves the -source using its own registry and account; coordinator principals, origins and source credentials -are not forwarded. Approval commits before dispatch, and exact lost-ACK retries retain one import. -Startup resumes accepted never-claimed work and fences unsettled claims for review. Explicit -`run_import` rechecks the original recipient, profile, live origins and source grant under a new -queue generation. Verified private chunks can be reused; an owned complete generation is inspected -and hashed without downloading or publishing again. Additional attempt origins remain restrictive. -An explicitly queued, never-claimed inspection survives another restart; current bytes, profile -and retained attempt origins are rechecked before accepting its result. -Before accepting a published import receipt, the destination rechecks the complete file list -and content digests after its final source response. Changed, missing or extra files leave -the import in requires_review, preserving user edits and the original publication for review. -Changed ownership, bytes or authority cannot confirm publication. Cancellation fences the producer; -unaccepted publication remains requires_review, and confirmed published files remain user output. -Cancelled or expired private chunk accounts are cleaned only after their exact producer retires; -failed cleanup retains capacity until a confirmed retry. Receipts keep their original fixed expiry. -Staging directories and preallocated files are journaled by filesystem identity before bytes -are copied. Expiry retries their exact cleanup after the producer retires, including after restart; -replaced or unrecognized objects retain capacity for review and are never recursively deleted. -Source maintenance retires expired or revoked private export accounts, including after restart -or issuer removal. Failed cleanup retains its reservation. Runtime ownership remains held until -source or destination cleanup finishes; idle maintenance takes no runtime writer. -Create/run replies describe the committed receipt assembled before waking new delivery work; -a later get_import reads current progress. This avoids reading that receipt behind the new writer. -A later maintenance sweep prunes already-cleaned, revoked and expired source metadata to reclaim -its record quota, preserving consent/revocation tombstones and other record families. Cold runtime -maintenance discovers pending source records through a read-only probe; unused controllers stay lazy. -Final runtime owner release is serialized with lazy controller construction and rechecks any late -controller. Active construction or cleanup keeps ownership held for a later close attempt. -Redirected private cache paths are refused before storage opens; failed cleanup retains capacity. -Subsequent maintenance also prunes expired destination import/delivery metadata and its terminal queue -rows after confirmed private cleanup. Active, rebound or unknown queue work prevents pruning; original -consent/revocation tombstones and published user files remain. Cold maintenance performs this retirement -without a listener or producer. Cleanup scans held accounts independently of retained unexpired metadata. -Portable evidence retention and shared surfaces are implemented; remaining fault acceptance and delivery -are tracked in Progress.md. -Experimental source evidence now supports review_evidence/create_evidence/get_evidence/revoke_evidence/ -list_evidence through the owning runtime and authenticated local transfer route. Separate durable -consent reuses real recovery/completion proof, current accounts and original local DAG admission. -The registered peer evidence operation matches the actual accepted key/spec and optional DAG node; -it returns only IDs, hashes and finite verification, with evidence_only=true/input_authorized=false. -Review summaries omit the node request_digest; live resolution supplies it for the exact reviewed -accepted key. Source grants do not grant ordinary task reads or input. Selected source-owned skill evidence, routed management and shared public surfaces are implemented. -Remaining fault acceptance and production delivery are tracked in Progress.md. -Experimental coordinator continuation accepts a separately reviewed live remote recovery grant for -the exact original source/key/spec/graph/node and pinned host. Approval and start persist provisional -states, resolve again outside the coordinator writer, then recheck immutable local consent and claims -before activation. Stop cancels pending states; an interrupted provisional approval requires the same -explicit request. Runtime ownership remains held during confirmation without serializing peer readers. -Dependency checks repeat around claim/record and final remote adoption acceptance. A failed grant -fences scheduling and requests bounded pause only for independently matched accepted dependents; -unknown or lost acknowledgements retain claims and require review. Completed effects and unrelated -tasks remain intact. This does not certify native input retirement or complete the full fault matrix. -Legacy delivery-schema upgrade preserves the accepted origin and fixed expiry. Additional origins -remain cumulative across resumes. Stopping an attached REST observer leaves the same service-owned -delivery and runtime owner intact; reattachment reads its result without redispatch. -Actual two-host and separate-process three-host tests independently verify bytes and account scope. -Further restart/cancellation faults, further staging faults, full retention, portable evidence, -client/GUI surfaces and complete-stage verification remain in Progress.md. A receipt grants no -task-input authority or task-completion evidence. +## Get started -Registered source management now routes review/create/get/list/revoke through a coordinator-owned -opaque review. Consent binds the actual local caller, current host fingerprint, peer review, manifest -digest and original key. Approved intent commits before forwarding; lost replies and coordinator -restart retry the same source grant. Changed actor/host/token/note/key or a different reply manifest -is refused. Pending reviews and retained route records each cap at128; expiry removes only local -route metadata while preserving consent fences. Runtime closure discards unapproved cached reviews; -durable approvals remain recoverable. The source uses its own account, and local principal/ -origin headers stay local. Destination lifecycle, source-owned skill evidence and shared surfaces are implemented; remaining -acceptance and production delivery are tracked in Progress.md. - -Existing remote DAG calls now read the actual persisted host book when pinning a host and before -and after each retained connection call. Another process replacing/removing the endpoint or token, -damaged configuration or revoked captured local authority invalidates the operation. Reads neither -initialize nor quarantine the book; local service delegation and the closed remote routes stay compatible. - -Cross-host outcome handoff remains experimental and incomplete. The runtime-owned local source core reviews -selected completed file outcomes and commits consent-bound immutable blobs with actual issuer and -recipient checks. Authenticated source management and peer-read HTTP routes now expose those reviewed -manifests/chunks. Peer reads use the receiving server's ordinary bearer/RBAC gate and rate limits; -local principal/origin headers are refused before foreign principal/store lookup. The local service -client preserves real owner delegation for management only. Transfer requests are capped at1MiB before -server reads; the bounded client refuses oversized request dispatch and success/error reply decoding -without changing ordinary HTTP limits. Destination publication, live evidence adoption and shared public surfaces are implemented. -Remaining lifecycle acceptance and production delivery are tracked in Progress.md. A transfer receipt grants no task-input authority. - -Source export excludes actual runtime/transfer databases and sidecars, current source-owner and -issuer user stores, service-owned connection files and owned evidence directories before opening -selected bytes. The service registers its actual private files; ordinary same-named outputs remain -valid. Manifest checks apply to selected outputs. Peer reads and exact retries recheck current path -authority without rehashing historical user output, and path checks retain the operation deadline. -DAG artifacts follow at most sixteen real recovery links to the original submitted task, binding -actual accepted requests and local DAG admission. The admitting actor is reauthorized, and its actual -user store is private even when distinct from the source owner. Recovery children need no fabricated -submission row; genuine standalone sources need no DAG row. A private lineage digest is rechecked at -review, creation, exact retry and peer reads. Actual private recovery ownership/reviewer bindings -also join the digest and their user stores stay private. Source operations honor cooperative -cancellation around byte access and grant writes; a committed intent remains exactly recoverable -after a cancelled reply. Artifact expiry is its completed source updated+30days; retries/restarts do -not refresh it or substitute an older ancestor deadline. Real local renewed readers use their current -private completion authority while old input remains revoked. Cross-host commit races, automatic cleanup and destination lifecycle/evidence remain open. - -Runtime owns a TransferPeer through its actual batch host adapter. Registered transfer reads pin the -persisted endpoint/credential and reread the book before and after HTTP, with current local caller -checks. Source authentication uses the receiving host's own credential; local principal/origin headers -are absent. Actual configured credential-book paths stay private without initializing or reloading the -console. Closed manifests and canonical base64 chunks require matching export IDs/hashes, at most256KiB -per chunk and a fixed deadline. The1MiB transfer wire cap also applies behind URL path prefixes; -ordinary HTTP keeps its existing limit. Invalid numeric budgets, including oversized integers, fail -with typed errors before dispatch. Remaining cross-host fault acceptance and production delivery are tracked in Progress.md. - -Idle background workers check empty work queues without reserving a database writer, reducing -contention with task status and completion transactions. A nonempty hint still requires the original -transaction to recheck and claim the work. Claim generations, stale-work recovery and retry limits -remain enforced; task and transport deadlines are unchanged. - -Lease maintenance binds expiry/revocation stops to the actual input owner and generation in the -same stop transaction. A delayed watcher cannot rewrite retired recovery evidence or cancel a newer -lease. The accepted final state and cancellation token are set before the stop becomes visible; -current revocation and the original deadlines remain enforced. - -Stopped browser tasks with confirmed effects can now use the existing completion review and -skill workflow with their actual original WebRunner context. The owned worker permanently freezes -SDK input/network before its input journal and lease release; the runtime retains at most 16 -contexts for at most 300 absolute seconds, starting before detachment. Preview/new admission probe that exact effect task's live SDK view. -The verifier borrows it for fresh bounded DOM/value reads, without configure, input ACKs, transfers -or another browser/helper. Retirement, capability probes and cleanup deny nested tools and native input. -Same-profile tasks keep separate contexts. A saved context ID grants nothing. -Private completion authorization can explicitly renew the verification scope within the original -ceiling while the original input specification stays immutable. Expired input origins grant no reads; -bounded private custody alone is not authority. Removed owners, disabled targets, changed sources, -expiry and failed reads invalidate contexts. Confirmed process reaping is required to free ownership; -failed cleanup stays tracked. Restart cannot restore a page. Network-retired DOM is not new server data. -Existing Python/AC/MCP/REST/CLI/Builder and GUI Actions share the same review requests. Skill recording -keeps original actions; publication requires its own actual validation trial and selected completion. -See `examples/agent_browser_retained_completion.py`. Cold browser-prefix reconstruction, remote -readers, production deployment and deferred native/browser/device/24-hour acceptance remain open. - -Stopped tasks with confirmed effects can use `manage_agent_recovery("preview_completion", {"task_id": id})` -to review a separate verification task. Call `create_completion` with the exact task_id/snapshot and a -review note, then finish the returned task. A private atomic binding selects a permanently read-only -helper; source actions never replay and fresh independent criteria plus input retirement prove success. -Skill plans must be fully confirmed; dynamic tasks must have no dormant finite plan or unknown effects. -Observe may precede finish: identical helper configuration reruns readiness without replacing its authority. -Source/reviewer authority stays live, including after helper cleanup and across explicit retries/restarts. -Existing API/AC/MCP/REST/CLI/Builder and GUI Actions share the workflow. Remote readers and -production deployment remain in Progress.md; desktop capability still requires separate native evidence. - -Managed-only DAGs can register a durable whole-graph batch with -`manage_agent_dag("register", {"definition": graph, "max_parallel": 4})`, then explicitly call -`run_dag(graph, batch_id=batch["batch_id"])`. Registration performs no target operation. The stored -graph pins topology, node contracts, host configuration and parallelism; destination keys/spec tags -bind each node to that batch. A claim commits before possible delivery, and exact destination spec / -completion / input-retirement evidence gates dependants. Repeated begin is refused after success, -interruption or a lost submit reply. `get/list/inspect` retain coordination identity across restart. -Use API/AC/MCP/REST/CLI/Builder or the DAG Actions batch register/read controls and optional batch ID. -For a stopped batch, `review_continuation` returns a read-only whole-graph snapshot and explicit node -decisions. Pass its reviewed `snapshot`, `decisions` and a nonempty `note` through -`run_dag(graph, batch_id=id, recovery=request)` to approve and consume one continuation attempt. -Only independently completed originals or genuine completed recovery successors can be adopted; -dispatch requires a never-claimed pending node with no accepted destination request. Local authority -can be renewed within equal/narrower roots. Unknown claims are never replayed. DAG Actions exposes -fencing, review and explicit continuation; fencing stops new dispatch and leaves accepted tasks under -their own lifecycle. To delegate coordination to an explicitly started service, call -`manage_agent_dag("run_background", {"batch_id": id, "definition": graph, "max_parallel": 4})`. -Add `approval_id` for an explicitly approved continuation. DAG Actions exposes both background actions; -closing the view leaves accepted service work alive. `get.background` reports bounded queue state. -Restart fences old attempts and requires review, without replaying queued or unknown deliveries. -Both original owner and submitting actor remain live checks; local tasks use their owning runtime. -The existing `prune_agent_tasks()` and hourly maintenance also collect expired unused registrations -and settled successful batches (30 days by default). Unresolved batches retain task/recovery evidence -and admission gates. Results add `deleted_batches` and `deleted_dag_deliveries`; foreign queues and -user outputs remain untouched. Remote evidence retention still requires an explicit handoff contract. -Caller-coordinated bound runs pin the local service path, endpoint, credential fingerprint and generation. -All local node calls reuse that client; replaced metadata stops future calls and requires explicit review. -Server-side batch evidence reads its owning runtime directly. No bearer credential is cached by binding. -Ordinary non-batch clients retain adaptive discovery; bound batches require generation-bearing metadata. -Local batch nodes now use the source service's closed `local_task` transport after a durable claim. -The exact spec/key is admitted as the original owner, with the real caller recorded atomically. Runtime -checks refresh both identities and the live attempt before input; losing admin authority over another -owner's work also blocks execution. Existing requests without this trusted admission are never backfilled. -Task metadata exposes bounded `local_dag_admission` audit data; accepted input retains its cleanup contract. -For a reviewed recovery successor that must remain readable to its original owner, pass -`owner_policy="source_owner"` to recovery preview/review_authorization, then carry its -`ownership.review` as `ownership_review` into explicit create/create_authorized. The child retains the -source owner and records the real reviewer atomically; both identities remain live input checks. -The recovery GUI offers this owner selection. Omitted policy keeps caller ownership and ordinary read -isolation. DAGs can adopt an independently completed source-owned child through normal recovery evidence. -Existing caller-owned children are not automatically transferred or backfilled into this policy. -See [the continuation protocol](docs/source/Eng/doc/ai_agents/agent_dag_batches_doc.rst). - -Triggers can explicitly use `manage_agent_trigger("review_authorization", {"trigger_id":"..."})`, -then `create_authorized` with `trigger_id`, `snapshot`, `authorization_review`, reviewed `spec` and `note`. -The new registration preserves its full template/config/pending limit within original/live/current -authority, retires the old binding atomically and enables future notifications. Shared lineage history -keeps accepted keys and outstanding tasks across renewal, removal and restart; inherited queued events -are never redispatched. Schedule windows restart in the future and file checkpoints remain. API/AC/MCP/ -REST/CLI/Builder and the GUI trigger selector share this explicit flow; ordinary enable cannot replace -expired authority. Review only prepares a request with a blank note. - -Published skills can use `manage_agent_skill("review_authorization", {"candidate_id":"..."})`, -then explicit `create_authorized` with `candidate_id`, `snapshot`, `authorization_review`, reviewed -`spec` and `note`. Renewal preserves the whole plan/parameter schema and source root ceiling, retaining -live restrictions and intersecting current authority. It creates an audited draft in the same skill -lineage; fresh validation and explicit next-version publication are required. Old versions remain -unchanged. Identical approval deduplicates; stale versions/context fail. API/AC/MCP/REST/CLI/Builder and -the GUI Skills operation selector share this flow. Trigger renewal uses the separate flow above. - -Stopped tasks with retired origin authority can explicitly use `review_authorization`, then -`create_authorized` with `task_id`, `snapshot`, reviewed `spec`, `note` and `authorization_review`. -The successor retains every live source restriction and intersects current authority with the original -root ceiling; roots may only stay equal or shrink. Other permissions, mode/model, budgets and completion -conditions stay fixed. Approval is audited atomically with the unique successor; the source and its -revoked witnesses stay unchanged. All recovery surfaces include these operations, with separate GUI -Actions for authorization review and creation. See the [recovery guide](docs/source/Eng/doc/ai_agents/agent_recovery_doc.rst). -Task recovery does not clear input quarantine or restore application state; skills and triggers use their separate renewal flows above. - -Stopped tasks can use `manage_agent_recovery("preview", {"task_id": "..."})` to review source -receipts and a source snapshot without touching an application. Finite skills expose remaining actions -and row outcomes. External-agent and local-model tasks provide `review_template` with a blank goal; -operators must explicitly supply a remaining-work goal, with no copied action list. Explicit `create` approval -supplies the snapshot, reviewed spec and note, creating one linked successor with fresh observations -and receipts. Repeated approval returns that task. Execution mode, model/endpoint, scope, budgets and -completion conditions stay fixed, and unknown effects require reconciliation. Old captures, indexes, -coordinates and completed history are not transplanted. Use `AC_agent_task_recovery`, MCP/REST, -`agent-task recovery preview|create request.json` or Agent tasks → Actions → Review remaining work / -replan / Create reviewed successor task. Delegated sources cannot resume; continue from the successor. -Login and window-state restoration is declared, never inferred: a successor (or any task) may list -`resume_conditions` — `screen`, `browser` or `file_*` clauses only, since receipts are history — and its -first action is admitted only on a fresh observation that passes all of them. A failed or unknown -condition puts the task in `waiting_user` instead of acting; once any action receipt exists the gate is spent. - -Built-in Android/iOS managed profiles remain unavailable. Their internal remote-effect guard records -before/after acknowledgements against a physical-device identity and retains quarantine when a local -helper exits with an unconfirmed effect. Recovery requires a trusted device proof after writer retirement -and a later epoch invalidating old commands. No built-in SDK proof, device profile or native acceptance -is implied; remaining integration is in `Progress.md`. -The internal Android transport connects only to an explicit existing loopback ADB server, with no CLI, -daemon management, retry or legacy-shell fallback. Shell-v2 exit evidence has bounded framing/output; -it does not establish app completion, physical-device identity or input retirement. -Internal Android sessions now inspect an exact endpoint, validate physical serial/boot/default-display -focus and pin one boot atomically. Finite input proposals recheck identity and focus on the selected -command connection, with literal bounded text and fixed results. Proposals grant no input authority; -input-window, occlusion, lock/presence and owned-worker integration remain required. -Android checked proposals now bind current native input-window/queue and keyguard evidence. Pointer -checks cover entire half-open touch-region paths and foreign interception/overlays; hashes are rechecked -on the command connection. Old ANR/history cannot certify current state. Human presence and global-monitor -review still require trusted providers; built-in managed device execution remains unavailable. -Internal Android action protocol v2 distinguishes complete pre-input refusal from input failure, -post-input refusal and returned input. Missing/malformed phases or mismatched shell exits remain unknown; -even returned input does not certify remote input retirement or task completion. No retry is authorized. -The internal owned remote SDK worker now checks exact task/owner scope, refreshed authority and physical -takeover; parent monitoring starts before the trusted host factory. Calls require a durable begin ACK, -then matching device/epoch settlement before an end ACK. Missing proof keeps effects quarantined. -Trusted device-control providers, the WDA adapter and managed profile wiring remain required. -The command compiler reads the three native focus fields in one labeled extraction, accepting their -six possible orders while refusing missing/duplicate/empty fields. Pre/post identity and input-security -checks remain, and action deadlines are unchanged. Owned POSIX fixtures avoid extra Git Bash reader -processes without changing file bytes; bounded phase/timing diagnostics exclude commands and output. -Internal AndroidRemoteAdapter now connects checked sessions to this worker through explicit per-command -AndroidCommandLease grants. A fresh identity/routing/security observation is consumed per action; the SDK -recompiles the finite command before sending it once over ADB. Device fencing must suppress old writes -after physical takeover, cancellation or expiry. No default provider exists: standard ADB and killing -the local helper cannot supply that guarantee. Settlement additionally binds one random request ID and -boot to independent input/queue proof. An optional explicit host hierarchy_reader supplies bounded -app-only semantic elements and reviewed non-sensitive text; without it observations remain metadata-only. -XML cannot grant text access; editable/password values and protected descendants stay masked. Raw XML -and private freshness hashes are never published; random observation revisions change after actions and -source changes. Android element references require a current actionable semantic element. Fresh screen -readback can confirm a reviewed positive label; missing/partial/masked content cannot prove text absent. -No CLI/SDK startup or capture fallback is added. Real capture/control providers, protected field-value -verification, Unicode/IME and managed profile delivery remain open. - -Managed screen completion now treats built-in desktop and WebRunner previews as partial text evidence. -File targets and desktop window bootstrap supply no semantic screen evidence. Known safe labels can -confirm presence or contradict absence; masked and explicitly hidden labels cannot. Combined conditions -remain unknown if any required evidence is missing, or fail on a known contradiction. Use explicit -browser completion reads for exact DOM/value checks. Custom targets without coverage flags keep legacy behavior. - -`lookup_agent_task("key", reviewed_spec)` optionally compares the destination-normalized specification -with the immutable digest stored for the original owner's request. The response advertises -`spec_match_contract=1` and reports `spec_match=matches|differs|unverifiable|not_found` when a spec is supplied. -CLI lookup accepts `--spec reviewed.json`; AC/MCP/REST/Builder share the optional object. Inspection first -queries the key, then compares the reviewed node spec only when the destination advertises the exact -contract. Old destinations stay `unverified`; local origin witnesses are never sent to remote matching. -Changed request identity invalidates the earlier snapshot. Matched nodes also require the exact count, -kinds and passed status of independent criterion reports before confirming recorded completion. -`request_match` binds the node's task spec; -DAG topology/batch approval and continuation remain separate, with `resume_permitted=false`. - -`inspect_agent_dag(definition, timeout_seconds=30)` looks up existing local/registered-host requests -without submitting, pausing or resuming tasks. Use `AC_agent_dag_inspect`, MCP `ac_agent_dag_inspect`, -REST action execution, CLI `agent-task inspect-dag reviewed.json`, Script Builder or DAG Actions. -At most 100 nodes and a 300-second maximum budget bound inspection. Remote lookup needs host-management -authority; local principal/store/origin metadata stays local. Results omit remote paths and raw errors. -`recorded_completion` describes the found task only. Node-spec matching is optional; `resume_permitted=false` -explicitly leaves graph/batch approval and continuation unapproved. A missing record -does not prove rejection. GUI inspection is read-only and discards results after graph edits. - -Use `lookup_agent_task("original-key")` (`AC_agent_task_lookup`, MCP `ac_agent_task_lookup`, -`POST /agent/lookup`, CLI `agent-task lookup original-key`, or the task view's Actions menu) to inspect -a submission whose reply was lost. It reads only the original principal/store namespace and never -submits, resumes or acquires input. `found=false` is a current snapshot; a late request may still arrive. -GUI lookup results cannot replace a task/key selected while the request was pending. DAG inspection -shares this lookup; specification-bound recovery approval remains separate work. The query requires task access. - -Existing `run_dag` / `AC_run_dag` / MCP `ac_run_dag`, REST action execution, CLI action files, -Script Builder and the DAG Actions menu accept nodes with a `task` payload instead of actions: - -DAG types and functions are also exported from `je_auto_control.api` and `je_auto_control.api.core`. - -```python -run_dag({"nodes": [{"id": "collect", "host": "reviewed-host", "task": { - "spec": reviewed_spec, "idempotency_key": "batch-20261024-collect", "wait_seconds": 300}}]}) -``` - -`reviewed_spec` must use skill or an explicitly configured local-model mode, with tools, destination -roots and completion criteria. The host must already expose an authenticated agent runtime with -background dispatch; this does not deploy listeners. Omit `host` for the explicit local service. -The destination validates scope and coordinates resource ownership. Nodes submit once, poll bounded -status and advance only with matching passed criteria, durable completion contract 1 and confirmed input -retirement. Keys are required and must stay stable when recovering the same reviewed batch; rerunning -does not resume paused tasks or replay effects. Stop, timeout or transport/authority failure requests -bounded pause when the task ID is known. A lost acknowledgement stays uncertain; failed nodes retain -the task ID/key and block dependants. The GUI displays retained task IDs. Remote credentials come from -the administrator's registered host; local principal/store paths and origin witnesses stay local. -Production multi-host setup and native/device acceptance remain separately tracked. - -Managed HTTP pause/cancel/stop-all/shutdown requests have a separate per-IP reserve with the same -120-per-minute rate and 30-request burst as ordinary traffic, so polling cannot exhaust stop admission. -Authentication, live roles, task ownership, audit and bounded input retirement still apply. The shared -client also reserves transport capacity for DAG batch/node pauses; its control marker admits only closed -pause requests on `/agent/dag`. Other marked DAG operations fail before dispatch. Custom auth gates -retain their own admission contract. This does not guarantee priority over a saturated OS/network. - -Managed task success is published after input cleanup is confirmed. If cleanup fails or remains busy, -the task requires review and keeps its input lease; a crash before confirmation remains recoverable. -Completion uses conditional state transitions so concurrent cancellation retains priority. Status and -the existing GUI/API task results expose `metadata.input_released` and durable `completion_contract=1` -for newly confirmed success (legacy records retain zero); final artifacts reflect the settled -state. This supplies local retirement evidence for subsequent DAG coordination. - -DAG nodes retain the caller's authorization, cancellation and command ceilings on pool threads, -including custom runners. Each node refreshes store-backed users before execution; removed users fail -that node and dependent nodes are skipped. Individual operations check the refreshed role. Default -remote nodes require `manage_hosts` before opening the host address book or action files, because -registered host credentials may grant more access than local action permissions. Trusted local Python -and administrators retain remote dispatch. Managed task nodes add the closed lifecycle described above; -production multi-host deployment and native acceptance remain separate work. - -Browser host profiles can select a reviewed installed Python environment through optional -`settings.helper_python` (an absolute local interpreter path). Explicit helpers run with `-I`, using -installed packages rather than the caller's `PYTHONPATH` or working directory. Virtualenv executable -symlinks retain their environment identity. Task options cannot select the interpreter. -Host managers can call `manage_agent_target("probe", {"name":"reviewed-browser"})` or use -`AC_agent_target`, MCP/REST, `agent-task target probe request.json` and the GUI Host targets operation. -The probe uses a separate bounded owned helper, imports browser dependencies through `je_web_runner`, -then retires it without acquiring input ownership or starting a browser. Its result can say -`python_dependencies_ready`; `browser_launch=not_probed` and `native_evidence=not_recorded` stay explicit. -`last_probe` is an in-memory timestamped diagnostic snapshot; passive readiness and task permissions -are unchanged by probing. Disabled targets stay disabled. Desktop/device native probes remain open. -The prepared isolated environment installs wheels from both feature worktrees. Shared environments -and production checkouts remain untouched; production service configuration and real-browser acceptance -remain separate work. Browser automation still belongs entirely to WebRunner (`je_web_runner`). - -Desktop finite skills now use the same context-continuity fence as browser skills. Retiring a -desktop scope or its owned helper requires review before an old prefix can continue; paused form/window -state is not established by historical receipts. Live uninterrupted contexts continue normally. File -adapters retain their persistent-artifact recovery. Target checks run before helper replacement, and -existing resume/status/receipt interfaces expose the human-review result. Draft/authentication/window -state restoration and reviewed remaining-step reconstruction remain open; native acceptance stays paused. - -A finite browser skill's verified prefix now requires its original live browser/helper context. -After pause, cleanup, helper loss or runtime restart, retained action history cannot prove that the -form still contains its previous values. Continuation enters human review before launching a replacement -helper or sending the next action. Review the remaining steps and create a new task explicitly. -Pausing before any retained attempt and attempts reviewed as failed/not-applied permit a fresh start. -External owners can reobserve a new context and plan fresh scoped actions; ordinary uninterrupted skills -continue on their existing session. Restoring authenticated/draft browser state remains open work. - -Local runtime principal and live-root forwarding now requires an explicit local-service call. -Generic authenticated HTTP requests carry the supplied bearer token; local user/store/witness metadata -is attached only by the runtime client after validating the loopback service destination and route. -The versioned `je_auto_control.api` namespace exposes every advertised `api.core` name, including -managed browser commands, target recovery and skills. Executor typing stubs include all shipped commands; -unresolved postponed project types use the generator's existing `Any` fallback instead of invalid names. -Concurrent budget readers sample clocks inside the exclusive database transaction, preventing false -task timeouts when readers acquire locks in a different order. Actual clock rollback remains fail-closed. -GUI/MCP/REST/CLI share these repaired client and API contracts. Production checkouts and existing -native/browser/device/24-hour acceptance pauses remain unchanged. - -Managed browser file commands `browser_link`, `browser_download` and `browser_upload` (with matching -`AC_browser_*` commands) delegate to WebRunner transfer contract version 1. Download and upload grants -require explicit host/task roots. Downloads preserve scoped browser cookies inside the owned SDK/helper, -check complete length and optional SHA256, and publish without overwriting an existing file; reuse -requires its matching SHA256. Uploads read one regular file up to 4 MiB into a checked immutable snapshot, -verify optional SHA256 and SDK metadata, and never submit a form. Network operations remain in `je_web_runner`. -The browser `download_archive` preview accepts a query `url`, explicit `allowed_origins`, rooted `directory` -and `files` with a plain `name` and either `url` or link `selector`/optional `frame`; `page_url` can override -the query page per file. It captures fresh links, downloads at most 16 MiB per file and writes a manifest -whose names/sizes/hashes are independently verified. GUI Actions draft file target/workflow/upload examples -without starting resources. MCP/REST/CLI/Builder/model tools share these commands; link reads still require -drive-input authority. Deployment and real-browser acceptance remain open; existing acceptance pauses hold. - -Browser tasks accept pinned completion clauses such as -`{"kind":"browser","operation":"value","selector":"#field","value":"expected"}`. -Operations are exact `text`, `value`, `visible` (boolean), or `url` (no locator). They require an explicit -`AC_browser_read` grant and task origins; completion cannot add permissions. At finish, the same owned -helper checks a current allowed HTTP(S) page and independently reads the full SDK value through guarded -read commands. Receipts, bounded previews and model stop messages do not substitute for those reads. -Blank/unavailable/out-of-scope pages, refused readbacks and invalid verifier replies remain unknown; -failed comparisons remain failed. Cancellation, authority revocation and human-review errors propagate. -GUI Actions can draft an inert browser completion example; API/MCP/REST/CLI finish share the verifier. -SPA URL fragments remain intact while origin checks exclude only the fragment. Browser/native -application acceptance and reviewed transfers remain open. - -Managed browser startup now requires the exact WebRunner `ManagedBrowserSession.contract_version == 1` -contract before constructing its policy or opening a proxy/browser. Missing, boolean, string, older or -unknown markers fail with an actionable readiness reason. SDK source `575e5d2` provides complete text/value -readback: at most 8,000 UTF-16 code units, with over-limit/invalid Unicode refusal instead of truncation. -AutoControl applies matching Unicode bounds to browser arguments and workflow preview data before effects. -The consumer/SDK source contract is tested through the real owned helper with fake Chromium; deployment -and real-browser/native acceptance remain separate from that evidence. - - -`draft_agent_workflow("batch_form", config)` and `transfer` accept `backend: browser` with -explicit `allowed_origins` and a reviewed browser target. CSV/XLSX sources stay rooted; browser drafts -emit only `AC_browser_*` actions and never fall back to desktop input. Forms take `url`, CSS `fields`, -optional frame selectors/new-record control, and submit plus confirmation selectors. Each fill has an -independent exact value readback. Optional `confirmation_column` supplies a per-row expected marker. -Transfers take `source_url`/`destination_url`, capture text/value fields, apply an allowlisted transform, -fill and read back destination fields, then verify saving. A stale confirmation is refused before submit. -`AC_browser_wait` / `browser_wait` polls text/value reads only, including a newly visible element; -`wait_seconds` defaults to 5, is capped by the action budget, and late matching replies are refused. -It never repeats a fill or click. Python/core, catalog/model schemas, MCP, CLI/REST task operations, -Builder and GUI workflow preview use the shared compiler. Browser readback can serve as independent -skill evidence. Actual application acceptance and production upload/download configuration remain open. -Managed browser startup requires WebRunner contract version 1 with complete bounded readback. - -Managed browser profiles (`kind: browser`) now delegate to the owned `je_web_runner` SDK from -WebRunner (`D:\Codes\WebRunner`; integration source on its isolated managed-session branch). -Profiles require exact `settings.allowed_origins`, browser-only tools and no desktop apps; every task -also declares a narrower nonempty `options.allowed_origins`. Profile/task grants are checked again on -activation. Registration stays inert. Install the reviewed managed-session SDK and its Chromium runtime -in the helper environment explicitly; absent dependencies fail readiness and nothing is installed automatically. -`AC_browser_navigate`, `AC_browser_click`, `AC_browser_fill`, `AC_browser_select`, `AC_browser_check` -and `AC_browser_read` share Python/core, executor, MCP and Builder schemas. They operate inside the -managed helper; drive them through the existing task submit/observe/act lifecycle, not an ambient browser. -The read operation is `text`, `value` or `visible`; secret form controls are refused by WebRunner. -Observation-local DOM indexes resolve selectors and frames after the runtime's freshness check. -Failed effects remain uncertain and require reconciliation; pause/cancel retire owned resources. -GUI Actions can draft a browser target example for review, and DOM selection only edits the action request. -The dedicated helper preserves one fresh session across readiness checks. Ordinary cleanup acknowledges -browser cleanup and reaps its owned process tree; eligible completion sources instead transfer their -actual frozen context to the bounded runtime collection. Browser tasks acquire no desktop input ownership. -Controlled cross-source tests use the real SDK with fake Chromium and owned IPC/loopback. Browser/native -acceptance, production transfer configuration and additional browser workflow kinds remain tracked in `Progress.md`. - -MCP asynchronous calls preserve the accepting caller's role, session, exact root policy and -disclosure view; retired sessions and path policies reject late dispatch. Stateless async calls keep -their fixed profile. HTTP tool-list changes reach all live session streams for plugin updates, while -session enable/disable targets one owner and avoids duplicate delivery. Stream registration and HTTP -headers share one lock so an early notification cannot precede the response headers. -The metadata-only `benchmarks/mcp_discovery.py --repeats 20` benchmark records count, JSON bytes, -warm in-process handshake, search and enable latency. The captured Windows/Python 3.14.4 run has -732 permitted tools / 358,029 initial response bytes in full mode and 5 / 2,029 in progressive mode -(99.43% fewer response bytes). Handshake is 58.263 / 47.439 ms; search median is 16.243 / 19.718 ms. -Progressive enable median is 42.486 ms. These local timings exclude cold imports and native work. -See the dated JSON report under `docs/benchmarks/`; argument-policy coverage limits remain in `Progress.md`. - -MCP supports opt-in session disclosure: `je_auto_control_mcp --tool-mode progressive` starts -with five discovery controls; `ac_mcp_tools_enable` / `ac_mcp_tools_disable` change only that session. -`--tool-mode static --tool-profile ac_screen_size,ac_list_windows` supplies a fixed profile for clients -that do not refresh tool lists. The default `full` mode retains its unpaginated permitted list. -Progressive/static pages use opaque, single-use cursors bound to a snapshot and caller; changed tools, -roles, view configuration or expired cursors require restarting `tools/list`. Enable/disable notify -the owning connection. Session closure retires outstanding metadata callbacks and clears cursors. -Use `MCPServer.configure_tool_disclosure(...)` for HTTP/embedded servers, or host environment -`JE_AUTOCONTROL_MCP_DISCLOSURE` and comma-separated `JE_AUTOCONTROL_MCP_TOOL_PROFILE`. -`plan_mcp_tool_profile(...)` and Diagnostics Actions preview startup arguments without starting a server. -Stateless requests use a fixed, unpaginated initial profile; they do not retain session enablement. -Read-only ceilings cover later plugin registrations. Unauthenticated/shared-token peers see operator -tools, matching their existing invocation ceiling; host-management tools require authenticated authority. - -MCP tool discovery is available through `search_mcp_tools(query, limit=10)` and -`get_mcp_tool_schema(name)`, corresponding AC/MCP commands, and Diagnostics → Actions. -Search returns bounded summaries with category and required capability; full schemas require a -single-tool lookup. Both queries refresh role authority and respect the registry's read-only filter. -MCP queries use that server's live registry, including plugin changes. CLI inspection: -`je_auto_control_mcp --search-tools document --limit 5` or `--tool-schema ac_mcp_tool_search`. -Full mode remains the default; opt-in session disclosure is described alongside this metadata API. - -Agent tool calls use `executor.execute_one(name, arguments)`, returning the raw result through -the same authorization, variable interpolation, cancellation and journal boundaries as action scripts. -Private executor arguments are rejected. Managed task delivery is tracked in `Progress.md`. - -Crash-safe input ownership uses a durable resource witness before dispatch/input ACK. After host death, explicitly review and recover the target with `recover_agent_target(target, note)` (host management), after manually releasing held input; task receipts still require separate reconciliation. Workspace document handoff runs outside the disposable input helper, and approved focus steps wait for the scoped application window. - -Managed skills record verified semantic flows into immutable candidates. `manage_agent_skill` previews typed parameters, runs a separate validation task, and publishes a numbered version only after explicit review of that candidate's verified success. Repairs are new selector candidates with fresh validation; tasks pin their version and digest. AC/MCP/REST/CLI and the Agent Tasks Actions menu share these operations. - -For an interrupted validation trial whose actions are all confirmed, explicitly review/create and -finish a separate read-only completion task, then call `manage_agent_skill("accept", {...})` with the -original `task_id` and optional `completion_task_id`. Publication retains the exact candidate/trial -hash/pin, up to sixteen real read-only recovery links, fresh authority and independently verified -retirement. The original stays stopped; its actions are not replayed. The Actions menu can prepare -the request for review. Publication keeps historical completion IDs/hashes after transient reader -evidence expires; unpublished adoption still needs retained evidence. - -`manage_agent_skill("record", request)` also accepts `completion_task_id` for a stopped original -workflow. Keep `task_id` equal to that workflow: its confirmed semantic actions become a draft, -while the separate reader supplies private, independently verified completion evidence. Recording -does not replay actions or change the source state. Source/proof checks and draft insertion share -one transaction with live authority rechecks. Historical `provenance.completion_review` survives -reader retention without granting current authority. The draft, including added validation criteria, -still needs its own new exact validation trial before publication. The Actions menu prepares the -record request without executing it. - -For a partially executed validation trial, first call `manage_agent_skill("review_execution", request)` -with `candidate_id`, the original `task_id` and a separate final `execution_task_id`. Then explicitly -`accept` those same IDs with the returned `execution_review`, `expected_version` and a nonempty `note`. -At most sixteen actual executable recovery links must confirm the complete original semantic plan; -a successful different remainder is insufficient. Comparison includes JSON types, captured values, -expectations and grounding, without restoring captures or rebuilding historical UI state. Each task -retains its existing limits and separate approval. Current callers, all owners and actual admission -reviewers must remain authorized. Version, publication and historical `publication.execution_review` -commit atomically, with post-write evidence/authority checks. The original stays stopped and retains -`publication.task_id`; no recovery child becomes a fabricated validation trial. An optional -`completion_task_id` must verify the final executable effect and is nested in this execution audit. -Expired evidence cannot approve an unpublished candidate. Two Actions examples prepare review and -accept requests without executing them; `agent_skill_execution_review.json` and -`agent_skill_execution_accept.json` are editable request examples. - -Managed tasks retain live origin path ceilings: removing a source root blocks later actions, trigger fires and skill trials. MCP client roots are isolated per session; retiring that client authority revokes its ceilings. Static host policy remains valid until explicitly replaced. Worker shutdown cancels actual running work, including model initialization before input acquisition, while unstarted deliveries remain durable. - -Experimental [managed agent tasks](docs/AGENT_TASKS.md) provide owner-scoped submit/observe/act/verify, -pause/resume/cancel, fenced target control, durable action receipts, WorkQueue delivery, local Ollama -inference and a background service shared by Python, AC, MCP, REST, CLI and the Agent Tasks view. -Start explicitly with `je_auto_control agent-task start`; new flows have no mandatory external service. -Four reviewable templates cover download/archive, CSV/XLSX forms, cross-app transfer and workspace -preparation. Use `agent-task draft` or Actions → Preview workflow before submitting. -Durable interval/cron/file/event bindings capture approved task scopes, reauthorize each fire and -deduplicate notifications. Submission keys prevent duplicate tasks across retries and restart. -Owner-scoped receipts and explicit uncertain-outcome review link to run history, journals and task -reports. Generated cache expires after 30 days; user outputs and external journals are preserved. -Evidence caches bind the complete database path and a persistent database identity under -`.agent-evidence-cache/`. Restored databases and legacy caches retain their original history references; -the next action or report starts a new owned journal segment without reading or moving historical files. -Task metadata reports `artifact_cache_state` as `owned` or `historical`. Retention removes only the current -database's recognized cache files; historical files remain, and retained private roots cannot be exported. - -On Linux, helper processes can run under the optional [owner service](native/owner_service/README.md). -A root guardian runs each helper in its own cgroup v2 tree, which the helper's account cannot leave. -Closing the channel kills the whole tree, escaped descendants included, and a restarted guardian -recovers after a crash. A root-owned `/etc/je_auto_control/owner_service.json` binding routes -exactly listed helper argv through it. Helpers that drive your desktop or browser always run as -local processes, because a protected helper runs as its own ID with an empty environment and -cannot reach your display. Without that binding, helpers keep running as local -processes, and `agent-task status` reports the mode under `helper_containment`. The Python -package never builds, installs or starts the service, and its builds refuse protected launches -until a reviewed release opens the gate. - -`agent-task readiness` (`agent_runtime_readiness`, `AC_agent_runtime_readiness`, the MCP tool and the -Agent Tasks view's Actions menu) reports, for the desktop input and capture, the human-presence source, -Android and iOS control, the browser and the local model, one of `unsupported`, `missing_dependency`, -`unauthorized`, `not_probed`, `not_recorded` or `measured`. It reads only the environment, `PATH` and -installed packages: it contacts no device, launches no helper and asks for no permission, so it never -reports `measured` and every area carries `native_evidence: not_recorded`. An installed tool is -`not_probed`, not ready. - -Before deployment or rollback, compare exact source and artifact hashes; the unchanged version number alone does -not identify private-cache compatibility. A runtime without this private-root protection must not reuse the -newer database/cache. A reviewed restore must use matching pre-upgrade state at its recorded locations, retire -owned input first, and exclude retained newer private files from every legacy task root. Preserve uncertain -journals and avoid replay. Keep the compatible runtime if these conditions cannot be established. - -Windows USB enumeration emits and decodes UTF-8 explicitly and keeps its PowerShell process hidden. -Unicode device names and diagnostics are preserved in both Python UTF-8 modes; enumeration remains read-only. -Native calls use an owned helper with cancellation/deadlines, recorded input cleanup and per-session -exclusion across runtime databases. Windows shared-desktop tasks share a persistent session source across -runtime/task/helper lifetimes and wait for sixty seconds of fresh unlocked inactivity after monitoring starts. -Only an active supported local console can acquire input; remote, shadowed and unknown sessions fail closed. -Each helper freshly checks its fixed host lease before and after input ACK. Source/reader loss pauses input; -unconfirmed held-input cleanup stays fenced for explicit retry. Closing one runtime preserves another's source. -Target descriptions expose coarse `presence` metadata with `native_evidence=not_recorded` and start no probes. -`agent-task stop-all` stops visible tasks. Other shared desktops require a trusted activity adapter. -Native acceptance and the remaining workflows are in `Progress.md`. - -Linux's internal presence_peer_linux retains a noninheritable pidfd for the original connected -Unix stream or sequenced-packet peer. It checks account, birth, namespaces and liveness without -reopening a PID. This process identity does not establish desktop or input authority. - -The internal LinuxListener and LinuxChannel transport owns its protected Unix endpoint, socket -and peer. Each bounded JSON packet requires the live original writer's kernel credentials and -pidfd. Extra, missing, negative or truncated descriptor controls are refused; received descriptors -retire before delivery. Admission and I/O share one deadline. Cancellation revokes delivery, and -unfinished or failed cleanup stays unconfirmed. Unknown filesystem objects remain untouched. -Pathname permissions do not isolate hostile processes sharing a UID. Bounded userspace waits -do not promise hard realtime kernel syscall completion. - -Physical-activity sources now exist for X11 and macOS. X11 counts XInput2 raw events from real -devices, never from XTEST slaves, and reads `Active`/`LockedHint` from logind: without logind or -`XDG_SESSION_ID` the seat counts as locked. macOS uses a listen-only session event tap (it needs the -Accessibility permission). An event counts as injected only when a process posted it from a non-HID -source state, so a doubt keeps a task waiting rather than letting it take over. Wayland has no -trusted source. On Linux the presence broker, worker and server now run over this transport: the owned -worker binds a fresh private endpoint and reports it in its bootstrap reply, the broker adopts only that -endpoint, and connecting pins the listener to the process it names before the presence challenge. macOS has -no presence transport yet, and the runtime still refuses non-Windows shared desktop tasks until native -acceptance. This transport is not full Linux application or native input acceptance. - -[![PyPI](https://img.shields.io/pypi/v/je_auto_control)](https://pypi.org/project/je_auto_control/) -[![Python](https://img.shields.io/pypi/pyversions/je_auto_control)](https://pypi.org/project/je_auto_control/) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) -[![Documentation](https://readthedocs.org/projects/autocontrol/badge/?version=latest)](https://autocontrol.readthedocs.io/en/latest/?badge=latest) - -**AutoControl** is an open-source, cross-platform **computer-use and GUI automation framework** for AI agents, Python applications, and automated testing. It drives the mouse and keyboard, finds UI targets through template matching, OCR, the OS accessibility tree, or a vision model, records and replays flows, and runs deterministic JSON actions across Windows, macOS, Linux (X11 and Wayland), the BSDs, Android, and iOS. - -Every capability ships three ways: a **Python API**, an **`AC_*` action command** usable -from JSON files / CLI / servers, and a **GUI tab**. Nothing is GUI-only. - -**[繁體中文](README/README_zh-TW.md)** · **[简体中文](README/README_zh-CN.md)** - ---- - -## Why AutoControl - -- **One API, seven platforms.** `wrapper/platform_wrapper.py` picks the backend at import - time; your script does not change between Windows, macOS, X11, and Wayland. -- **Scriptable without Python.** 911 `AC_*` commands cover the whole feature set, so a - JSON file can do anything the library can — including loops, branches, try/catch, - macros, and variables. -- **Headless by default.** `import je_auto_control` never loads Qt. The GUI is an - optional extra that wraps the same headless core. - Public exports load their source modules when requested. `__all__` and `dir()` list names - without loading every feature; wildcard import requests them all. Unresolved names are absent - from `vars(je_auto_control)`. - On X11, plain package import opens no display or input device and starts no keyboard listener. - Desktop operations acquire resources when called. Reading `keyboard_keys_table` or calling - `get_keyboard_keys_table()` resolves actual server keycodes and requires an X connection. -- **Locate things four ways.** Template matching, OCR, the accessibility tree, and a - vision-language model — composable through anchor locators and self-healing fallbacks. -- **Light dependency floor.** The REST server, JSON Schema validator, JWT, TOTP, - WebSocket framing, ACME client, USB/IP protocol, and Prometheus metrics are all - standard-library implementations. Heavy things are opt-in extras. - - -## AI agents and computer use - -**AutoControl is an open-source, cross-platform computer-use and GUI automation framework for AI agents.** - -Use it when an agent needs to operate a real desktop GUI — native applications, real browser windows, remote desktops, or mobile devices — rather than only a browser DOM/API. - -### When an AI agent should choose AutoControl - -- Real mouse and keyboard input -- Screenshots and screen-coordinate interaction -- OCR and native accessibility-tree discovery -- Image/template matching -- Vision-language-model UI localization -- Anchor and self-healing locators -- Cross-platform desktop/mobile automation -- Deterministic JSON action files -- MCP-based computer use - -A robust agent loop is: - -**observe → identify → act → wait → verify → recover** - -The repository also has a dedicated [AI agent guide](AI.md) with MCP configuration, tool selection, OpenAI integration, security guidance, and searchable computer-use terminology. - -### AI-friendly MCP - -Start the stdio server with: - -```bash -pip install je_auto_control -je_auto_control_mcp -``` - -The MCP server exposes the canonical `ac_*` surface plus short, model-friendly aliases such as `click`, `type`, `screenshot`, `find_text`, `click_text`, `drag`, `focus_window`, and `wait_image`. - -For inspection-only clients: - -```bash -je_auto_control_mcp --read-only -``` - -If a client needs only canonical `ac_*` names: - -```bash -JE_AUTOCONTROL_MCP_ALIASES=0 je_auto_control_mcp -``` - -For OpenAI agent integrations, expose a focused allow-list with `export_openai_tools(only=[...])` instead of passing the complete AutoControl command catalogue. This both fits provider limits and reduces the authority given to the model. - -### Project identity - -**Project:** AutoControl -**Repository:** `Integration-Automation/AutoControlGUI` -**Python package / PyPI:** `je_auto_control` -**MCP command:** `je_auto_control_mcp` - - ---- - - -## Choosing the right automation layer - -AutoControl is not intended to replace every automation tool. Use the smallest layer that matches the interface: - -| Need | Good fit | -|---|---| -| Stable browser DOM/API automation | Playwright / Selenium | -| Simple Python mouse and keyboard scripting | PyAutoGUI or AutoControl | -| Native desktop application automation | **AutoControl** | -| Accessibility-tree GUI automation | **AutoControl** | -| OCR-driven GUI automation | **AutoControl** | -| Screenshot / vision-model GUI localization | **AutoControl** | -| Self-healing cross-platform GUI locators | **AutoControl** | -| AI agent controlling a real desktop | **AutoControl + MCP** | -| Deterministic JSON GUI workflows | **AutoControl** | - -The differentiator is the combination of **real computer input + semantic/visual discovery + self-healing + agent/MCP integration** behind one cross-platform automation surface. - - -## Installation +Requires Python 3.11 or later. ```bash -pip install je_auto_control # core -pip install je_auto_control[gui] # + PySide6 desktop app +python -m pip install je_auto_control ``` -Optional extras, installed only when you need them: - -| Extra | Enables | -|---|---| -| `gui` | PySide6 desktop application (51 tabs): a searchable navigation panel (`Ctrl+K`) lists every feature by category, tabs are built the first time they are opened, and **View → Theme** switches dark / light. Pages scroll in narrow windows; theme, text size, navigation visibility (`Ctrl+B`) and width are saved in `~/.je_auto_control/gui.ini` on close. Themes use Qt directly; `qt-material` is not required. | -| `webrtc` | WebRTC remote desktop, USB passthrough (`aiortc`, `av`) | -| `signaling` | Standalone signaling / rendezvous server (`fastapi`, `uvicorn`) | -| `discovery` | mDNS / Zeroconf LAN host discovery | -| `pdf` / `office` | PDF and Excel / Word / PowerPoint reading | -| `fuzzy` / `locale` | `rapidfuzz` matching, `babel` locale parsing | -| `s3` / `audio` | S3 artifact store, system volume control | - -Closing a factory-built feature with the tab cross releases its widget, subscriptions and timers on the next Qt event-loop turn; reopening starts a new panel. **View → Tabs** and the embedding `hide_tab` API only hide it and preserve state. `tab_registry.open/close` and `close_tab` expose explicit lifecycle operations. Legacy owner-built forms and Remote Desktop remain reusable on close while their lifecycle migration is pending. - -**Windows on arm64** installs and runs, minus what upstream cannot ship -there: neither `opencv-python` nor `cryptography` publishes a `win_arm64` -wheel. So `find_image*`, `screenshot()` (the OpenCV/BGR one — the Pillow -capture still works), the secret vault, action-file encryption, ACME/TLS -and encrypted recording each raise a message naming the missing wheel -instead of failing obscurely. Mouse, keyboard, screen size, window -management, the accessibility tree, the action executor, the MCP/REST/TCP -servers and the GUI all work — measured, not assumed. Every other platform -is unaffected. - -**Requirements:** Python ≥ 3.11. On Linux, install build -prerequisites first: - -```bash -sudo apt-get install cmake libssl-dev -``` - -OCR, VLM, and LLM backends (`pytesseract`, `easyocr`, `paddleocr`, `anthropic`, -`openai`) are loaded on demand — install whichever you actually use. For Tesseract, -`find_tesseract_cmd()` locates the executable (`$TESSERACT_CMD`, then `PATH`, then the -installers' default folders), `set_tessdata_dir()` points it at a language-data folder, -and `ocr_status()` / `ocr_languages()` say what is missing before the first OCR call. - -**Log file:** the library logs to `~/.je_auto_control/logs/AutoControlGUI.log`, -created on the first record (importing alone writes nothing) and shared by every -process on the account (appended to, one process id per line, moved to `.1` -past 10 MB). Set `JE_AUTOCONTROL_LOG_FILE` to write elsewhere, or to -`os.devnull` to turn the file off. - ---- - -## 60-second quick start - -**1. As a Python library** +Read the screen dimensions without sending input: ```python import je_auto_control as ac -ac.set_mouse_position(500, 300) -ac.click_mouse("mouse_left") -ac.write("Hello World") -ac.hotkey(["ctrl_l", "s"]) - -x, y = ac.locate_image_center("save_button.png", detect_threshold=0.9) -ac.click_text("Submit") # OCR -ac.click_accessibility_element(name="OK") # accessibility tree -ac.click_by_description("the green Submit button") # vision model -ac.screenshot("shot.png", screen_region=[0, 0, 800, 600]) +print(ac.screen_size()) ``` -**2. As a JSON action file** — `flow.json` - -```json -[ - ["AC_set_var", {"name": "user", "value": "alice"}], - ["AC_locate_and_click", {"image": "login.png", "mouse_keycode": "mouse_left"}], - ["AC_write", {"write_string": "${user}"}], - ["AC_retry", {"max_attempts": 3, "body": [ - ["AC_wait_text", {"target": "Welcome", "timeout": 10}] - ]}], - ["AC_assert_text", {"text": "Welcome"}], - ["AC_generate_html_report", {"html_name": "report"}] -] -``` - -```bash -je_auto_control run flow.json --var user=bob -je_auto_control run flow.json --dry-run # list the steps without touching the mouse -``` - -**3. As a desktop app** +To use the desktop app: ```bash -pip install je_auto_control[gui] +python -m pip install "je_auto_control[gui]" python -c "import je_auto_control; je_auto_control.start_autocontrol_gui()" ``` -Record a flow, edit it in the visual Script Builder, and save it as the same JSON -format the CLI runs. (`python -m je_auto_control` is the legacy action-file runner — `-e`, `-d`, -`-c`, `--execute_str` — not the GUI.) - ---- - -## Capability overview - -Every row works headlessly. "GUI tab" is where the same feature surfaces in the -desktop app; tab commands live in the window's **Actions** menu. - -| Capability | Python API | `AC_*` command | GUI tab | -|---|---|---|---| -| Mouse | `click_mouse` (`clicks=2` double-clicks), `set_mouse_position`, `mouse_scroll`, `tween_drag` / `drag_path` (paced by `step_delay_s`, `settle_s`) | `AC_click_mouse`, `AC_tween_drag`, `AC_drag_path` | Auto Click | -| Keyboard | `write`, `write_secret`, `hotkey`, `type_keyboard`, `keyboard_key_name` (code → canonical name; Windows also takes aliases such as `ctrl`, `esc`, `enter`) | `AC_write`, `AC_write_secret`, `AC_hotkey` | Auto Click | -| Screen & pixels | `screenshot`, `screen_size`, `get_pixel` | `AC_screenshot` | Screenshot | -| Image matching | `locate_image_center`, `locate_and_click` | `AC_locate_and_click` | Image Detect | -| OCR text | `click_text`, `wait_for_text`, `read_text_in_region`, `ocr_status` | `AC_click_text`, `AC_wait_text`, `AC_ocr_status` | OCR Reader | -| Accessibility tree | `find_accessibility_element`, `click_accessibility_element` | `AC_a11y_find`, `AC_a11y_click` | Accessibility | -| Vision-model locator | `locate_by_description`, `click_by_description` | `AC_vlm_locate`, `AC_vlm_click` | VLM | -| Anchor locator | — | `AC_anchor_click`, `AC_anchor_locate` | — | -| Self-healing locators | `self_heal_run`, `self_heal_locate`, `self_heal_click` | `AC_self_heal_click` | Self-Healing | -| Natural-language planner | `plan_actions`, `run_from_description` | `AC_llm_plan` | LLM Planner | -| Computer-use agent | `AgentLoop`, `run_agent` | `AC_run_agent` | Computer Use | -| Record & replay | `record`, `stop_record` | `AC_record`, `AC_stop_record` | Record | -| JSON scripting | `execute_action`, `execute_files` | all 911 commands | Script, Script Builder | -| Variables & flow control | `execute_action_with_vars` | `AC_set_var`, `AC_loop`, `AC_for_each`, `AC_try`, `AC_retry` | Variables | -| Data-driven runs | — | `AC_for_each_row` (CSV / JSON / SQLite / Excel) | Data Sources | -| Assertions | `assert_text`, `assert_image` | `AC_assert_text` + 20 more | Assertions | -| Test suites | `run_suite` | `AC_run_suite` | Test Suites | -| Scheduler (interval + cron) | `default_scheduler` | — | Scheduler | -| Global hotkeys | `default_hotkey_daemon` | — | Hotkeys | -| Event triggers | `default_trigger_engine` | `AC_email_trigger_add` | Triggers, Webhooks, Email | -| Window management *(Windows, macOS, X11)* | `list_windows`, `focus_window` | `AC_focus_window`, `AC_snap_window` | Window Manager | -| Clipboard (text + image) | `get_clipboard`, `set_clipboard`, `get_clipboard_image`, `set_clipboard_image` | `AC_clipboard_get`, `AC_clipboard_set`, `AC_clipboard_get_image`, `AC_clipboard_set_image` | — | -| Remote desktop | `RemoteDesktopHost`, `RemoteDesktopViewer` | `AC_start_remote_host`, `AC_remote_connect` | Remote Desktop | -| USB enumeration & passthrough | `list_usb_devices`, `enable_usb_passthrough` | `AC_usb_*` (16 commands) | USB Devices, USB Share | -| Secrets vault | `default_secret_manager` | `AC_secret_set` + `${secrets.NAME}` | Secrets | -| Reports (HTML / JSON / XML) | `generate_html_report` | `AC_generate_html_report` | Report | -| Run history | `HistoryStore`, `manual_history_scope` | `AC_history_list`, `AC_history_capture` | Run History, Script Executor, Script Builder | -| Action journals | `execute_journal_run`, `inspect_journal` | `AC_journal_capture`, `AC_journal_read` | Run History, Script Builder | -| Metrics & tracing | `default_metric_registry`, `render_metrics_text` | — | — | -| Diagnostics | `run_diagnostics` | `AC_diagnose` | Diagnostics | -| Test-code generation | `generate_code` | — | — | - -Self-healing propagates cancellation before fallback or clicking. Its audit log masks secrets already resolved in the current run before writing or returning records; returned locator outcomes retain their original values. Legacy log files are not rewritten. - -Live image/VLM self-healing now shares one lazy logical capture, including its actual clipped origin. `screen_region` is `[left, top, right, bottom]` for both strategies. Schema-v2 audit records add run/step identity, content/configuration version, frame hash, strategy/capture timing and resolved backend/model; old records still load. Click dispatch without a verifier is recorded as issued or failed, with verification left unknown. The GUI exposes region input and selected-record evidence; Script Builder keeps region JSON structured. Historical `healed`/`heal_rate` count located candidates; separate operation metrics require explicit verification. - -Experimental `self_heal_run(SelfHealRequest(...))` defaults to locating. Choose `operation="click"` and `VerificationRequest(verifier=...)` (a Python bool callback) or `VerificationRequest(description=...)` (a configured VLM) to check the post-condition after input dispatch. VLM verification obtains a fresh logical frame and may incur API cost. `verified` is true, false or unknown; `found` and `issued` alone do not verify the operation. Exceptions and cancellation propagate without retrying the click. `AC_self_heal_run` and MCP `ac_self_heal_run` accept a nested `request`; explicit false verification fails the command/CLI or returns MCP `isError` with the structured result. GUI **Self-Healing** offers an optional post-condition field, and Script Builder edits the JSON request. Standalone VLM capture now uses the same logical origin/Retina normalization in memory. Framework assertions stop lookup recovery. - -Captured self-healing rows now include an optional `journal_path` alongside run/step IDs. Experimental `inspect_heal_source(path, run_id, step_id)`, `AC_self_heal_source` and MCP `ac_self_heal_source` read only the original step’s sanitized lifecycle snapshots. In **Self-Healing**, select a row and choose **Actions → Inspect original step** to open the background reader. Switching targets waits for the older reader to stop and retains the requester’s context; closing cancels pending work. Run History’s reader also accepts an optional step ID. Run/step filtering precedes the output limit, the whole file is validated, current path roots are rechecked around progress callbacks, and cancellation returns no partial result. Legacy or uncaptured rows have no original-source link; inspection never replays a command. - -Experimental causal synchronization provides `CausalBucket`, `CausalConfigStore`, `SyncActor`, conflict-preserving entry versions and a durable local `SyncOutbox`. The dedicated authenticated `GET/PUT /config/{user_id}/causal` protocol (version 3) validates peer registration, acknowledgements, retirement/full-sync epochs and collection in the same CAS transaction as retry receipts. Collected deletions retain permanent minimal fences; legacy writers cannot overwrite upgraded accounts. Private `AC_config_store_get` / `AC_config_store_commit` and matching MCP/Builder commands read and commit causal JSON with an explicit `_actor`. Pure merge/peer commands and private outbox commands remain available. The explicit `CausalSyncClient` and `AC_config_causal_fetch`, `AC_config_causal_commit`, `AC_sync_outbox_flush` (matching MCP/Builder commands) now deliver v3 HTTP requests: uncertain sends reuse the frozen request; only definite stale-base errors rebase within a bounded budget. `CausalReceipt` confirms the original receipt and latest complete snapshot atomically in the outbox. Command credentials use a live `options.secret_env` reference. `CausalSyncClient.control` and private `AC_sync_peer_control` / `ac_sync_peer_control` / Builder Data commands durably register, acknowledge, collect, retire and perform full resync. `SyncControlRequest(operation_id=...)` makes completed RPC retries idempotent; full resync requires explicit `discard_pending=True` before atomically adopting a new generation and archiving pending old edits. Local `status` reads no credential or network. Run `python -m examples.causal_peer_control` for the temporary loopback workflow; explicit local asset generations are available through `AssetManifest`, `DirectoryAssetTransport`, `build_asset_manifest`, `sync_assets` and private `AC_sync_asset_manifest` / `AC_sync_assets` (MCP/Builder). All assets stage and pass SHA-256/size checks before one directory publication; damaged caches are refused and scripts stay inert. `python -m examples.sync_assets` uses temporary directories only. Seven experimental adapters now capture selected scripts, locators, hotkeys, triggers, address-book entries, JSON settings and saved native GUI preferences into durable causal profiles. `SyncBindings` replaces explicit secrets and machine values with named references; `materialize_sync_profile` publishes a complete inert native-format generation. Private `AC_sync_adapter_snapshot`, `AC_sync_adapter_apply`, `AC_sync_adapter_resolve`, `AC_sync_profile_materialize` and matching MCP/Builder commands share the workflow. `python -m examples.sync_adapters` uses temporary files only. Private absolute path bindings accept high-entropy directory names while recognized credential formats remain refused. Native numeric definitions reject out-of-range values, including extreme JSON integers, with typed errors before storage. `WorkspaceSettingsSyncAdapter` captures only theme, font size, navigation visibility/width from native GUI INI files and publishes an inert `workspace.ini`; explicitly copy it to a separate working file before opening a new GUI. `python -m examples.sync_workspace` stays Qt-free. `SyncWorkspace` now coordinates selected sources, durable offline capture, causal HTTP, exact conflict review and full-resync source baselines. Private `AC_sync_workspace` / `ac_sync_workspace` / Builder Data share status/capture/sync/review/resolve/preferences/materialize and explicit peer controls; all require DRIVE. Runtime network credentials use `options.secret_env`. `python -m examples.sync_workspace_http` demonstrates two temporary sources over loopback, conflict resolution, restart and no replay of retired edits. Received definitions remain inert. Referenced asset transport is described below; explicit native working-copy loading is described below; `ConfigSyncClient` retains its timestamp merge. See the [causal/outbox guide](docs/source/Eng/doc/causal_sync/causal_sync_doc.rst) and `python -m examples.causal_sync`. - -The lazy **Workspace Sync** tab exposes local status/capture, network synchronization and peer controls, exact causal review/resolution, and complete inert publication through **Actions**. Paste an explicit private workspace descriptor; credentials are environment variable names. Sync never applies received preferences automatically. Select `workspace`, review its current heads, then choose **Apply reviewed GUI preferences** to update theme, font and navigation in the running window. `SyncWorkspace.preferences(observed=change_ids)` and the existing AC/MCP/Builder `preferences` operation return four canonical values only when the exact reviewed heads remain conflict-free; missing/deleted values use safe defaults. Workers preserve caller context, refresh DRIVE authority, support cancellation and discard stale results on close. The view shows revision/pending/conflict/reference counts and the last successful sync revision; no connection starts when opened. - -Explicit native loading uses `load_sync_profile(directory, target_root, expected_digest=...)` and `LoadedSyncProfile`, with private `AC_sync_profile_load` / `ac_sync_profile_load` / Builder Data equivalents. The published `files` directory and exact reviewed manifest digest create a fresh editable workspace. Full verified bytes, canonical native files and sealed heads must agree before atomic publication. Loaded hotkeys and every trigger node are disabled native objects; locator and address-book handles use the working files. Typed asset references and native hotkey/trigger paths resolve against that working root, while literal script strings keep their meaning and secrets stay placeholders. In **Workspace Sync**, materialization fills the directory/digest fields; choose a working-copy container and **Load reviewed native profile**. Separate Actions inspect the selected native kind, open a loaded script snapshot in Builder, or apply its preference snapshot. These actions recheck both the current caller and captured owner; opening a script keeps Run explicit. Builder renders imported command names and positional data as literal text. `python -m examples.sync_profile_load` uses seven temporary domains and a real PNG with no network or device calls. - -Folder mirroring now compares SHA-256 content instead of increasing modification times: metadata-only touches do not resend, while same-time/older-time edits do. FolderSyncEngine retains pending/offline edits across restarts, checks stop between files, and owns a blocked sender until it exits. Transport owners can explicitly call record_received(path) after publication to prevent echoing received bytes. Native GUI frozen-receipt handling is described below. - -File sends now wait for each DataChannel callback, bound buffered data to 1 MiB and propagate channel failures to the caller. Optional `cancelled` predicates stop queued writes; announced byte counts detect source truncation/growth. Native folder jobs capture their authorization, engine, viewer and peer connection, and stop when ownership changes. Inbox downloads run outside the event loop through a per-channel queue capped at 32 requests. Default manual-mode channel acceptance is not publication acknowledgement; confirmed mode is described below. GUI reconnect handoff is described below. - -Native file receivers now discard unfinished bytes on shutdown, files/control channel close, terminal connection state, replacement channel or revoked file permission. Closed receivers reject late frames; current peer/channel and authentication checks protect replacement transfers, including viewer receives before authentication. State cleanup precedes user callbacks so callback-driven reconnection survives an old failure. File/audit/state callbacks preserve original cancellation and hard-interruption objects. Filesystem cleanup failures are logged after both close and unlink are attempted. Existing Remote Desktop controls use this lifecycle automatically; completed targets and the legacy wire format remain available. - -Local `FileReceiveReceipt(path, sha256, size)` metadata now freezes the original received bytes after atomic publication. `FileTransferReceiver.handle_message(on_receipt=...)` and native host/viewer `set_file_receipt_callback()` expose it without rereading the published file. `FolderSyncEngine.record_receipt()` prevents echo while retaining later local edits; legacy `record_received(path)` explicitly snapshots current content. The GUI folder toggle captures its engine and viewer for receipt delivery and refreshes its original authorization before touching the watch. Relative inbox/watch paths bind to their creation working directory; existing path notices use absolute paths. These local receipts feed the confirmed native mode below; GUI reconnect handoff is described below. - -Native `FileTransferSender.send`, viewer `send_file` and host `push_file` now accept keyword-only `require_commit=True`. Confirmed mode probes an authenticated native peer before source metadata/content reads, sends version-2 begin/end metadata and verifies the matching transfer ID, unpredictable end nonce, SHA-256 and byte size after atomic publication. Relative source paths bind before the exchange. Each file rechecks peer support/permission; waits are bounded and cancellation, channel/loop replacement or permission loss retain failure. GUI folder sends always require this mode, so accepted-but-dropped bytes do not advance delivery state and uncertain sends retry on the same engine. Legacy manual mode remains the default and sends its original envelopes. Both peers need confirmed-transfer support for GUI folder delivery; unsupported peers fail before file content is sent. Explicit GUI reconnect/resume is described below. - -GUI reconnect retains one in-memory folder baseline per panel. After reconnecting, press Start sync again: the same authenticated host fingerprint, absolute watch path and local principal resume failed/offline edits through a new authorised sender. A missing/changed host fingerprint, different root or principal starts a fresh baseline; a still-running old worker blocks handoff until it exits. Explicitly disabling folder sync resets the baseline, while stopping/reconnecting the viewer retains it. Closing the application clears it. The fingerprint follows the existing authenticated host-metadata trust model, not a new cryptographic identity guarantee. SDK callers can stop a FolderSyncEngine, export checkpoint() after actual worker retirement and pass that immutable FolderSyncCheckpoint to a replacement engine with the same path/recursion mode and an explicitly authorised sender. The baseline includes initially ignored files and received bytes; it is not a list of remote acknowledgements. - -TCP/WebSocket clipboard transfers use the existing explicit SDK methods and GUI Push clipboard button. Received text/images do not automatically send or broadcast onward; deliberate repeated sends of identical content remain valid. Buffered viewer/host reads recheck the original connection, authentication and full-control permission before applying clipboard data. Viewer sends pin the original channel before encoding and refuse replacement. Queued GUI deliveries retain their concrete viewer and connecting user; permissions and ownership are refreshed before native clipboard writes, before explicit clipboard reads and again before sending. Stale/revoked work is discarded or reports its permission error. Ordinary provider/callback errors stay contained; original cancellation and hard-control objects propagate. Text/image JSON envelopes and existing APIs remain unchanged. Callback registration binds the original viewer weakly once, so a disconnected viewer does not keep itself and its Qt panel alive until cyclic GC. Actual queued deliveries still retain the original peer and authority until consumed or discarded. Controlled local protocol, loopback and offscreen tests replace native clipboard providers; real-device and paid-API acceptance remain deferred. - -Experimental referenced assets use `SyncAssetBlob`, `SyncAssetReference`, `SyncAssetStore` and `SyncAssetHTTPClient`. Explicit `SyncBindings.assets` aliases freeze selected files into immutable SHA-256 references; asset-only changes create new causal versions. `SyncWorkspace` uploads verified chunks before preparing new definition requests, resumes interrupted transfers and downloads referenced bytes before complete inert publication. Existing private AC/MCP/Builder workspace/profile commands share these fields. `asset_cache_path` selects the client cache; signaling `--asset-store` / `AUTOCONTROL_SYNC_ASSET_STORE` select the separate server database. Authenticated version-one asset routes use 256-KiB chunks, a 64-MiB per-file bound and default per-account limits of 256 MiB, 8,192 chunks and 4,096 blob receipts. Quota exhaustion fails explicitly; immutable history has no automatic garbage collection. Paths in native output are relative to the generation root. `python -m examples.sync_referenced_assets` sends a real PNG and script through temporary loopback HTTP with no execution or active workspace change. - -Experimental persistent configuration uses `ConfigStore.commit(..., base_revision=..., operation_id=...)` and a version-two signaling PUT envelope. SQLite transactions preserve buckets and retry receipts across restart; stale revisions or changed operation identities conflict. `ConfigSyncClient` defaults to conditional writes; blind legacy writes require explicit client/server opt-in. `--config-store` selects the lazy database. Private `AC_config_store_get` / `AC_config_store_commit` and matching MCP tools share explicit Script Builder Data commands. This stores data without running scripts or enabling triggers; causal merge and offline outbox remain separate. See the [persistent config guide](docs/source/Eng/doc/config_store/config_store_doc.rst) and `python -m examples.config_store`. - -Experimental journal-to-code candidates use `generate_candidate_from_log(path, run_id=...)`, `AC_generate_candidate_from_log`, and MCP `ac_generate_candidate_from_log`. They reconcile lifecycle snapshots, retain recorded control sources and retry evidence, and mark partial reconstructions as observed paths. Failed/incomplete invocations and unknown or redacted inputs remain explicit exclusions; parallel order is never invented. Generated Python/pytest/Robot source passes static, command and non-dispatching dry-run checks. `codegen --from-log run.jsonl --run-id selected` prints a JSON review bundle; `-o review.zip` or `write_candidate_archive` atomically exports code, actions and provenance together. **Actions → Review journal candidate** in Recording Editor or Script Builder opens source/diff/manifest/warnings; Builder import is separate and refuses intervening editor changes. Neither generation nor import runs the candidate. See the [journal candidate guide](docs/source/Eng/doc/journal_candidates/journal_candidates_doc.rst) and `python -m examples.journal_candidates`. - -Experimental template-candidate revisions use `create_template_candidate`, `preview_template_candidate`, `verify_template_candidate`, `accept_template_candidate` and `revert_template_candidate`, with matching `AC_template_candidate_*` / `ac_template_candidate_*` operations. A new immutable JSON bundle retains original bytes and the candidate encoded in the target’s PNG/JPEG/BMP format. Preview returns bounded thumbnails. Verification compares both frozen versions on a local sample manifest; acceptance requires a labelled hit, an expected miss and every labelled case correct, plus the reviewed bundle SHA-256. Acceptance rechecks the dataset and atomically replaces only matching original bytes; revert restores exact original bytes and refuses later edits. Unknowns and native-operation success remain separate. The recorded threshold applies to verification; activating image bytes does not edit script thresholds. **Self-Healing → Template candidates** offers all five Actions, background work, cancellation and JSON evidence. Run `python -m examples.template_candidates` for a temporary-file-only example. - -Experimental fixed-frame comparisons use `evaluate_locators` or `evaluate_healing_manifest`, `AC_self_heal_evaluate`, MCP `ac_self_heal_evaluate`, and **Self-Healing → Version comparison**. Reports separate labelled accuracy, wrong predictions, unknowns and verified recovery, include p50/p95 and provenance, and export JSON/HTML through `write_healing_report` or GUI Actions. The local manifest operation never captures, clicks or selects a network backend. See the [dataset, populations and limits](benchmarks/self_healing/README.md). - -Beyond this table, `utils/` holds 311 headless packages covering assertions, resilience, -data quality, i18n auditing, redaction, governance, observability, and more. The full -per-module map is in **[architecture_explore.md](architecture_explore.md)**. - ---- - -Experimental structured journal capture is exported from `je_auto_control` (also available in `utils.action_journal`): `journal_scope` captures existing executor calls, and `execute_action_with_journal` isolates one run. Local loop/parallel/DAG steps retain parent IDs; failures, cancellation and dry-runs are distinct. Existing history owners automatically link explicit captures, including captures opened by local parallel/DAG workers; `HistoryStore.journals_for_run` returns the non-owning links. Clearing/pruning history leaves journal files intact. The CLI supports `run script.json --journal run.jsonl [--journal-run-id ID]` and `journal run.jsonl [--run-id ID] [--limit 100]`. Journal reads show sanitized lifecycle snapshots in append order; output defaults to 100 snapshots (maximum 10,000). `AC_journal_capture` accepts named parameters and runs a nested `body` on the owning executor without replacing its variables; `AC_journal_read` shares sanitized, bounded inspection with the CLI and public `inspect_journal`. Both commands are editable in Script Builder. Capture rejects identifiers or destinations containing secrets known to the run before history linking, file creation or action effects. MCP `ac_journal_capture` and `ac_journal_read` provide structured results, progress and cooperative cancellation. Captured journal roots and observers survive nested captures and local workers; reads can cancel between validated records. `JournalRunOptions` and `execute_journal_run` expose the same controls in Python. - -Manual runs can opt into history with `manual_history_scope`, `AC_history_capture`, CLI `run --history [--history-db PATH]`, or **Record in Run History** in Script Executor / Script Builder. An optional GUI journal path also works independently of history. GUI/CLI result JSON and existing variable scopes are preserved; the command returns `history_id`, `record` and `failed_actions`. Existing and nested captures link to the new manual row. CLI previews use the `cli.preview` source label; ordinary runs use `cli.run`. - -Run History includes a read-only journal browser. Use **Actions → Use Journals from Selected Run** to select a provenance link, or **Choose Journal** for an external file. Set a run ID and snapshot limit, then **Read Journal**; start/completion snapshots stay separate and their full sanitized data appears on selection. **Cancel Journal Read** and closing the view request cancellation between records. File parsing runs in a background worker; selecting a link opens no file. - -Values resolved from `${secrets.NAME}` are masked in application diagnostics during executor runs, including nested actions and local parallel/DAG workers. CLI/REST/MCP requests and scheduled, trigger, hotkey and email runs retain the mask through error handling and audit/history writes; report records capture redacted snapshots. DAG calls retain the owner mask through complete node diagnostics, including standalone calls and custom local runners. Watchdog, observer and callback-executor calls also retain it through final diagnostics; independent rules have separate masks. CLI stderr is masked, while API outcomes, raised exceptions and CLI result payloads retain their original values. Masks are discarded when the owning request or run exits. Interrupted history runs are recorded as `error`, while journal steps remain `cancelled`; no error screenshot is taken. Cancellation propagates through non-strict execution, recovery/retry, callbacks and local workers. Hard exits retain their original signal even if history completion fails. - -## Command-line interface - -Each `je_auto_control run` invocation, including `--dry-run` and runs without `--var`, gets a fresh variable scope. Top-level `run_from_description` and `StateMachine.run()` also isolate variables while sharing them across their own actions and states; nested calls reuse an existing execution scope. A caller-owned `Executor()` keeps its own variables. - -```bash -je_auto_control run script.json [--var name=value] [--dry-run] [--allow-package NAME] -je_auto_control validate script.json # alias: lint -je_auto_control fmt script.json [--check] -je_auto_control list-commands [--filter mouse] [--json] -je_auto_control record out.json [--duration 5] -je_auto_control codegen script.json --target pytest -o test_flow.py -je_auto_control failure-bundle failure.zip --error "login timed out" -je_auto_control list-jobs -je_auto_control start-server --port 9938 # TCP socket server -je_auto_control start-rest --port 9939 # REST API -je_auto_control version -``` - -`--var name=value` is parsed as JSON when possible (`count=10` becomes an int), -otherwise kept as a string. `run` exits 1 when any action failed (the run -still goes on to the end), so a CI step fails with it. The legacy -`python -m je_auto_control -e file.json` entry point still works, and its -`-e`, `-d` and `--execute_str` flags exit 1 the same way. Under -[TestPioneer](https://github.com/Integration-Automation/TestPioneer), which -sets `TEST_PIONEER_ARTIFACT_DIR`, the HTML, JSON and XML reports asked for -under a relative name are written below that directory. - ---- - -## Servers and integrations - -| Surface | Start it with | Notes | -|---|---|---| -| **MCP server** | `je_auto_control_mcp` (stdio) or `AC_start_mcp_http_server` | 820 tools for Claude Desktop / Claude Code / custom tool loops: the full `ac_*` surface plus short model-friendly aliases for common GUI actions. Speaks the stateless MCP 2026-07-28 beside the `initialize`-based revisions. Bearer auth, TLS, audit log, rate limit, plugin hot-reload, CI fake backend. | -| **REST API** | `je_auto_control start-rest` | Bearer token, per-IP rate limit + lockout, SQLite audit hook, `/metrics`, `/openapi.json`, `/docs` Swagger UI, `/dashboard`. | -| **TCP socket server** | `je_auto_control start-server` | Newline-framed JSON action lists. Binds `127.0.0.1` by default. | -| **pytest plugin** | installed automatically | Fixtures plus a Gherkin step library for pytest-bdd / behave. | -| **Language server** | `python -m autocontrol_lsp.server` | Completion and diagnostics for `AC_*` action JSON, generated from the live command table. | -| **Remote desktop** | `RemoteDesktopHost` / GUI | TCP, WebSocket, or WebRTC; TOTP, trust list, TURN config, file/clipboard/audio sync. | - -All servers bind to `127.0.0.1` unless you opt in explicitly. - -The MCP window-state tools `ac_window_minimize`, `ac_window_maximize` and `ac_window_restore` return the window handle on accepted requests and `isError: true` on backend refusal (including a stale handle or rejected activation). Raw Win32 `ShowWindow` previous visibility is normalized by the backend. - -**Package gate.** `AC_add_package_to_executor` and `AC_add_package_to_callback_executor` import a Python package and register its members as commands, so an action list arriving over any of these surfaces could load `os` or `subprocess`. No package loads unless it has been allowed: a package that is not on the allowlist is refused before it is imported, and that action fails with `AutoControlExecuteActionException`. Allow packages (submodules included) from Python with `executor.allow_packages("name", …)`, for every entry point — both CLIs, the socket / REST / MCP servers and the scheduler — with the `JE_AUTOCONTROL_ALLOWED_PACKAGES` environment variable (comma-separated names, read when the process starts), or for one CLI run with `je_auto_control run script.json --allow-package NAME` (repeatable). `executor.set_allow_arbitrary_packages(True)` opens the gate for every package, which is what earlier releases did by default (with a `DeprecationWarning`). None of these is an `AC_*` command, so an action list cannot open its own gate. - -**Opt-in hardening.** Each of these is off until configured, and a server without them behaves as before. `JE_AUTOCONTROL_RBAC_USERS=` makes the REST API and the MCP HTTP transport resolve the bearer token to a user and authorise each route, tool and privileged `AC_*` command by role (viewer / operator / admin); the shared token is then refused. `JE_AUTOCONTROL_MCP_PATH_ROOTS` (directories separated by the OS path separator) confines every MCP tool argument that is a file path to those directories, `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT=1` adds the client's `roots/list`, and `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` limits which `env://` names `ac_resolve_ref` may read. `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` makes an endpoint verify Ed25519-signed action files without being able to sign them (`create_signing_keypair`; the private key stays on the signing machine). A remote-desktop viewer writes files pushed by a host only below `~/Downloads/AutoControl` (`JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR`); that one is on by default. - -The REST GUI shows RBAC mode and disables the shared-token field while a user store is active. `rest_api_registry.status()` includes `rbac_enabled` and returns `token: null` in that mode; use an individual user token. Custom REST gates that only implement `check()` remain supported in shared-token mode; RBAC requires an authenticated user context and refuses an identityless success. - -RBAC viewers do not receive the named sensitive-read tools, even when their MCP `readOnlyHint` is true: clipboard/history, local document/data/SQL and dotenv reads, reference resolution, credential generation, persistent store readers, outbound checks, microphone capture and external VLM requests require operator/admin. Assertion containers also require operator because their specs can read those resources. Screen observation and pure input parsing keep their existing classification. `ac_realize_item`, `ac_idempotency_begin` and `ac_rate_limit` change state and are excluded from `--read-only` mode. - -Delayed interval/cron jobs, triggers, hotkeys, watchdog rules, webhooks, e-mail triggers and observer callbacks retain their registrant’s identity. Store-backed users and roles are checked again on dispatch; deleted users, unavailable stores and viewers cannot execute deferred work. Starting a daemon does not transfer its registrations to the starter. Ownership metadata retains no RBAC bearer token; explicit Python `AuthorizationContext` values without `store_path` keep their captured role, and work registered outside RBAC clears worker identity. Observer/watchdog callbacks get fresh variable scopes, and failed watchdog actions do not count as dismissed popups. Nested callbacks retain the caller’s failure count; a webhook with a revoked owner returns HTTP 403 and `fired: false`. - -### How the remote-desktop wire protocol works - -TCP hosts release a rejected authentication attempt’s client slot before sending `AUTH_FAIL`. A viewer can retry immediately, including after a bad token, wrong handshake message or denied approval, while socket cleanup/logging finishes. Pending handshakes retain their independent resource bound. - -Worth knowing before you expose a host, and described nowhere else in the -docs. The default transport is length-prefixed framing over raw TCP — no extra -dependencies — and it opens with an **HMAC-SHA256 challenge/response -handshake**: a viewer that fails auth is dropped before it is sent a single -frame. JPEG frames are encoded at the configured FPS and quality and handed to -authenticated viewers through a shared *latest-frame slot*, so a slow viewer -drops frames instead of stalling the rest. Viewer input arrives as JSON and is -**validated against an allow-list** of actions before being applied through the -ordinary input wrappers, so a viewer cannot invent new operations. - -```python -# Be remoted — start a host and hand the token + port to whoever views you -from je_auto_control import RemoteDesktopHost -host = RemoteDesktopHost(token="hunter2", bind="127.0.0.1", - port=0, fps=10, quality=70) -host.start() -print("listening on", host.port, "viewers:", host.connected_clients) -``` - -```python -# Control another machine — connect a viewer and send input -from je_auto_control import RemoteDesktopViewer -viewer = RemoteDesktopViewer(host="10.0.0.5", port=51234, token="hunter2", - on_frame=lambda jpeg: ...) -viewer.connect() -viewer.send_input({"action": "mouse_move", "x": 100, "y": 200}) -viewer.disconnect() -``` - -Narrow who may connect at all with an IP allow-list (CIDR ranges or exact -addresses); peers outside it are rejected during the handshake: - -```python -RemoteDesktopHost(token="tok", ip_allowlist=["10.0.0.0/8", "192.168.1.100"]) -``` - ---- - -## Platform support - -| Platform | Backend | Input | Screen capture | Recording | Window management | -|---|---|:---:|:---:|:---:|:---:| -| Windows 10 / 11 | Win32 ctypes (+ optional Interception driver) | ✅ | ✅ | ✅ | ✅ | -| macOS 10.15+ | pyobjc / Quartz | ✅ | ✅ | ✅¹ | ✅ | -| Linux X11 | python-Xlib (+ optional `uinput`) | ✅ | ✅ | ✅ | ✅ | -| Linux Wayland | libei via the desktop portal, or ydotool / wtype + a capture tool | ✅ | ✅ | ❌ | ❌ | -| FreeBSD / OpenBSD / NetBSD | python-Xlib, the same X11 backend as Linux | ✅² | ⚠️² | ✅² | ✅² | -| Android | adb + uiautomator2 | ✅ | ✅ | — | — | -| iOS | WebDriverAgent / facebook-wda | ✅ | ✅ | — | — | - -¹ macOS recording captures through a Quartz event tap and needs -**Accessibility** permission (System Settings → Privacy & Security → -Accessibility). Without it recording raises and names the permission -rather than returning an empty session. - -² The BSDs run the X11 backend unchanged — the same X server, the same -`python-Xlib`, which is the only dependency input, recording and window -management have. A `freebsd` CI job drives real input on a real FreeBSD 14 and -reads it back off the X server; OpenBSD and NetBSD take the same code path but -have no CI runner. Screen capture is the exception, and the reason is -packaging rather than the platform: it goes through Pillow/mss and OpenCV, and -`opencv-python`, `pillow` and `cryptography` publish no FreeBSD wheels. Build -those from ports and capture, image matching, OCR and action encryption work -too — `import je_auto_control` no longer requires any of them. - -Wayland key/button/pointer input in `auto` mode uses CLI when the optional native -backend is absent. Once a portal request starts, refusal, timeout, handshake -failure, device pause or revocation stops input; it never silently switches -providers. Repeated refused calls retain inert failure state without reopening -consent. `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND=libei` requires native input; -`=cli` explicitly selects CLI. After resolving permission, an explicit -`je_auto_control.linux_wayland.libei.reset_default_backend()` allows a fresh -request. Interrupted native chords attempt all owned key releases on the same -backend and preserve the original cancellation. This does not change the -explicit wtype text path or screen-capture selection. - -The `ydotool` fallback needs **ydotool 1.0 or newer**. Every argument -AutoControl builds arrived in that release; 0.1.x — which is what Debian -bookworm and every current Ubuntu still ship under that name, and Debian -trixie ships not at all — answers the same arguments with exit code 0 and no -events. AutoControl detects it and refuses rather than reporting success for -input it never sent. Arch, Fedora and Debian unstable package 1.0. - -That fallback also positions the pointer accurately **only where the -compositor's pointer acceleration is off**. `ydotool mousemove --absolute` -sends no absolute event: it drives the cursor into the corner the compositor -clamps to and then moves relative to it, so the compositor accelerates the -move — measured against a real wlroots session, libinput's default profile -travels exactly twice the distance asked for. ydotool's own `--help` says the -same; AutoControl logs it once per process rather than mispositioning in -silence. Turn acceleration off for the ydotoold device (sway: `input -type:pointer accel_profile flat` and `pointer_accel 0`), or install -`liboeffis` so the libei path — absolute at the protocol level — is used. - -The factor is the compositor's own setting and no client can read it back, so -only you know whether it is off. `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL=flat` -says it is, and moves silently; `=strict` refuses the move rather than let a -click land somewhere else; leaving it unset keeps the warn-and-move default. - -Wayland screen capture needs the tool your compositor supports, because no -single one covers them all: `grim` on wlroots compositors (sway, Hyprland, -river), `gnome-screenshot` on GNOME, `spectacle` on KDE. Install one and every -capture path — screenshots, image and anchor locators, OCR, screen recording, -remote desktop — goes through it. With none installed, a session bus is -enough: the built-in D-Bus client tries `xdg-desktop-portal` last, though it may ask for consent the -first time. Failing that, capture fails loudly with an install hint rather than -returning the blank XWayland root. The `screen_capture` check in -`je_auto_control.api.run_diagnostics()` (and the GUI Diagnostics tab) reports -which tier is in use. - -A native Wayland pointer coordinate outside every granted EIS region, after -raw-coordinate and layout-origin mapping, raises `LibeiUnavailable` with -`state="failed"` and disables automatic CLI fallback. A rejected move emits -no motion/frame or subsequent click. Valid coordinates, devices without -regions, later valid requests on the same sender and explicit CLI selection -retain their existing behavior. - -Passive **input/capture capabilities** use `BackendContext`, `CapabilityStatus`, -`CapabilitySnapshot` and `probe_capabilities` from `je_auto_control.api` (also -exported at the package root). Call -`probe_capabilities(BackendContext.current()).to_dict()`, use no-argument -`AC_probe_capabilities` / read-only `ac_probe_capabilities`, or choose -**Diagnostics → Actions → Inspect input and capture capabilities**. Builder -provides the same no-argument command. `python -m examples.capabilities` prints -live prerequisites and a deterministic XWayland scope example without desktop operations. - -Input describes key/pointer events; the existing wtype text path is separate. -The probe reads environment/PATH and nonblocking cached native state; it never -loads optional native libraries, connects, polls events, captures or requests -permission. Installed tools or a bus address mean `unverified`, not readiness. -Cached libei readiness requires a completed handshake and active keyboard, -absolute pointer, button and scroll families. A partial grant remains -unverified; paused families and removed required devices report paused/revoked. -The eight states are `available`, `unverified`, `needs_permission`, -`needs_dependency`, `unsupported`, `paused`, `revoked` and `failed`. -`available` is only the last local observation and may be stale; every real -operation rechecks authority. XWayland always has `desktop_wide=False` and cannot -cover native Wayland windows. Other scope flags remain subject to granted -regions/permissions and do not verify every monitor. - -Contexts detach environment/executable facts and may carry an owner's inert -input/capture observations. They grant no authority. Default live results omit -environment values, command arguments, executable paths and native error text; -AC/MCP accept no supplied observations. Explicit CLI configuration remains -distinct from automatic fallback after observed optional native absence; -permission/pause/revocation/failure metadata cannot imply CLI fallback. -Capture helper and portal selection are diagnosed independently. Rendering and -language changes reuse the snapshot without probing. Native portal restore, -compositor restart, capture-result/context integration and native session -controls remain in `Progress.md`. - -The GUI task infrastructure provides `gui.task_controller.TaskController`: -`submit(work, owner=widget)` returns a caller-owned `TaskHandle` with -typed `TaskOutcome` and `TaskProgress` observations. Work receives a -Qt-free `CancellationToken` with checkpoints, bounded interruptible waits -and progress reporting. Submission captures context; dispatch refreshes -store-backed identity. Work must receive plain data, avoid widget references -and authorize its own operation. Existing -`DeferredAuthorization.scope()` still requires input privilege, while -`context_scope()` only refreshes/binds identity for independently authorized work. - -Owner/handle/controller destruction requests cooperative stop and drops -late delivery. Each task has a separate ID/token; callbacks run on the GUI -thread. Cancellation does not forcibly interrupt an uncooperative call -or relabel a successful committed return. Errors/progress use the captured -secret scope; terminal errors retain no exception traceback. Failed thread -starts roll back both registries and preserve the original failure. -Diagnostics now adopts this controller. Remaining panel/backend migrations -and native session operations stay in `Progress.md`. - -Active **Diagnostics → Actions → Run diagnostics** uses the shared task -controller off the GUI thread. **Stop diagnostics** requests cooperative stop; -the view distinguishes running, stopping, canceled and failed states in four -languages. Progress counts completed checks. Duplicate runs are ignored, close -abandons late progress/results, and a deliberate retry starts a new owned run. -GUI cancellation is a typed outcome without retained exception tracebacks; -headless core/SDK/CLI and the MCP handler preserve original direct/wrapped controls. -Ordinary probe failures still become report rows and allow remaining checks. - -`CancellationToken`, `TaskProgress` and `cancellation_scope` are exported by both -SDK namespaces. Bind `with cancellation_scope(token): report = run_diagnostics()`; -the owning caller can call `token.cancel()` from another thread. The existing -no-argument diagnostics signature remains. Scope binding grants no authority; -`cancellation_scope(None)` only suspends cancellation for bounded owned cleanup. -`AC_diagnose` and the new read-only `ac_diagnose` share the report. The MCP tool -accepts no arguments, uses request cancellation/progress and requires -`read_screen`, as does the explicit GUI action. Caller-supplied tokens or -authority metadata are rejected. These are active checks: capture may request -consent. `ac_probe_capabilities` remains the separate passive alternative. - -Scoped Wayland D-Bus connect/read/partial-write waits poll at intervals capped -at 0.1s within the original total deadline. Cancellation attempts Request.Close -on the originating bus with its separate 0.25s budget, then releases that -connection; a canceled returned image is discarded. Scoped CLI captures stop -and reap their newly owned helper/process group with bounded cleanup, preserving -the original control even if pipe close fails; reaped numeric PIDs are never -signaled. liboeffis acquisition observes scoped stop and releases its own context. -Uncooperative/native calls are not forcibly preempted; the GUI remains responsive -while cleanup completes. Restore/restart, native session controls, capture-owner -metadata and remaining panel/backend migrations stay in `Progress.md`. - -`python -m examples.cancellable_diagnostics` runs a controlled cancellation demo -without providers. `--active --cancel-after 2` explicitly runs diagnostics and -requests stop after two seconds; native/device/API acceptance remains separate. - -Opening Diagnostics displays a localized not-run state and performs no checks. -Choose **Actions → Run diagnostics** to start the existing active checks, which -can capture the screen or require portal consent. Changing the display language -does not start checks. The explicit `run_diagnostics`, `AC_diagnose` and MCP -diagnostic calls retain their active behavior. Passive capability inspection is a separate action below. - -Abandoned screenshot portal requests attempt `Request.Close` on the originating -bus before disconnect, using a separate 0.25-second D-Bus I/O budget. A returned -alternate handle is followed; after an uncertain method reply, the predicted -handle is used. Completed responses are not closed again. Ordinary cleanup -errors do not replace the primary capture failure; original cancellation and -hard-control objects survive wrappers and cleanup. D-Bus writes and reply waits -share the call budget, connection setup has an explicit timeout, and interrupted -connect/authentication/Hello releases its owned descriptor even when `__enter__` -fails. Actual compositor/dialog cancellation remains platform acceptance work. - -One Wayland-only difference to plan around: **a capture may contain the mouse -cursor.** Nothing here asks for it, but wlroots composites a *software* cursor -into the output buffer whenever the backend has no cursor plane — which -includes any session run with `WLR_NO_HARDWARE_CURSORS=1` — and that buffer is -what screen capture hands back. Windows and X11 never include the pointer, so a -locator, a template match or an OCR read can find a pointer-shaped hole in the -middle of its target here and nowhere else. Wayland does not let a client read -the cursor position, so there is nothing to reliably mask or move around it: -park the pointer away from what you are about to capture. The `screen_capture` -check reports this as `cursor_may_be_captured`. - -For a setup none of that fits, name your own command — it wins over every -detected tool, and `{output}` is replaced with a temporary PNG path: - -```bash -export JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND="mycapture --png {output}" -``` - -Wayland forbids global input recording for unprivileged clients — set -`JE_AUTOCONTROL_LINUX_DISPLAY_SERVER=x11` to record on an X11 session. Window -management works on Windows, macOS (pyobjc) and X11, including XWayland; on a pure -Wayland session, whose protocol hides other clients' windows, `list_windows()` returns -an empty list and every window action raises `AutoControlUnsupportedOperationException` -saying why. Opt-in driver-level backends (`JE_AUTOCONTROL_WIN32_BACKEND=interception`, -`JE_AUTOCONTROL_LINUX_BACKEND=uinput`, ViGEm virtual gamepad) exist for apps that -ignore synthetic input, and fall back silently when the driver is absent. - ---- +## What you can do -## Configuration +- Automate mouse, keyboard and window operations. +- Locate controls with image matching, OCR, accessibility APIs or optional vision models. +- Save repeatable workflows as JSON action files. +- Connect AI clients through MCP, or integrate through REST and Python. +- Use recording, scheduling and remote-desktop tools through the optional GUI. -Every environment variable AutoControl reads. Nothing here is required: with no variable set, AutoControl picks the platform backend by itself, servers bind `127.0.0.1`, and every opt-in feature (signature enforcement, RBAC, USB passthrough, tool-path roots) is off. The [configuration reference](https://autocontrol.readthedocs.io/en/latest/Eng/doc/configuration/configuration_doc.html) ([source](docs/source/Eng/doc/configuration/configuration_doc.rst)) has the accepted values in full and links each variable to the page that explains the feature; CI compares it, and the tables below, with the code. +Windows, macOS, X11 and Wayland use different backends. Available features depend on system permissions and optional dependencies; Windows ARM64 has additional limitations. See the installation guide before choosing a deployment target. -### Platform backends +Managed agent tasks and cross-host transfers include experimental features. See the implementation notes and project progress before relying on them in production. -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_WIN32_BACKEND` | `sendinput` | `interception` sends keyboard and mouse through the Interception driver; falls back to `SendInput` with a warning when the driver or DLL is missing. | -| `JE_AUTOCONTROL_LINUX_BACKEND` | `x11` | `uinput` writes kernel input events; falls back to XTest with a warning when `/dev/uinput` is not writable. | -| `JE_AUTOCONTROL_LINUX_DISPLAY_SERVER` | `auto` | Which Linux backend loads: `auto` reads `XDG_SESSION_TYPE` and `WAYLAND_DISPLAY`; `wayland` or `x11` forces one (`x11` on a Wayland session drives XWayland windows only). | +## Documentation -### Windows Interception driver - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_INTERCEPTION_DLL` | unset: `PATH`, then next to the package | Full path of `interception.dll`. | -| `JE_AUTOCONTROL_INTERCEPTION_KEYBOARD` | `1` | Interception device id (`1`–`10`) keyboard events are sent to. | -| `JE_AUTOCONTROL_INTERCEPTION_MOUSE` | `11` | Interception device id (`11`–`20`) mouse events are sent to. | - -### Wayland - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND` | `auto` | `cli` sends input through `ydotool` and never asks the desktop portal. Chosen before starting: after a refused consent AutoControl does not switch to it by itself. | -| `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL` | `warn` | Absolute moves on the `ydotool` path only (relative motion the compositor accelerates): `warn` warns once and moves, `flat` declares acceleration off and moves silently, `strict` refuses the move. | -| `JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND` | unset | Your own screenshot command line, with `{output}` where the PNG path goes. Takes precedence over `grim`, `gnome-screenshot`, `spectacle` and the portal. | -| `JE_AUTOCONTROL_WAYLAND_RECORD_DEVICES` | unset: none | Comma-separated `/dev/input/event*` devices `PhysicalRecorder` may read; physical recording is opt-in per device. | - -### MCP server - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_MCP_READONLY` | unset | `1`: only tools marked read-only are offered and callable. | -| `JE_AUTOCONTROL_MCP_TOOL_PROFILE` | unset | Comma-separated tool names and `category:` entries of the `static` profile. | -| `JE_AUTOCONTROL_MCP_ALIASES` | `1` | `0` leaves out the short aliases (`click`, `screenshot`, …) registered beside the `ac_*` tools. | -| `JE_AUTOCONTROL_MCP_TOKEN` | unset | Bearer token of the HTTP transport. Not accepted once RBAC is on. | -| `JE_AUTOCONTROL_MCP_ALLOWED_ORIGINS` | unset: loopback origins only | Comma-separated extra browser origins (exact, e.g. `https://example.test:8443`) the HTTP transport accepts. | -| `JE_AUTOCONTROL_MCP_CONFIRM_DESTRUCTIVE` | unset | `1`: destructive tools ask the client for confirmation (MCP elicitation) before they run. | -| `JE_AUTOCONTROL_MCP_PATH_ROOTS` | unset: no confinement | Directories (separated by the OS path separator) every file argument of a tool must stay inside. | -| `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` | unset | `1`: also accept the roots the MCP client reports through `roots/list`. | -| `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` | unset: no restriction | Comma-separated environment variable names (`fnmatch` patterns allowed) `ac_resolve_ref` may read; a value that names nothing allows none. | -| `JE_AUTOCONTROL_MCP_AUDIT` | unset | Path of a JSON-lines file that receives one record per `tools/call`. | -| `JE_AUTOCONTROL_MCP_ERROR_SHOTS` | unset | Directory a screenshot is saved to each time a tool fails. | -| `JE_AUTOCONTROL_FAKE_BACKEND` | unset | `1`: the MCP server records mouse, keyboard and clipboard calls in memory instead of performing them, for CI without a display. | - -### REST / RBAC and chat-ops - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_RBAC_USERS` | unset: shared token | Path of the user store file. Setting it is what switches roles on for the REST API and the MCP HTTP transport. | -| `JE_AUTOCONTROL_CHATOPS_SCRIPT_ROOT` | unset: `run` is refused | The only directory the chat-ops `run` command may load action files from. | - -### Executing and signing action files - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_ALLOWED_PACKAGES` | unset: none | Comma-separated packages `AC_add_package_to_executor` may load (submodules included), for every entry point. Read once, when the process starts. | -| `JE_AUTOCONTROL_REQUIRE_SIGNED_ACTIONS` | unset | `1`: every path that runs an action file refuses one without a valid signature sidecar. | -| `JE_AUTOCONTROL_ACTION_SIGNING_PRIVATE_KEY` | unset | Path of the Ed25519 private key (PEM). Set it on the signing machine only; signing then writes a version-2 sidecar. | -| `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` | unset | Path of the matching public key. Set it on every machine that executes: it verifies and cannot sign. | -| `JE_AUTOCONTROL_ACTION_SIGNING_PASSPHRASE` | unset | Passphrase of the private key, when it was created with one. | -| `JE_AUTOCONTROL_ACCEPT_LEGACY_ACTION_SIGNATURES` | unset | `1` is migration mode: once a public key is configured, HMAC sidecars written before version 2 are refused unless this is set. Switch it off again when every file has been re-signed. | - -### Remote desktop and signaling - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR` | `~/Downloads/AutoControl` | Directory a remote-desktop viewer stores files its host sends in. A received path is confined to it. | -| `JE_AUTOCONTROL_USB_PASSTHROUGH` | unset | `1` enables USB passthrough opcodes on the remote-desktop channel. | -| `AC_SIGNALING_SECRET` | unset | Shared secret of the signaling / config-sync server (`X-Signaling-Secret`). Read by the server when `--shared-secret` is not given. | - -### GUI - -| Variable | Default | Effect | -|---|---|---| - -### Logging, data and testing - -| Variable | Default | Effect | -|---|---|---| -| `JE_AUTOCONTROL_LOG_FILE` | `~/.je_auto_control/logs/AutoControlGUI.log` | Where the log file is written. The null device (`/dev/null`, `NUL`) switches the file off. Read when the first record is written, not at import. | -| `JE_AUTOCONTROL_ENV` | `default` | The active environment of the asset store (`active_environment()`), so one script reads different values in `dev` and `prod`. | -| `JE_AUTOCONTROL_REDACTION` | `off` | Default screenshot redaction policy: `off`, `moderate` or `strict`. An unknown name is an error, not `off`. | -| `JE_AUTOCONTROL_PYTEST_ARTIFACTS` | `./autocontrol_screenshots` | Directory the pytest plugin writes failure screenshots to when a test did not request the `autocontrol_screenshot_dir` fixture. | - ---- - -## Documentation and examples - -| Resource | What's in it | -|---|---| -| [`examples/`](examples/) | 45 self-contained scripts: screenshot + click, OCR, scheduler, remote desktop, agent loop, observability, recording, variables, hotkeys, triggers, reports, MCP, REST, secrets, plugins, computer use, Wayland, cross-host DAGs, chat-ops, pytest/BDD, anchor locators, action journals. | -| [Read the Docs](https://autocontrol.readthedocs.io/en/latest/) | Full API reference, English and 中文. | -| [architecture_explore.md](architecture_explore.md) | Every module's responsibility, layer by layer. | -| [docs/CAPABILITY_MATRIX.md](docs/CAPABILITY_MATRIX.md) | Capability × platform matrix. | -| [docs/API_LIFECYCLE.md](docs/API_LIFECYCLE.md) | Stable-API and deprecation policy. | -| [docs/updates/](docs/updates/README.md) | Update log: release notes and finished work, one file per month (formerly `WHATS_NEW.md`). | -| [CHANGELOG.md](CHANGELOG.md) | Compatibility changelog. | -| [SECURITY.md](SECURITY.md) | Security policy and reporting. | - ---- - -## Development - -```bash -git clone https://github.com/Integration-Automation/AutoControlGUI.git -cd AutoControl -pip install -r dev_requirements.txt -uv sync # or: reproducible install from the committed uv.lock -``` - -```bash -python -m pytest test/unit_test/headless # headless unit tests -python -m pytest test/integrated_test/ # cross-module workflows - -ruff check je_auto_control/ -pylint je_auto_control/ -bandit -c pyproject.toml -r je_auto_control/ - -python test/verify/typing_contract_verify.py # mypy, whole package, three target platforms -python test/verify/typing_contract_verify.py --extras # the same against the real PySide6 / aiortc types -python -m sphinx -b html -W docs/source docs/_build/html # the docs, warnings as errors -``` - -The dev/main headless jobs retain `native--` artifacts for seven -days: merged process output, package/runtime versions and exit status. Linux -runs under GDB to retain all-thread native backtraces; other platforms retain -Python faulthandler output. Test failures remain failures. From a repository -checkout, reproduce collection with `python scripts/ci_native_diagnostics.py ---artifact-dir test-artifacts -- python -m pytest -v --tb=short --timeout=120` -(one command); add `--native` before `--` on Linux with GDB installed. -Literal argv (including whitespace/quotes) and handled `SIGINT` reach the -child unchanged. Linux first verifies the runner outside the suite's debugger; -its preflight logs are included in the same artifact. - -Selected dev pushes run `.github/workflows/ei-lifecycle.yml` in an isolated -libei/libeis container, retaining versions and both native logs for 14 days in -`ei-lifecycle--` artifacts. Half-open and live cleanup children -have 10/60-second deadlines and faulthandler. Unrelated child failures fail CI; -successful cleanup requires begin/end markers. The half-open probe also requires -equal integer descriptor counts; live cleanup releases owned device refs first. -Run 39507190704 on libei/libeis 1.3.901-1 passes 9/9 and 20/20 checks, including -native out-of-region refusal without CLI fallback. Half-open `ei_unref` still -segfaults, so runtime protection remains and helper isolation is pending. -Device pause and sequence readback remain unverified. These controlled socket -peers do not establish compositor consent, physical or multi-monitor acceptance. - -Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) and -[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Two rules the CI enforces: `import -je_auto_control` must never pull in PySide6, and every feature needs both a headless -API and a GUI surface. - ---- +- [Installation, platform support and configuration](docs/guides/en/setup.md) +- [Python, JSON and command-line usage](docs/guides/en/usage.md) +- [AI agents, MCP and server integrations](docs/guides/en/integrations.md) +- [Completion verification and evidence handoffs](docs/guides/en/evidence.md) +- [Development and resources](docs/guides/en/development.md) +- [Implementation notes](docs/guides/en/implementation-notes.md) +- [Documentation index](docs/README.md) +- [Examples](examples/README.md) +- [Progress](Progress.md) ## License -[MIT License](LICENSE) © JE-Chen. -See [Third_Party_License.md](Third_Party_License.md) for the licenses of bundled and -optional third-party components. - -- **Homepage**: https://github.com/Integration-Automation/AutoControlGUI -- **PyPI**: https://pypi.org/project/je_auto_control/ -- **Documentation**: https://autocontrol.readthedocs.io/en/latest/ - -Legacy MCP action wrappers, parallel branches and local DAG workers retain the same origin ceilings. - -Managed point actions accept observation-local element indices or thumbnail image points. The host checks the current frame and resolves native coordinates, including scaling and negative monitor origins. Receipts retain geometry provenance without image bytes. `AgentObservationStale` identifies rejection before dispatch; local agents reobserve only within their retry budget when the adapter confirms no held or pending input. - -Emergency stop returns compact snapshots with metadata.details_deferred; fetch individual task details for full artifact links. - -Managed mouse presses normalize button ownership and confirm the actual cursor before input. Windows pointer checks reject foreign overlays. Vision renders the exact scoped window into cleared private GDI storage, rejects geometry changes and releases resources even on rendering/read failure. There is no desktop-crop fallback. Fake-native tests cover these paths; native acceptance remains unverified. - -The Agent tasks view groups task scope, workflow settings, triggers, skills and recovery into separate pages. Its observation page lists read-only elements and shows a validated, strictly masked JPEG at one rendered pixel per logical widget pixel. Selecting a row or image point only edits a frame-bound action request; Actions -> Perform observed action sends it through the shared task API. Switching tasks clears the preview, and late replies cannot replace the selected task. A new frame requires reselection before an old reference can be sent. Closing the view only detaches its requests. - -Managed workflow waits (workflow_wait / AC_workflow_wait) poll only exact scoped control values or states, with cancellation and a deadline capped by the action budget (default five seconds, maximum sixty). They never replay a write or submit. Fixed skills require all previous receipts to match the pinned sequence before continuing, including after resume; autonomous model loops retain stuck detection. New form/transfer drafts refuse an already-matching confirmation before submit and wait for a fresh transition afterward. Batch configurations may provide new_record_selector to reset each record; confirmations prove the configured UI transition, and transaction-specific receipt values should be used when available. Archive drafts also re-read the exact reviewed manifest and current file digests at finish (one-megabyte manifest and sixty-four-megabyte total evidence limit). - -AgentHumanReview identifies an unsaved-content or unknown-dialog gate. It persists waiting_user and retires input ownership, including for external observe requests; explicit resume still rechecks the gate. Windows detection uses native dialog/disabled-owner evidence and known English/Chinese/Japanese unsaved labels. Workspace tasks also pause for leading/trailing asterisks in document titles; a window entry may supply unsaved_selector and unsaved_value for an application-specific indicator before layout changes. These checks do not infer every application's dirty state. Recognized standard file pickers use a context-local driver on the existing AC_handle_file_dialog executor: exact unique title, same PID, confirmed foreground and canonical rooted absolute paths. UIA control patterns must belong to the actual owned root window, even when another window shares its PID. All behavior has fake-native/loopback coverage; actual platform acceptance remains unverified. - -Host-reviewed targets use AgentTargetProfile and manage_agent_target (AC_agent_target; register/get/disable/enable/probe). Names and configuration are immutable; desktop/file/browser adapters are currently supported; unimplemented kinds are rejected and optional browser helper_python is host-reviewed. Tasks pin the host profile digest and cannot expand its tools, applications, roots or network origins. Availability persists across restart and is checked at dispatch; disabling requests pause/cleanup, while enabling requires explicit task resume. list_agent_targets / AC_agent_target_list / CLI agent-task targets expose passive metadata with readiness=not_probed and native_evidence=not_recorded. Full configuration requires manage_hosts; CLI agent-task target and the GUI Host targets page use the same service. Live anonymous MCP tool sessions have operator authority across direct and legacy wrapper calls; MCP host management requires an authenticated administrator. Trusted direct Python callers remain unchanged. Browser automation belongs to WebRunner (je_web_runner), with D:/Codes/WebRunner as the development source; browser profiles use the managed je_web_runner SDK contract, and dependency probes do not establish native readiness. - -Existing browser automation, including open_path(URL) and AC_open_path, delegates to WebRunner (Python package je_web_runner). URL plans now report backend=je_web_runner; callers inspecting the previous webbrowser descriptor should use the new value. Signatures and local-file opening stay compatible. URL execution requires the configured WebRunner project and propagates WebRunnerBridgeError when unavailable, without opening an OS browser as a fallback. The development source is D:/Codes/WebRunner. Planning and injected-opener tests remain usable without that package; browser protocol support is determined by WebRunner and its selected browser. Existing dedicated browser GUI/MCP/AC paths and recorded WR_* actions share the same bridge. - -## Explicit local DAG evidence handoffs - -Existing recovery children held by another caller can provide completion evidence to their -original local DAG through an explicit revocable handoff. In `manage_agent_recovery`, use -`review_handoff` with the final `task_id`, `batch_id` and `node_id`; an authorized manager then calls -`create_handoff` with the same IDs, returned `handoff_review` as `review`, and a nonempty `note`. -The service derives the recipient from the real original admission. In a `review_continuation` -successor decision, explicitly include `handoff_id` alongside `node_id`, `action` and `task_id`, then -review and approve the whole continuation. At most sixteen real recovery links are supported, -including a privately admitted permanent read-only final verifier. Ordinary task ownership remains. - -`get_handoff` and `revoke_handoff` take `handoff_id`; `list_handoffs` takes `batch_id` and `node_id`. -Issuance and consumption refresh actual owners, admitting reviewers, issuing-session root witnesses, -current consumer ceilings, fixed scope, effect snapshots, independent completion and retirement. -Approval, start and late dependency validation recheck consent; revocation or evidence loss blocks -adoption. Grants expire no later than the earliest retained terminal witness's existing thirty-day -deadline. Returned data contains bounded IDs, hashes and status, without private task arguments, -captures or principal-store paths. No ordinary task-read/input access, ownership transfer or replay is -granted. Cross-host and non-DAG handoff contracts remain outstanding in `Progress.md`. - -The Agent Tasks Handoffs page has an operation selector and JSON editor; Actions prepare review, -create and revoke requests without dispatching them. Five editable `agent_handoff_*.json` examples -cover review/create/get/list/revoke. Python, AC, CLI, authenticated MCP, REST and Builder use the -same recovery operations. These checks establish contract and owned-file behavior; deferred native -desktop, browser, device and 24-hour acceptance still require their own evidence. - -## Explicit read-only completion authorization renewal - -When original origin references are expired or unavailable, explicitly call -`manage_agent_recovery("review_completion_authorization", {"task_id": ""})`. -Review the server-derived `verification_spec` and retained/replaced/current origin context, then call -`create_authorized_completion` with the same `task_id`, returned `snapshot`, `authorization_review` -and a nonempty `note`. Optional `owner_policy="source_owner"` requires the returned `ownership_review` -at creation. Callers cannot supply a replacement verification spec. Existing live constraints stay; -new roots intersect the original ceiling, prior reader ceiling and current session. Ordinary -completion review does not replace this explicit consent for an already renewed reader. - -The child is permanently read-only. It independently checks current conditions against the actual -confirmed original effects, without input, replay, restoring captures or modifying old witnesses. -Source/effect snapshots, real owners/reviewers and original DAG admission are rechecked. Task admission -and final completion each revalidate inside their own SQLite writer after SQL; changes roll back. -At most sixteen actual recovery links are supported. A retired successful reader may be explicitly -renewed again, retaining its previous narrower ceiling and all still-valid inherited restrictions. -Changed source/effect evidence remains refused and must not be silently repaired by scope renewal. - -Historical `get` preserves succeeded state; loss of renewed authority makes its current -`completion_contract` zero and `completion_authorization` unavailable. DAG adoption and late dependency -validation then refuse that evidence. Malformed/missing renewed read-only markers fail before helper -startup. Recording with `completion_task_id` uses the approved restricted scope and original semantic -actions, but the draft still needs its own fresh validation trial. Renewal does not publish an expired -candidate or renew a published skill grant. Existing skill reauthorization remains separate. - -Python, AC, CLI, authenticated MCP, REST and Builder share both operations. The Recovery page exposes -two explicit Actions using its selected task, owner policy and request editor. Editable examples are -`agent_completion_authorization_review.json` and `agent_completion_authorization_create.json`. -Remote read-only providers, cross-host handoffs, actual application -state restoration and deferred native/device/browser/24-hour acceptance remain in `Progress.md`. - -## Explicit renewed-reader completion handoffs - -Existing `review_handoff` / `create_handoff` can explicitly transfer completion evidence from -a privately renewed, permanently read-only reader to its real original local DAG. Select that reader's -task ID and the actual original batch/node. The service derives the proof; callers cannot supply a -policy, ownership override or authorization bundle. Ordinary handoffs keep their existing rules. - -The preview's `evidence.completion_authorization` contains the completion task/review, a bound review -digest, approved-root count and replaced/retained/current origin IDs. It omits private principal paths, -action arguments and captures. Set creation's `review` to the returned top-level `handoff_review`, then -provide a nonempty `note`. Every actual task keeps its reviewed ceiling; all live historical restrictions stay, unavailable -references are explicitly reviewed, and the issuing session's additional constraints remain live. -The grant uses the exact already-verified reader roots. A different intersection requires another -real completion review and verification. The consuming session/profile still applies its own limits. - -At most sixteen actual recovery links may mix previously reviewed executable successors and private -readers. A succeeded intermediate reader needs actual private historical scope and retirement proof; -an ordinary succeeded source does not gain that exemption. No helper is launched or input replayed -while granting or adopting evidence. Old source state, witnesses, receipts and all task owners stay. -The original owner receives only the bounded completion projection, without ordinary access to the -other caller's task. Revocation or lost authority blocks adoption and late dependency validation. - -Original accepted-request hashes, raw submission witnesses, private admission, graph, owners/reviewers, -all real source/child snapshots and the leaf renewal remain bound. Reads and post-write checks use -the same SQLite writer, including uncommitted changes; mutation rolls back admission/grant creation. -An inherited `dag_batch` option is not admission: a bounded real recovery chain must resolve the actual -original request and admitting identity without creating a replacement admission row. Earlier ordinary -completion binding hashes remain compatible. Each historical task retains its own policy review; -combining history cannot bypass the normal sixteen-live-origin limit or any original root ceiling. - -Exact active retries retain their note and ID; revoked IDs never reactivate. Restart and adoption -preserve the earliest retained terminal witness's thirty-day deadline. Historical get/list/revoke stay -available after an origin expires, while that history supplies no usable completion or input grant. -Python, AC, CLI, authenticated MCP, REST and Builder share the five existing operations. Existing -Handoffs Actions and its JSON editor/result view show the explicit renewed review without dispatching -consent automatically. Cross-host handoff, remote readers, actual application/device -providers and deferred native/browser/device/24-hour acceptance remain in `Progress.md`. - -## Explicit task-source completion evidence handoffs - -The five existing handoff operations also accept a real non-DAG source task: - -- `review_handoff`: supply `source_task` and the actual final evidence `task_id`. -- `create_handoff`: add the returned top-level `handoff_review` as `review`, plus a nonempty `note`. -- `list_handoffs`: supply `source_task`; `get_handoff` and `revoke_handoff` still use `handoff_id`. - -Task-source fields and DAG batch/node fields are mutually exclusive. The service resolves persisted -grant IDs to their actual storage family. Original DAG ancestry must use its real batch/node route, -even if a later read-only reader dropped its `dag_batch` option. No synthetic DAG node or admission -is created. Ordinary standalone tasks need no invented submission witness or idempotency key; -any actual accepted request is bound and rechecked on the same SQLite writer. - -Select `handoff_id` explicitly in existing skill operations. `record` uses a separate verified reader -through `completion_task_id` and creates a draft which still needs its own new validation trial. -`accept` with `completion_task_id` keeps the actual original candidate's validation task. -`review_execution` and its matching `accept` may select an actual `execution_task_id`; add -`completion_task_id` when the final granted evidence is a separate reader. The service verifies -the exact complete original semantic action plan, real execution IDs and independent final criteria. -A reader never becomes an execution task or a substitute validation trial. - -The grant yields only a private bounded evidence view. Original task owners, source state and -receipts remain; ordinary get/list/observe/act/resume access never expands. Granting or adopting -launches no helper and replays no input. Real source/child snapshots, original optional requests, -actual owners/reviewers, retired input and every live historical origin remain checked. New recorded -drafts retain both issuing and consuming session ceilings. Unavailable restrictions require actual -private completion renewal; matching hashes or caller-authored scope flags cannot replace it. -Read-only evidence adoption does not renew a published skill's original input authorization. - -At most sixteen real recovery links include source ancestry and the forward granted chain. Earliest -retained terminal evidence expires after thirty days; anchoring at a later reader cannot extend an -older ancestor. Same-writer post-insert and exact-retry checks honor revocation tombstones for both -DAG and task grants. Source/request/role/origin/revocation changes roll back grant creation, draft -recording or publication. Revoked IDs never reactivate. Historical get/list/revoke after an origin -expires expose bounded IDs and hashes, not continued completion or input authority. - -The Handoffs page explicitly selects original local DAG or original task when preparing JSON. -Three skill Actions prepare recording, publication or execution review with a handoff placeholder; -they do not issue consent or publish automatically. Python, AC, CLI, authenticated REST/MCP and -Builder share the same operations and actual caller identities. Editable requests are -`agent_task_handoff_review.json`, `agent_task_handoff_create.json`, `agent_skill_recording_handoff.json`, -`agent_skill_completion_handoff.json`, `agent_skill_execution_handoff_review.json` and -`agent_skill_execution_handoff_accept.json` under `examples/`. - -Cross-host handoffs, remote readers, actual application/device providers, deferred native -and twenty-four-hour acceptance, and unresolved HTTP409/bootstrap issues remain in `Progress.md`. - -Installed wheel and source distributions include the REST Dashboard and Swagger HTML, CSS and -JavaScript resources. The same localhost REST routes and authentication rules apply to an -installed package; serving static pages grants no task or desktop input authority. +[MIT](LICENSE) © JE-Chen. [Third-party licenses](Third_Party_License.md). diff --git a/README/README_zh-CN.md b/README/README_zh-CN.md index 259a84b56..1710ace94 100644 --- a/README/README_zh-CN.md +++ b/README/README_zh-CN.md @@ -1,1331 +1,56 @@ # AutoControl -成果移交管理已共用 `manage_agent_transfer(operation, request)`、`AC_agent_transfer`、 -`ac_agent_transfer`、已授权的 `POST /agent/transfer` 与 Script Builder metadata。CLI 使用 -`agent-task transfer --operation review_export --request request.json`。审阅返回批准 token; -创建须提供该 token、原请求 key 与明确 note。导出/导入管理可指定已登记主机; -可携证据管理也可指定已登记主机,由来源核实私有权限。传输页提供四语 Actions、可编辑 JSON 与服务回复; -审阅不自动批准,批准模板保留原主机、token 与 key 并留空备注。选项变更或关闭页面后, -旧回复不覆盖画面,已接受的导入仍由服务持有。远端批准先保存明确同意,失联或协调端重启后以原键重发,保持同一授权。 -被动诊断仅列出本机契约,不代表即时授权或远程/原生能力已验证。只读完成证据在创建与使用时重新核实原私有同意,不恢复原输入权限。 -实现验证记录见 docs/updates/README.md;其余交付与验收见 Progress.md。 -examples/agent_transfer_export_review.json、agent_transfer_import_review.json 与 -agent_transfer_evidence_review.json 提供可编辑请求,并各有独立的 create 模板。 +[English](../README.md) | [繁體中文](README_zh-TW.md) | [简体中文](README_zh-CN.md) -实验性的来源主机技能操作,可通过现有 `handoff_id` 明确选择可携授权与完成/执行任务。 -来源在技能事务内重新核对实际同意、接收者与私有证据,候选/发布写入后再次核对。 -保留原始动作、候选自己的验证试跑与明确版本批准;新的技能试跑建立服务生成的全新请求 key, -不为旧有未带 key 的试跑补造记录。此流程不将外部动作或策略移交协调端; -技能证据保留来源主机的原动作/试跑/版本;其余跨主机验收与交付见 Progress.md。 -选择移交证据的技能操作,全程保留 runtime 所有权,操作结束后才释放。 +AutoControl 是用来操作桌面应用程序的 Python 自动化框架。你可以控制鼠标与键盘、截取画面,并通过图片、OCR 或无障碍 API 寻找界面元素。支持 Python、JSON 动作文件、桌面 GUI 与 MCP 客户端。 -目的端导入目前仍为实验功能。明确启动的服务可通过 runtime 移交控制器与经验证的 -`/agent/transfer` 接受 `review_import`/`create_import`/`get_import`/`run_import`/ -`cancel_import`/`list_imports`。协调端可通过自己的不透明同意 token 路由这些有限操作; -目的端使用自己的来源登记与账号,不转发协调端 principal/origin 或来源凭据。 -批准意图在派送前提交;回复丢失后的精确重试仍对应同一笔导入。 -启动时接回已批准且尚未领取的工作;未结算 claim 会转为待审阅。明确的 `run_import` -以新队列代次重新核对原收件者、profile、实时 origin 与来源 grant,可重用已验证私有分块, -或只读核对既有完整目录与哈希,不重新下载/发布。续行时新增的 origin 限制仍持续生效。 -已明确排入队列且未领取的只读核对可跨再次重启;采认前重验当前字节、profile 与保留的 origin。 -导入收据确认完成前,目的端会在最后一次来源回复后重新核对完整文件清单与内容摘要。 -文件遭改写、丢失或增加未列入清单的文件时,导入保留 requires_review, -保留用户修改与原发布成果供审阅。 -目录身份、字节或权限变更不能确认发布。取消会使生产者失效;尚未完成收据确认的 -发布保留 requires_review,已确认发布的文件保留为用户成果。 -取消或过期的私有分块账号须确认生产者退出才清理;失败时保留配额,成功重试后才释放。 -收据维持原本固定期限。 -暂存目录与预先创建的文件会在复制字节前记录文件系统身份。生产者退出后, -过期清理可于重启后重试;遇到替换或无关对象时保留配额待审阅,不递归删除。 -来源维护会清理过期或已撤销的私有导出账号,包含重启或授权者移除后;失败时保留配额。 -来源或目的端清理完成前持续保有 runtime 所有权;无待清理数据时不获取 runtime 写入锁。 -创建/续行回复会在唤醒新投递前读取已提交的收据;后续以 get_import 查询当前进度,避免回复被新 writer 阻塞。 -后续维护会修剪已清理、撤销且过期的来源元数据以回收记录配额,保留同意/撤销凭据与其他记录类别。 -冷启动维护以只读探测发现待处理来源记录;没有待处理记录时不创建移交控制器。 -runtime 最后释放所有权时会与控制器构建互斥,并重验后建立的控制器是否退出;忙碌时保留所有权供稍后重试关闭。 -私有缓存路径重定向会在打开存储前拒绝;清理失败时保留配额。 -后续维护会在私有数据确认清理后,回收到期的目的端导入/派送元数据及其已结束队列记录。 -仍在执行、身份被替换或未知状态的队列会阻止回收;原同意/撤销凭证与已发布用户文件保留。 -冷启动维护不启动监听端或生产者;待清理账户的扫描不受大量未到期历史记录遮蔽。 -可移植证据保留与共用接口已接入;其余故障交错与正式交付见 Progress.md。 -来源证据实验功能已接入 owning runtime 与具名/共用账户的本机 transfer HTTP 管理路径, -提供 review_evidence/create_evidence/get_evidence/revoke_evidence/list_evidence。 -独立持久授权沿用真实恢复/完成验证、当前账户与原本机 DAG 审核;已登记 peer 的 evidence -读取核对实际接收的 key/规范与 DAG 节点,只返回 ID、哈希及有限验证,不授予一般任务读取或输入。 -审阅摘要不含 node.request_digest;即时读取才按精确已审阅原请求补入。 -来源主机技能证据、远端管理路由与共用接口已接入;其余故障验收与交付见 Progress.md。 -协调端 DAG 的实验采纳已接入独立审阅的远端恢复授权,固定原来源/key/规范/graph/node 与主机。 -批准与启动先持久保存暂定状态,离开本机 writer 后即时验证来源,再核对原同意与认领,才启用。 -停止会取消暂定状态;中断后只可用同一明确批准请求续接。确认期间保留 runtime 所有权, -不把独立 peer 读取串行化;认领/记录及最终采纳前后重新验证。 -授权失效会阻止后续调度,只对精确已接收的下游任务请求有限暂停;回复未知或丢失时保留认领并待审阅。 -已完成副作用与无关任务保留;不宣称已证明原生输入退休或完成整份故障矩阵。 -旧投递格式升级会保留原批准 origin 与固定期限;多次续行的额外 origin 仍累积生效。 -停止附加的 REST 观察端不会重派或取消服务持有的导入,也不释放 runtime 所有权;重新连接可读取同一笔成果。两主机与独立进程三主机测试已核对实际字节及账号范围。 -更多重启/取消交错、更多暂存故障交错、完整保留、可移植证据、client/GUI 接口与完整阶段检查 -仍列于 Progress.md;移交收据不授予任务输入权限,也不能证明任务完成。 +## 开始使用 -来源导出的远端审阅/创建/查询/撤销已接合。协调端发出自己的不透明审阅 token, -绑定实际本机调用者、当前主机/凭据摘要、来源审阅、清单摘要与原 key。批准意图在转发前 -持久提交;回复丢失或协调端重启后,相同批准仍取回同一来源成果。更换调用者、主机、凭据、 -note/key 或来源回复摘要即拒绝。待审阅与持久路由各限128条;到期只清理本机路由 metadata, -保留同意边界。关闭 runtime 会清除尚未批准的本机审阅缓存,已批准的持久意图仍可恢复。 -来源使用自身账号,本机 principal/origin 不转发。目的端导入、可移植完成证据与公开接口均已接入; -其余验收与正式交付见 Progress.md。 - -既有远端 DAG 在固定主机配置及每次保留连接调用前后,均读取实际持久化通讯录。 -其他进程替换/移除端点或凭据、配置损坏或原本本机调用者被撤权时,操作会失效。 -读取不建立 console,也不隔离通讯录;既有本机服务委派与封闭远端路由保持兼容。 - -跨主机成果移交依明确审阅与各主机本机授权运行。来源核心可审阅已完成文件成果,建立不可变 blob, -并核对实际发行者/接收者。来源管理与 peer 只读 HTTP 路由已可提供经审阅的清单/分块。 -Peer 使用接收端本身的 bearer/RBAC 与速率限制,在外部 principal/用户数据库查询前拒绝 -本机 principal/origin header;本机服务 client 仅在管理流程保留实际所有者委派。 -移交请求在服务器读取前限制为1MiB;受限 client 在派送请求与解码成功/错误回复前核对上限, -不变更一般 HTTP 的既有上限。完整私有授权链/生命周期验收、目的端发布/ -证据采纳及共用公开接口已接入;其余验收与交付见 Progress.md。移交收据不授予任务输入权限。 - -来源导出在打开选定文件前,排除实际 runtime/移交数据库与 sidecar、当前来源所有者及 -发行者的用户数据库、服务连接文件与专属证据目录。服务登记实际私有文件,不保留一般成果的 -同名文件名;manifest 只核对选中的输出。Peer 读取与相同请求重试会重新核对当前路径权限, -不重新哈希历史用户成果,并保留操作期限。DAG 成果沿最多十六层真实恢复链核对原始 -提交任务、实际请求及本机 DAG admission,重新授权接纳者,并排除其不同位置的账号数据库。 -恢复子任务不补造提交记录;正常 standalone 不要求 DAG 提交记录。私有恢复链摘要在审阅、建立、 -相同请求重试与 peer 读取时重验;实际私有恢复所有者/审阅者绑定也纳入摘要,其数据库保持私有。 -来源操作在字节存取与 grant 写入边界配合取消;提交后回复被取消仍可依固定意图精确取回。 -成果期限依完成来源 updated+30 天计算,不因重试/重启刷新,也不改用较早祖先的期限。 -本机只读 reader 依当前私有完成授权导出,旧输入仍撤销;自动清理、目的端发布与证据采纳已接入。 -其余提交/撤权交错验收与正式交付见 Progress.md。 - -Runtime 透过实际 batch 主机 adapter 保管 TransferPeer;具名传输固定端点/凭据,于 HTTP 前后 -重读持久化通讯录并核对当前本机调用者。来源端使用自身凭据验证,不接收本机 principal/origin -header。来源私有排除只取得实际通讯录路径,不建立/重载 console 或隔离文件。封闭清单与规范 base64 分块须符合 -导出 ID/摘要、每块最多256KiB及原始期限;URL 路径前缀同样套用1MiB移交上限,一般 HTTP -保留既有上限;无效预算(含过大整数)在派送前回报类型化错误。两/三主机 -导入交付仍待完成。 - -空闲后台 worker 以只读预检识别空队列,减少轮询与任务状态、完成事务的写入锁竞争。 -发现工作后仍须在原有事务内重新核对与领取;保留 claim 代次、过期工作回收与重试上限, -不延长任务或传输期限。 - -租约维护会在停止事务内核对实际输入所有者与世代。延迟的监视程序不能改写已退役任务的 -恢复证据,也不能取消新租约;接受的最终停止状态与取消 token 会先于停止事务发布。 -仍有效的权限撤销与原有期限持续生效。 - -副作用已确认的浏览器任务,可通过已有完成审核与技能流程读取原来的 WebRunner context。 -原 helper 先永久结束 SDK 输入/网络,再释放输入 journal/租约;runtime 最多保留 16 个 context, -自分离前预留起最多保留 300 秒,不因分离耗时延长。预览/创建核对实际 effect task 的实时 SDK view;验证只借用原 context -读取最新有界 DOM/字段值,不重新配置输入、不 ACK 原生输入、不传输,也不另开浏览器或 helper。 -退出切换、能力探测与清理也拒绝嵌套工具与原生输入。 -同 profile 的不同任务分开保管,context ID 本身不授权。私有完成授权审核可在原上限内明确续授权 -验证 scope,原输入规范不变;已失效输入 origin 与有限私有保管本身均不授予读取权限。 -拥有者删除、目标停用、来源变动、期限或读取失败会使 context 失效;只有确认进程结束才释放 -进程拥有权,清理失败持续跟踪。重启不恢复页面,网络结束后的 DOM 不能当作新服务器数据。 -Python/AC/MCP/REST/CLI/Builder 与 GUI Actions 共用原审核 request;技能录制保留原动作, -发布须使用自己的实际新验证试跑与明确选择的完成证据。示例见 -`examples/agent_browser_retained_completion.py`。冷启动浏览器前缀重建、remote reader、正式部署, -以及暂缓的原生/浏览器/真机/24 小时验收仍待完成。 - -已停止且副作用已确认的任务,可用 `manage_agent_recovery("preview_completion", {"task_id": id})` -审核独立验证任务,再将精确 task_id/snapshot 与审核说明交给 `create_completion`,最后完成新任务。 -私有原子绑定只选择永久只读 helper,不重播来源动作;须有新鲜独立完成条件与输入退出证据。 -skill 计划须全部确认;动态任务不得含未处理的有限计划或未知效果。 -可先 observe 再 finish;相同 helper 配置只重新检查就绪,不替换权限,也不缓存就绪结果。 -来源/审核者权限持续有效,覆盖清理后、明确重试与重启。API/AC/MCP/REST/CLI/Builder 及 GUI Actions 共用此流程。 -remote reader、正式部署仍列于 Progress.md;桌面能力仍须另行原生验证。 - -只有受管任务节点的 DAG,可用 `manage_agent_dag("register", {"definition": graph, -"max_parallel": 4})` 注册持久批次,再明确 `run_dag(graph, batch_id=batch["batch_id"])`。 -注册不操作目标;保存整张图的拓扑、节点契约、主机设置与并行数,目标端 key/规范标记绑定批次。 -可能派送前先提交 claim,目标端精确规范、完成及输入释放证据通过后才放行依赖节点。成功、中断或 -提交回复遗失后都不能再次 begin;`get/list/inspect` 让协调记录跨重启保留。API/AC/MCP/REST/ -CLI/Builder 及 DAG Actions 的批次注册/读取、选填批次 ID 共享流程。 -停止后用 `review_continuation` 获取只读整图快照及逐节点决策,再把审阅的 `snapshot`、`decisions` -与非空 `note` 放入 `run_dag(graph, batch_id=id, recovery=request)`,批准并使用一次续接机会。 -只能采纳独立完成的原任务或真实 recovery 后继任务;派送限从未 claim 且目标端未接收的 pending -节点。本地授权可在相等或更窄根目录内更新,未知 claim 永不重放。DAG Actions 提供停止新派送、 -审阅及明确续接;已接受任务仍依自身生命周期处理。将协调交给已明确启动的服务,可调用 -`manage_agent_dag("run_background", {"batch_id": id, "definition": graph, "max_parallel": 4})`; -明确批准的续接另带 `approval_id`。DAG Actions 提供两个后台动作;关闭视图不停止已接受的服务工作, -`get.background` 提供有限队列状态。重启使旧 attempt 失效并要求审阅,不重放排队或未知派送。 -原 owner 与提交者的权限持续重新验证,本地任务绑定所属 runtime。 -既有 `prune_agent_tasks()` 与每小时维护会回收过期且未使用的注册及已安全结束的成功批次,默认 30 天。 -未决批次持续保护任务/恢复证据与接收 gate;结果新增 `deleted_batches`、`deleted_dag_deliveries`。 -其他队列与用户成果不受影响,远程证据保留仍须明确移交契约。 -caller 协调的受管批次固定来源服务路径、端点、凭证指纹及世代,本地节点共用同一 client;连接文件 -身份变更就停止后续调用并要求明确审阅。服务端批次证据直接读取所属 runtime,绑定不缓存 bearer -凭证。普通非批次 client 保留动态连接行为;受管批次须有含世代的连接数据。 -本地批次节点在持久 claim 后使用来源服务的封闭 `local_task` transport,以原 owner 接收精确规范/ -key,并在事务内记录真实 caller。输入前更新双方权限及 attempt;管理员失去跨 owner 管理权也会 -阻止执行。没有可信接收记录的旧请求不补造见证。任务 metadata 提供有限 `local_dag_admission` -审计数据,已接受输入仍依既有清理契约处理。 -若恢复后继任务须让原所有者读取,preview/review_authorization 请求加入 -`owner_policy="source_owner"`,明确 create/create_authorized 时另带回 `ownership.review` 为 -`ownership_review`。后继任务保留来源所有者,事务内另记实际审核者,输入前持续验证双方权限。 -GUI 提供所有者选择;省略策略仍由创建者持有,沿用既有读取隔离。DAG 可用正常恢复证据采纳独立完成 -的原 owner 后继任务;已存在的 caller-owned 子任务不自动变更归属或补造此记录。 -详见[续接协议](../docs/source/Zh/doc/ai_agents/agent_dag_batches_doc.rst)。 - -触发器可明确使用 `manage_agent_trigger("review_authorization", {"trigger_id":"..."})`,再以 -`create_authorized` 提供 `trigger_id`、`snapshot`、`authorization_review`、经审阅的 `spec` 与 `note`。 -新注册保留完整模板/设置/待处理上限,受原授权、仍有效限制与当前权限交集约束;事务内停用旧绑定, -并启用未来通知。共享历史让已接受事件与未完成任务跨更新、移除及重启保留,继承的旧排队事件不再派送。 -计划从未来时段开始,文件检查点保留。API/AC/MCP/REST/CLI/Builder 及 GUI 触发器菜单共享流程; -普通启用不能取代失效授权,审阅只准备注记留空的请求。 - -已发布技能可用 `manage_agent_skill("review_authorization", {"candidate_id":"..."})`,再明确 -`create_authorized`,提供 `candidate_id`、`snapshot`、`authorization_review`、经审阅的 `spec` 与 -`note`。完整计划与参数定义固定;保留原根目录上限及仍有效限制,与当前权限取交集。流程只创建 -同一技能的新草稿及审计证据,须重新验证并明确发布下一版,旧版本不变。相同批准去重,过期版本/ -授权内容拒绝。API/AC/MCP/REST/CLI/Builder 与 GUI 技能操作菜单共享此流程;trigger 更新使用上方独立流程。 - -来源授权失效的停止任务,可明确使用 `review_authorization`,再以 `create_authorized` 提供 -`task_id`、`snapshot`、经审阅的 `spec`、`note` 与 `authorization_review`。新任务保留所有仍有效的 -来源限制,将当前权限与原根目录上限取交集;根目录只可维持或缩小,其余权限、模式/模型、预算及 -完成条件固定。批准证据与唯一新任务在同一事务保存;来源及已撤销的见证不变。现有共享接口均提供 -这两种操作,GUI Actions 另有授权审阅/创建命令,详见[恢复指南](../docs/source/Zh/doc/ai_agents/agent_recovery_doc.rst)。 -任务恢复不解除输入隔离,也不重建应用状态;技能与 trigger 使用上方独立更新流程。 - -停止的任务可用 `manage_agent_recovery("preview", {"task_id": "..."})` 审阅来源回执与快照, -不接触应用程序。有限 skill 提供剩余动作及逐条结果;外部 agent/本机模型任务则提供空白目标的 -`review_template`,须由操作人明确填写剩余工作目标,不复制旧动作列表。明确 `create` 时提供 -快照、经审阅的规范与注记,创建有来源关联的新任务,重新观察并从零回执开始;重复批准返回同一 -任务。执行模式、模型/端点、范围、预算及完成条件固定,未知副作用须先人工核对;不移植旧 -capture、索引、坐标或已完成历史。可用 `AC_agent_task_recovery`、MCP/REST、 -`agent-task recovery preview|create request.json`,或「Agent 任务 → Actions → 审阅剩余工作/ -重新规划/创建经审阅的新任务」。已移交的来源不能再恢复,须由新任务继续。 -登录与窗口状态的恢复须明确声明,不能推断:继任任务(或任何任务)可列出 `resume_conditions`,只接受 -`screen`、`browser` 与 `file_*` 条件(回执是历史,不能证明现状);第一个动作只在新观察全部通过时 -才被接受,任一不成立或无法判定就转为 `waiting_user`,不会动作;有任何动作回执后此关卡即结束。 - -Android/iOS 内置受管 profile 仍未提供。内部远程副作用防护按实体设备标识保存动作前/后确认; -本地 helper 结束但动作未确认时,仍保留隔离。恢复须在 writer 退出后取得可信设备证据,再以 -后续能使旧指令失效的世代证明安全。尚无内置 SDK 证据来源、设备 profile 或原生验收; -剩余接合列于 `Progress.md`。 -内部 Android 传输只连接明确设置的现有 loopback ADB server,不调用 CLI、不管理 daemon、 -不重试或退回旧 shell;shell-v2 的退出证据有封包/输出上限,但不代表应用完成、实体设备 -身份或输入已释放。 -内部 Android session 会核对指定端点、实体序号、boot 与默认显示器焦点,并以原子方式固定 -boot。有限输入提案在命令连接内重验身份/焦点,限制文字与结果;提案不授权输入,仍须接合 -输入窗口、遮挡、锁定/真人活动与自有 worker。 -Android 检查后提案会绑定当前的原生输入窗口/队列及 keyguard 证据,核对完整触控路径、 -外部拦截与遮挡,并在命令连接内重验摘要。旧 ANR/历史记录不能证明当前状态;真人活动、 -全局监视器审阅仍须可信来源授权,内置受管设备执行仍未开放。 -内部 Android 动作协议 v2 区分完整前置拒绝、输入失败、输入后拒绝与输入返回。 -缺少/错误阶段或退出码不符都维持未知;输入返回不代表远程输入已清空或任务完成,也不授权重试。 -内部自有远程 SDK worker 会核对精确任务/所有者范围、重新授权与真人接回;可信主机 factory -创建前先启动 parent 监视。持久化 begin 并收到 ACK 后才调用 SDK,相符设备/世代的清理证据 -通过后才发送 end;缺证据维持隔离。可信设备控制来源、WDA adapter 与受管 profile 仍待接合。 -命令编译器以一次带标签的提取核对三个原生焦点字段,接受六种顺序,缺少/重复/空值仍拒绝。 -前后身份与输入安全检查、原本动作期限均保留。自有 POSIX 假设备减少 Git Bash 读取进程且维持 -原始文件 bytes;有限阶段/耗时诊断不含命令、参数或输出。 -内部 AndroidRemoteAdapter 已通过逐命令 AndroidCommandLease 接合 checked session 与 worker; -每个动作消耗一次新的身份/输入路由/安全观察,SDK 重新编译有限命令后才通过 ADB 发送一次。 -设备端防护须在真人接回、取消或到期后阻止旧写入;没有默认 provider,标准 ADB 或停止本地 -helper 不能提供这项保证。清理证据还须绑定新的随机命令 ID、boot 及独立输入/队列状态。 -可明确配置主机 hierarchy_reader,提供有界、限 app 的语义元素及经过审阅的非敏感文字;未配置时 -仍只有身份 metadata。XML 不授予文字权限;编辑/密码值及受保护子节点持续遮罩,不发布原始 -XML 或私有 freshness hash。公开观察版本随来源及动作更新;Android 元素引用须来自当前可操作 -的语义元素。新的画面读回可确认已审阅文字出现,缺少/部分/遮罩内容不能证明文字不存在。 -不新增 CLI/SDK 启动或捕获备用;真实来源、受保护字段值验证、Unicode/IME 与受管 profile 仍待交付。 - -受管画面完成验证将内置桌面与 WebRunner 预览视为部分文字证据;文件目标与等待窗口阶段没有 -语义画面证据。已知安全文字可确认出现或推翻不存在条件,遮罩与明确隐藏的标签不可作证。 -组合条件缺少任一必要证据时保持未知,已知矛盾则判定失败。精确 DOM/字段值应使用明确的 -浏览器完成读回;未声明覆盖标志的自定义 target 保留既有行为。 - -`lookup_agent_task("键", reviewed_spec)` 可选择由目标主机规范化规格,与原所有者提交时保存的 -不可变摘要比较;回复声明 `spec_match_contract=1`,并提供一致/不同/无法核对/查无记录。 -CLI 可加 `--spec reviewed.json`;AC/MCP/REST/Builder 共用可选对象。DAG 视图先查键,再在 -目标端明确支持契约时核对已审阅的节点规格;旧端保持 `unverified`,本地来源 witness 不发到远程。 -键改指向别的任务会使旧快照失效;规格一致时仍须核对完成报告的种类、数量与通过结果。 -节点比较不等于整个 DAG 拓扑/原批次批准, -`resume_permitted=false` 仍保留明确继续审阅。 - -`inspect_agent_dag(definition, timeout_seconds=30)` 可查看本地/已登记远程主机的现有提交, -不提交、不暂停、不续跑。提供 `AC_agent_dag_inspect`、MCP、REST 动作、CLI -`agent-task inspect-dag reviewed.json`、Builder 与 DAG Actions。最多 100 节点、最长 300 秒; -远程仍须主机管理权限,不发送本地身份/数据库路径/来源 metadata,不返回远程路径或原始错误。 -`recorded_completion` 仅描述查回的任务;节点规格可选择核对,`resume_permitted=false` 仍表示尚未 -授权整个 DAG 继续。查无记录不代表拒绝;GUI 在图编辑后丢弃旧视图。 - -提交回复丢失时,可用 `lookup_agent_task("原去重键")`、`AC_agent_task_lookup`、MCP、 -`POST /agent/lookup`、CLI `agent-task lookup 原去重键` 或任务视图 Actions 查询。仅读取原身份及 -用户数据库范围,不提交、不续跑、不取得输入控制权;`found=false` 只是当前快照,迟到请求仍 -可能被接收。GUI 不会让旧查询回复覆盖后来选择的任务/键。DAG 视图也使用此查询;规格绑定及继续审阅仍待完成; -只读查询仍须具任务访问权限。 - -现有 `run_dag`/`AC_run_dag`/MCP `ac_run_dag`、REST/CLI 动作文件、Script Builder 与 DAG -Actions 菜单支持受管任务节点:以 `task` 替代 `actions`/`action_file`,包含 `spec`、必填的 -`idempotency_key` 与可选的 `wait_seconds`。省略 `host` 使用明确启动的本地服务;远程使用管理员 -已登记的主机。目标端须已配置有后台派送的授权 runtime,本功能不部署服务。规格限 skill 或明确 -配置的本地模型模式,工具、目标主机路径及完成条件由目标端验证。 -节点只提交一次,等待完成条件通过、持久完成契约及输入释放证据后才启动下游。同一批次恢复 -须保留去重键;不自动恢复暂停任务或重放副作用。停止、超时或通信/权限失败时,已知任务 ID -才会提出有时限的暂停;未收到确证仍为未知。失败结果保留 ID/去重键并阻止依赖节点,GUI -表格显示任务 ID。本地身份、用户数据库路径及来源 witness 不发送到远程。正式多机部署及原生/ -设备验收仍分别跟踪。 - -DAG 类型与函数也可从 `je_auto_control.api`/`je_auto_control.api.core` 导入。 - -受管 HTTP 暂停/取消/停止全部/关闭服务使用独立的每 IP 配额,与普通流量同为每分钟 120 次、 -突发 30 次;状态查询不会耗尽停止请求的配额。登录、实时角色、任务归属、审计与有界输入清理仍须 -通过。共享客户端也为 DAG 批次/节点暂停保留传输容量;`/agent/dag` 的控制标头仅接受封闭的暂停 -请求,其他带标记的操作在派送前拒绝。自定义认证门保留自己的契约;这不保证 OS/网络饱和时的优先权。 - -受管任务在确认输入清理后才发布成功。清理失败或仍忙碌时保留输入租约并要求审阅;确认前 -中断仍需恢复。完成发布采用条件式状态转换,不覆盖同时到达的取消请求。现有 GUI/API 任务 -结果通过 `metadata.input_released` 显示释放状态;新成功记录保存 `completion_contract=1`,旧记录 -保持零而不自动认证。产物报告按最终状态更新,供后续 DAG 协调判断。 - -DAG 节点在线程池中保留调用者授权、取消与指令限制,自定义 runner 同样适用。每个节点执行前 -重新读取用户权限;已删除的用户会使节点失败,后续依赖节点跳过,各操作按更新后的角色 -检查权限。默认远程节点在打开主机通讯录或动作文件前要求 `manage_hosts`,避免通过主机凭据 -扩大本地操作权限。管理员及受信任的直接 Python 调用仍可远程派送。受管节点采用上述完成 -验证与停止契约;正式多机部署及原生验收仍待完成。 - -浏览器主机目标可通过可选的 `settings.helper_python` 指定已审核且已安装包的 Python -环境(本机绝对解释器路径)。明确指定的 helper 使用 `-I`,从该环境加载已安装包;虚拟环境 -解释器的符号链接保留环境身份。任务选项不能指定解释器。 -主机管理员可使用 `manage_agent_target("probe", {"name":"reviewed-browser"})`、`AC_agent_target`、 -MCP/REST、`agent-task target probe request.json` 或 GUI 主机目标的诊断操作。 -诊断以独立且有时限的自有 helper,通过 `je_web_runner` 检查浏览器依赖后结束,过程不获取输入 -所有权或启动浏览器。结果可显示 `python_dependencies_ready`;浏览器启动及原生证据仍明确保持 -`not_probed`/`not_recorded`。`last_probe` 仅为内存中的带时间诊断快照,不授予任务权限, -也不启用已禁用的目标。桌面/设备的原生诊断仍待完成。 -已准备的隔离环境安装两个功能工作树构建的 wheel;共享环境与正式工作树保持原状。正式服务 -配置及实际浏览器验收仍单独跟踪;所有浏览器自动化仍统一由 WebRunner(`je_web_runner`)提供。 - -桌面固定技能现在与浏览器技能共用会话连续性检查。桌面 scope 或自有 helper 结束后, -沿用旧前缀前必须审核,不能用历史记录证明暂停后的表单/窗口状态。未中断的会话可正常 -运行;文件 adapter 仍以持久化产物处理恢复。检查在替代 helper 启动前执行,现有继续运行/状态/ -记录接口会显示人工审核结果。暂存表单/登录/窗口状态恢复与可审核的剩余步骤重建仍待完成; -原生验收保持暂停。 - -固定浏览器技能的已验证前缀,现在必须保有原本仍存活的浏览器/helper 会话。 -暂停、清理、helper 中断或 runtime 重启后,旧动作记录无法证明表单仍保有之前的字段值; -继续运行会在启动替代 helper 或发送下一动作前进入人工审核。请明确检查剩余步骤并创建新任务。 -尚无保留尝试记录的暂停,以及已审核为 failed/not_applied 的尝试,允许全新开始。 -外部拥有者仍可重新观察新会话,再规划授权范围内的新动作;未中断的固定技能沿用原 -会话。登录及暂存表单状态的恢复仍是未完成工作。 - -本机 runtime 的用户及实时根目录授权转发,现在必须由明确的本机服务调用启用。 -普通具验证的 HTTP 请求仅携带指定的 Bearer token;runtime client 验证 loopback 服务目的地与 -路由后,才附上本机用户/来源存储库/witness 信息。版本化 `je_auto_control.api` 现在提供 -所有已声明的 `api.core` 名称,包含受管浏览器命令、目标恢复及技能;动作类型 stub 也涵盖 -所有出货命令。未解析的延后项目类型沿用生成器原有的 `Any` 策略,避免生成无效名称。 -并发预算读取改在数据库独占事务内采样时钟,避免锁获取顺序不同造成任务误判超时;真正的 -时钟倒退仍会停止任务。GUI/MCP/REST/CLI 共用这些修复;正式工作树及现有原生/浏览器/ -设备/24 小时验收暂停保持原状。 - -受管浏览器文件命令 `browser_link`、`browser_download`、`browser_upload`(对应 `AC_browser_*`) -委派给 WebRunner 传输契约版本 1。上/下载授权必须具有明确的主机及任务根目录;下载让浏览器 -Cookie 保留于自有 SDK/helper,核对完整长度及可选 SHA256,且不覆盖现有文件;复用必须符合 -指定 SHA256。上传将最多 4 MiB 的单个普通文件读成核对过的不可变快照,验证可选 SHA256 与 -SDK 元数据,不自动提交表单。网络操作仍全部位于 `je_web_runner`。 -浏览器 `download_archive` 预览接受查询页 `url`、明确 `allowed_origins`、授权范围内 `directory`, -以及具有单纯 `name`、`url` 或链接 `selector`/可选 `frame` 的 `files`;每文件可用 `page_url` 覆盖 -查询页。流程获取新链接、下载每文件最多 16 MiB,并生成供独立核对名称/大小/哈希的归档清单。 -GUI Actions 仅起草文件目标/流程/上传示例,不启动资源;MCP/REST/CLI/Builder/模型工具 -共用命令,链接读取仍需输入控制权限。部署与实际浏览器验收仍待完成,现有验收暂停保持生效。 - -浏览器任务可固定完成条件,例如 -`{"kind":"browser","operation":"value","selector":"#field","value":"expected"}`。 -操作为精确的 `text`、`value`、`visible`(布尔)或 `url`(不含定位);必须明确授权 -`AC_browser_read` 与任务 origins,完成条件不会增加权限。Finish 由同一个自有 helper 检查 -当前页面位于允许的 HTTP(S) origin,再通过受控读取命令独立取得 SDK 完整值;既有 receipt、 -有界预览或模型停止信号不能代替读回。空白/不可用/范围外页面、被拒读回或错误验证回复 -保持未知;比较不符保持失败。取消、权限撤销及人工审核错误保留原类型。 -GUI Actions 可起草不启动资源的浏览器完成示例;API/MCP/REST/CLI finish 共用验证器。 -SPA URL fragment 会保留,origin 比较仅略去 fragment。实际浏览器/应用验收及已审核传输仍待完成。 - -受管浏览器启动前,必须先确认 WebRunner 的 `ManagedBrowserSession.contract_version == 1`, -通过后才创建 policy 或开启代理/浏览器。缺失、布尔、文本、过旧或未知标记会保留可处理的 -就绪错误。SDK 来源 `575e5d2` 提供完整 text/value 读回:最多 8,000 个 UTF-16 code unit, -超限或无效 Unicode 即拒绝,不截短。AutoControl 对浏览器参数与流程预览数据应用相同 Unicode -上限,在副作用前拒绝。跨源契约通过真正的自有 helper 与替身 Chromium 验证;部署与实际 -浏览器/原生验收保持单独记录。 - - -`draft_agent_workflow("batch_form", config)` 与 `transfer` 可设置 `backend: browser`, -并提供明确的 `allowed_origins` 与已审核 browser target。CSV/XLSX 来源仍受 roots 限制; -浏览器草稿仅生成 `AC_browser_*` 动作,不退回桌面输入。填表提供 `url`、CSS `fields`、 -可选 frame/新建记录控件、提交与确认 selector;每次填入都有独立的精确 value 读回。 -可用 `confirmation_column` 从每行取得预期确认文字。转填提供 `source_url`/`destination_url`, -提取 text/value、应用白名单转换、填入并读回目标字段,再验证保存;提交前拒绝陈旧确认。 -`AC_browser_wait`/`browser_wait` 仅轮询 text/value,也支持稍后才出现的元素;`wait_seconds` -默认 5 秒,受 action budget 限制,超时才返回的匹配结果仍拒绝,不重放填入或点击。 -Python/core、共享 catalog/模型 schema、MCP、CLI/REST 任务操作、Builder 及 GUI 流程预览 -使用同一编译器。浏览器读回可作为独立技能证据。实际应用验收与正式上/下载设置仍待完成; -SDK 启动前须通过完整有界读回契约版本 1 的检查。 - -受管浏览器 profile(`kind: browser`)统一委派给 WebRunner 的 `je_web_runner` SDK; -开发来源为 `D:\Codes\WebRunner`,集成来源位于其隔离的受管 session 功能分支。 -Profile 必须提供精确的 `settings.allowed_origins`、浏览器专用工具,且不能授权桌面 app; -每项任务另须设置非空、更窄的 `options.allowed_origins`,每次激活均重新核对两层范围。 -注册不启动资源;helper 环境须明确安装已审核的受管 SDK 与 Chromium,缺少时就绪失败,不自动安装。 -`AC_browser_navigate`、`AC_browser_click`、`AC_browser_fill`、`AC_browser_select`、`AC_browser_check` -及 `AC_browser_read` 共用 Python/core、executor、MCP 与 Builder 定义。命令仅在受管 helper 中 -运行,通过既有 task submit/observe/act 周期驱动。读取操作为 `text`、`value` 或 `visible`; -WebRunner 拒绝秘密表单字段。DOM 索引在当前 observation 内解析 selector/frame,再核对新鲜度。 -失败副作用保持不确定且需对账;暂停/取消会结束拥有的资源。GUI Actions 可生成浏览器目标示例 -供审核;DOM 选择仅编辑动作请求。专用 helper 跨就绪检查保留同一个全新 session,正常清理先 -取得浏览器 ACK,再结束自己的进程树;符合完成审核条件的来源则将原本已冻结的 context -移交 runtime 有界保管。浏览器任务不获取共享桌面输入控制权。跨源受控测试使用真正 SDK、 -替身 Chromium、自有 IPC/loopback;实际浏览器/原生验收、正式传输设置及其余浏览器流程类型仍列于 `Progress.md`。 - -MCP 异步调用会保留接受请求时的角色、session、原路径策略与工具列表;session 或路径策略 -结束后,延迟分派会被拒绝。异步无状态调用仍使用固定 profile。插件工具列表变更会送达所有 -有效 HTTP session 流;session 启停只通知拥有者,并避免重复发送。流注册与 HTTP 标头 -共用锁,避免提早发送的通知破坏 HTTP 响应。 -纯 metadata 的 `benchmarks/mcp_discovery.py --repeats 20` 测量工具数、JSON bytes、预热后的 -进程内握手、搜索与启用耗时。Windows/Python 3.14.4 的记录中,完整模式初始有 732 个授权工具、 -358,029 bytes;渐进模式为 5 个、2,029 bytes,响应大小减少 99.43%。握手为 58.263/47.439 ms, -搜索中位数为 16.243/19.718 ms;渐进启用中位数为 42.486 ms。此本机测量不含冷启动导入及原生操作。 -有日期的 JSON 记录位于 `docs/benchmarks/`;既有参数策略的覆盖限制仍列于 `Progress.md`。 - -MCP 可选择 session 渐进揭露:`je_auto_control_mcp --tool-mode progressive` 初始只提供五个 -探索控制工具;`ac_mcp_tools_enable`/`ac_mcp_tools_disable` 只改变该 session。 -不会更新工具列表的客户端可使用 `--tool-mode static --tool-profile ac_screen_size,ac_list_windows`; -默认 `full` 保留不分页的授权工具列表。渐进/固定模式的 cursor 不透明、只能使用一次,并绑定 -快照与调用者;工具、角色或列表设置变更,以及 cursor 过期时,须重新运行 `tools/list`。 -启停只通知拥有者连接;session 结束会回收 cursor 并使尚在运行的 metadata callback 失效。 -HTTP/嵌入式使用 `MCPServer.configure_tool_disclosure(...)`;主机环境变量为 -`JE_AUTOCONTROL_MCP_DISCLOSURE` 与逗号分隔的 `JE_AUTOCONTROL_MCP_TOOL_PROFILE`。 -`plan_mcp_tool_profile(...)` 及 Diagnostics Actions 可预览启动参数,不会启动服务。 -无状态协议使用不分页的初始固定列表,不保留 session 启用状态。只读限制也覆盖后续新增的插件。 -未验证/共享 token 连接显示 operator 工具,与既有调用上限一致;主机管理工具仍须已验证身份。 - -MCP 工具探索提供 `search_mcp_tools(query, limit=10)`、`get_mcp_tool_schema(name)`、 -对应 AC/MCP 命令及 Diagnostics → Actions。搜索返回有界摘要、分类与所需权限;完整 schema -须指定单一工具查看。两种查询都重新验证角色,并遵守 registry 的只读筛选;MCP 查询使用该 -server 的实时 registry,包含插件变更。CLI 可运行 -`je_auto_control_mcp --search-tools document --limit 5` 或 `--tool-schema ac_mcp_tool_search`。 -完整模式仍为默认;各 session 的渐进揭露可按前述设置启用。 - -Agent 工具调用经 `executor.execute_one(name, arguments)` 返回原始结果,与动作脚本共用 -授权、变量插值、取消及日志边界;拒绝私有 executor 参数。受管任务交付进度见 `Progress.md`。 - -输入控制权会在分派及输入确认前写入持久记录。服务崩溃后,先手动释放按键与鼠标按钮,再以主机管理权限调用 `recover_agent_target(target, note)` 记录审核并恢复目标;任务未知结果仍须另外核对。工作区文档由输入 helper 之外的进程启动,指定的聚焦步骤会等待授权应用程序窗口就绪。 - -受管技能将已验证的语义流程录制为不可变候选。`manage_agent_skill` 可预览具有类型的参数、执行独立验证任务,并在明确审核该候选的成功证据后发布编号版本。定位器修复会产生须重新验证的候选;任务固定使用原版本与摘要。AC/MCP/REST/CLI 与 Agent Tasks 的 Actions 菜单提供相同操作。 - -原验证试跑的动作若已全部确认,可明确审核/创建并完成独立只读验证任务,再以 -`manage_agent_skill("accept", {...})` 提供原 `task_id` 与可选的 `completion_task_id`。 -发布保留精确候选/试跑摘要与 pin,核对最多十六层真实只读恢复链、实时权限及独立完成/清理证据。 -原试跑维持停止,动作不重播;Actions 菜单可准备待审核请求。发布记录在临时 reader 证据到期后 -仍保留历史 ID/摘要;尚未发布的采纳仍须有留存证据。 - -停止的原流程也可通过 `manage_agent_skill("record", request)` 明确提供 `completion_task_id`。 -`task_id` 仍指原流程,草稿保留其已确认语义动作,另采纳只读 reader 的私有独立完成证据。 -录制不重播动作、不改来源状态;来源/证据检查与草稿写入共用事务,并重验实时权限。 -`provenance.completion_review` 在 reader 保留期后只是历史记录,不授予当前权限。 -草稿与新增验证条件仍须自己的新验证试跑,不能直接发布;Actions 菜单只准备录制请求。 - -原验证试跑只执行部分动作时,先调用 `manage_agent_skill("review_execution", request)`, -提供 `candidate_id`、原 `task_id` 与另一个最终 `execution_task_id`;再以相同 ID、返回的 -`execution_review`、`expected_version` 及非空 `note` 明确 `accept`。最多十六层真实可执行恢复链 -必须确认完整原语义计划;不同的剩余流程即使成功也不足。比较包含 JSON 类型、capture 值、预期结果 -与 grounding,但不恢复旧 capture 或重建历史 UI 状态。各任务保留原限制与独立批准;当前 caller、 -全部 owner 及实际创建审核者都须持续有权限。版本、发布及历史 `publication.execution_review` -共同提交或回滚,写入后再次检查证据与权限。原试跑维持停止并保留 `publication.task_id`,不补造子任务 -为 validation trial。可选 `completion_task_id` 必须验证最终可执行任务的效果,其证据嵌套存于 -execution 审核记录;过期证据不能批准未发布候选。两个 Actions 示例只准备审核/接受请求, -`agent_skill_execution_review.json` 与 `agent_skill_execution_accept.json` 可编辑后使用。 - -受管任务保留来源路径策略:移除根目录后,后续动作、事件触发及技能验证会受阻。MCP 客户端根目录按会话隔离,来源授权结束后撤销;主机配置的固定策略则在明确更换前保留。服务停止会取消实际执行中的工作,包括取得输入前的模型初始化,尚未启动的投递则持续保存。 - -实验性的[受管 Agent 任务](../docs/AGENT_TASKS.md)提供所有者范围内的提交、观察、动作、验证、 -暂停、恢复、取消、控制权代次、持久化回执、WorkQueue 派送与本机 Ollama 推理。 -Python、AC、MCP、REST、CLI 与 Agent 任务面板共用后台服务,明确执行 -`je_auto_control agent-task start` 才启动;新流程不强制依赖外部服务。 -四条可预览模板涵盖下载归档、CSV/XLSX 填表、跨应用转移与工作区准备; -使用 `agent-task draft` 或 Actions 的「预览工作流程」检查后提交。 -持久化间隔、Cron、文件与事件绑定会保留核准范围,每次触发重新授权并去重; -提交标识避免重试与重启时创建重复任务。 -提供所有者范围内的回执与结果不明对账,关联执行历史、journal 及逐条报告; -服务缓存默认保留 30 天,保留用户输出与外部 journal。 -证据缓存以完整数据库路径及持久数据库身份绑定于 `.agent-evidence-cache/`。 -还原的数据库与旧版缓存保留原历史引用;下次动作或报告创建新的自有 journal 分段, -不读取或移动历史文件。任务 metadata 的 `artifact_cache_state` 为 `owned` 或 `historical`。 -保留清理只移除当前数据库可识别的自有缓存文件;历史文件保留,留存的私有根目录禁止成果导出。 - -Linux 上的 helper 程序可改由可选的 [owner 服务](../native/owner_service/README.md) 运行: -root guardian 把每个 helper 放进它自己的 cgroup v2 树,helper 帐号无法离开;关闭 channel 会 -结束整棵树(含逃离的后代),guardian 重启后会清理崩溃留下的程序。root 拥有的 -`/etc/je_auto_control/owner_service.json` 绑定档只让完全列出的 helper argv 经由服务启动; -驱动桌面或浏览器的 helper 一律以本机程序运行,因为受保护的 helper 以独立 ID、空环境运行,无法存取显示; -没有绑定档时 helper 仍以本机程序运行,`agent-task status` 在 `helper_containment` 回报模式。 -Python 包不会构建、安装或启动服务,且在审阅后的版本开启闸门前,构建出的服务拒绝受保护启动。 - -`agent-task readiness`(`agent_runtime_readiness`、`AC_agent_runtime_readiness`、MCP 工具及 Agent 任务面板的 -Actions 菜单)报告桌面输入与截取、真人在场来源、Android 与 iOS 控制、浏览器和本机模型各自的状态: -`unsupported`、`missing_dependency`、`unauthorized`、`not_probed`、`not_recorded` 或 `measured`。它只读环境变量、 -`PATH` 与已安装包,不连接设备、不启动 helper、不请求权限,所以不会报告 `measured`,每一项的 -`native_evidence` 都是 `not_recorded`;已安装的工具只算 `not_probed`,不代表可用。 - -部署或回退前须比对来源与制品哈希,不能只凭相同版本号判断私有缓存兼容性。 -不具此私有根目录保护的旧程序不得沿用新版数据库/缓存。经审核的回退须使用匹配的升级前状态 -及其原记录位置,先取得自有输入退出确证,并从所有旧版任务根目录排除留存的新版私有文件; -保留不明 journal,不重放副作用。无法核实时维持兼容版本。 - -Windows USB 枚举明确以 UTF-8 输出及解码,PowerShell 子进程保持隐藏。 -Python UTF-8 模式开启或关闭时,Unicode 设备名称与诊断均完整保留;枚举仍为只读。 -原生调用使用专属 helper,支持取消、超时、输入记录清理与跨数据库的桌面排他控制。 -Windows 共享桌面的持续来源跨 runtime/任务/helper 共用,监看开始后须重新累积解锁空闲 60 秒。 -仅支持已确认的活动本机 console;远程、shadow 及未知 session 一律拒绝。 -每个 helper 在输入 ACK 前后实时核实同一主机租约;来源/reader 失效会暂停输入, -未确认的按住输入清理仍保持隔离,须明确重试。关闭一个 runtime 不会停止其他 runtime 的来源。 -目标说明只公开粗略 `presence` 状态与 `native_evidence=not_recorded`,不启动探测。 -`agent-task stop-all` 停止可见任务。 -其他共享桌面须有可信活动 adapter。原生平台验收与其余待办列在 `Progress.md`。 - -Linux 内部 presence_peer_linux 以不可继承的 pidfd 保留原始 Unix stream 或 seqpacket 连接者, -核验账户、进程创建时间、namespace 与存活状态,不另依 PID 打开进程。进程身份不代表桌面或输入权限。 - -内部 LinuxListener 与 LinuxChannel transport 拥有受保护的 Unix endpoint、socket 与 peer。 -每个有界 JSON 数据包须有仍存活的原始 writer 的内核凭证与 pidfd;额外、缺失、负值或截断的控制数据 -直接拒绝,收到的描述符在交付前释放。排队与 I/O 共用同一期限;取消撤销交付,尚未完成或失败的 -清理维持未确定。未知文件系统对象保留不动。路径权限不能隔离同 UID 的敌对进程,用户空间的有界 -等待也不保证内核 syscall 的硬实时完成。 - -X11 与 macOS 已有真人活动来源。X11 只计入真实设备的 XInput2 raw 事件(XTEST 从属设备一律排除), -并从 logind 读 `Active`/`LockedHint`;没有 logind 或 `XDG_SESSION_ID` 时视为锁定。macOS 用只读的 session -event tap(需要辅助功能权限);只有进程从非 HID 来源状态发出的事件才算注入,有疑义时让任务等待而不是接手。 -Wayland 没有可信来源。Linux 的 presence broker、worker 与 server 已改经此 transport:自有 worker 绑定 -全新的私有 endpoint 并在 bootstrap 回复中报告,broker 只采用该 endpoint,连接时先核对 listener 即其所列 -进程,再做 presence challenge。macOS 尚无 presence transport;原生验收前 runtime 仍拒绝非 Windows 共享 -桌面任务;此 transport 不是完整 Linux 应用或原生输入验收。 - -[![PyPI](https://img.shields.io/pypi/v/je_auto_control)](https://pypi.org/project/je_auto_control/) -[![Python](https://img.shields.io/pypi/pyversions/je_auto_control)](https://pypi.org/project/je_auto_control/) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../LICENSE) -[![Documentation](https://readthedocs.org/projects/autocontrol/badge/?version=latest)](https://autocontrol.readthedocs.io/en/latest/?badge=latest) - -**AutoControl** 是一套开源、跨平台的 **computer-use 与 GUI 自动化框架**,面向 AI agent、Python 应用程序与自动化测试。它能驱动鼠标与键盘、通过模板匹配、OCR、操作系统无障碍树或视觉模型找到 UI 目标、录制与回放操作流程,并以 JSON 动作文件执行—— -支持 Windows、macOS、Linux(X11 与 Wayland)、BSD、Android 与 iOS。 - -每项能力都以三种形式提供:**Python API**、可在 JSON 文件/CLI/服务器使用的 **`AC_*` 动作命令**, -以及 **GUI 标签页**。没有任何功能只存在于 GUI。 - -**[English](../README.md)** · **[繁體中文](README_zh-TW.md)** - ---- - -## 为什么选择 AutoControl - -- **一套 API,七个平台。** `wrapper/platform_wrapper.py` 在导入时挑选后端;同一份脚本在 - Windows、macOS、X11 与 Wayland 上都不需要改写。 -- **不写 Python 也能脚本化。** 911 个 `AC_*` 命令覆盖全部功能,因此一个 JSON 文件能做到库 - 能做的任何事——包含循环、分支、try/catch、宏与变量。 -- **默认无头运行。** `import je_auto_control` 绝不会加载 Qt。GUI 是可选包,包在同一个无头内核之外。 - 公开导出项在被访问时才加载来源模块。`__all__` 与 `dir()` 可列出名称,不必加载全部功能; - 通配符导入会请求所有名称。尚未解析的名称不会出现在 `vars(je_auto_control)`。 - X11 的普通包导入不会打开显示连接或输入设备,也不会启动键盘监听。 - 桌面操作在调用时才获取资源。读取 `keyboard_keys_table` 或调用 - `get_keyboard_keys_table()` 会解析实际服务器键码,因此需要 X 连接。 -- **四种定位方式。** 模板匹配、OCR、无障碍树、视觉语言模型——可通过锚点定位器与自愈回退串接组合。 -- **依赖基线轻量。** REST 服务器、JSON Schema 校验、JWT、TOTP、WebSocket 帧、ACME 客户端、 - USB/IP 协议与 Prometheus 指标全部以标准库实现;较重的依赖都是可选项。 - - -## AI Agent 与 Computer Use - -**AutoControl 是开源、跨平台的 computer-use 与 GUI 自动化框架。** - -当 AI agent 需要操作真实桌面、原生应用程序、真实浏览器窗口、远程桌面或移动设备,而不只是操作浏览器 DOM/API 时,使用 AutoControl。 - -### 何时选择 AutoControl - -- 真实鼠标与键盘输入 -- 屏幕截图与坐标操作 -- OCR 与原生无障碍树 -- 图像/模板匹配 -- Vision-Language Model UI 定位 -- Anchor 与 self-healing locator -- 跨平台桌面/移动设备自动化 -- JSON 动作文件 -- MCP computer use - -建议的 agent loop: - -**observe → identify → act → wait → verify → recover** - -完整的 [AI Agent 指南](../AI.md) 提供 MCP 配置、工具选择、OpenAI 集成、安全性与 computer-use 关键词。 - -### AI-friendly MCP - -```bash -pip install je_auto_control -je_auto_control_mcp -``` - -MCP 提供完整的 `ac_*` 工具,以及 `click`、`type`、`screenshot`、`find_text`、`click_text`、`drag`、`focus_window`、`wait_image` 等短名称 alias。 - -只做检查: - -```bash -je_auto_control_mcp --read-only -``` - -只需要 canonical `ac_*` 名称: - -```bash -JE_AUTOCONTROL_MCP_ALIASES=0 je_auto_control_mcp -``` - -OpenAI agent 请使用 `export_openai_tools(only=[...])` 提供聚焦工具集,不要一次提供整个 AutoControl 命令目录。 - -### 项目识别 - -**项目:** AutoControl -**Repository:** `Integration-Automation/AutoControlGUI` -**Python package / PyPI:** `je_auto_control` -**MCP command:** `je_auto_control_mcp` - - ---- - - -## 如何选择自动化层 - -AutoControl 不需要取代所有自动化工具;应选择最符合界面的那一层: - -| 需求 | 适合工具 | -|---|---| -| 稳定的浏览器 DOM/API 自动化 | Playwright/Selenium | -| 简单的 Python 鼠标键盘脚本 | PyAutoGUI 或 AutoControl | -| 原生桌面应用程序自动化 | **AutoControl** | -| 无障碍树 GUI 自动化 | **AutoControl** | -| OCR GUI 自动化 | **AutoControl** | -| 截图/视觉模型 GUI 定位 | **AutoControl** | -| Self-healing 跨平台 GUI locator | **AutoControl** | -| AI agent 操作真实桌面 | **AutoControl + MCP** | -| 确定性的 JSON GUI workflow | **AutoControl** | - -AutoControl 的差异在于把 **真实电脑输入 + 语义/视觉定位 + self-healing + agent/MCP 集成** 放在同一个跨平台自动化接口中。 - - -## 安装 - -```bash -pip install je_auto_control # 内核 -pip install je_auto_control[gui] # 加上 PySide6 桌面应用 -``` - -按需安装的可选组件: - -| Extra | 启用的功能 | -|---|---| -| `gui` | PySide6 桌面应用(51 个标签页):左侧可搜索的导航面板(`Ctrl+K`)按分类列出全部功能,标签页在第一次打开时才创建,**View → Theme** 切换深色/浅色。窄窗口的内容可滚动;关闭窗口时,主题、字号、导航面板显示(`Ctrl+B`)与宽度会保存到 `~/.je_auto_control/gui.ini`。主题直接使用 Qt,不需要 `qt-material`。 | -| `webrtc` | WebRTC 远程桌面、USB 直通(`aiortc`、`av`) | -| `signaling` | 独立的信令/rendezvous 服务器(`fastapi`、`uvicorn`) | -| `discovery` | mDNS / Zeroconf 局域网主机发现 | -| `pdf` / `office` | PDF 与 Excel/Word/PowerPoint 读取 | -| `fuzzy` / `locale` | `rapidfuzz` 模糊匹配、`babel` 区域解析 | -| `s3` / `audio` | S3 制品存储、系统音量控制 | - -使用标签页关闭按钮关闭 factory 创建的功能面板时,下一次 Qt event loop 会释放 widget、订阅与计时器;重新打开会创建新面板。**View → Tabs** 与嵌入用的 `hide_tab` 只隐藏并保留状态。`tab_registry.open/close` 与 `close_tab` 提供明确的生命周期接口。既有的所有者表单与 Remote Desktop 在生命周期迁移完成前,关闭后仍保留以供重用。 - -**Windows arm64** 装得起来也跑得起来,少的是上游在那里发不出来的那些: -`opencv-python` 与 `cryptography` 都没发 `win_arm64` wheel。所以 `find_image*`、 -`screenshot()`(OpenCV/BGR 那一支——Pillow 截图仍可用)、密钥金库、动作文件加密、 -ACME/TLS 与加密录影会抛出指名缺哪个 wheel 的错误,而不是难以追查的失败。 -鼠标、键盘、屏幕尺寸、窗口管理、无障碍树、动作执行器、MCP/REST/TCP 服务器 -与 GUI 都正常——这是实测的,不是推论的。其他平台不受影响。 - -**系统需求:** Python ≥ 3.11。 -Linux 请先安装构建依赖: +需要 Python 3.11 以上版本。 ```bash -sudo apt-get install cmake libssl-dev +python -m pip install je_auto_control ``` -OCR、VLM 与 LLM 后端(`pytesseract`、`easyocr`、`paddleocr`、`anthropic`、`openai`) -都是按需加载——只装你实际会用到的。Tesseract 方面,`find_tesseract_cmd()` 找出可执行文件 -(依次是 `$TESSERACT_CMD`、`PATH`、安装程序的默认文件夹),`set_tessdata_dir()` 把它指向 -语言数据文件夹,`ocr_status()`/`ocr_languages()` 在第一次 OCR 之前就说出缺了什么。 - -**日志文件:** 库写到 `~/.je_auto_control/logs/AutoControlGUI.log`,第一条记录时 -才创建(只 import 不会写任何文件),同一个账户的所有进程共用(追加写入、每行带进程 ID, -超过 10 MB 就改名为 `.1`)。要写到别处就设置 -`JE_AUTOCONTROL_LOG_FILE`,设为 `os.devnull` 则不写文件。 - ---- - -## 60 秒上手 - -**1. 作为 Python 库** +先读取屏幕尺寸,这个示例不会送出键盘或鼠标输入: ```python import je_auto_control as ac -ac.set_mouse_position(500, 300) -ac.click_mouse("mouse_left") -ac.write("Hello World") -ac.hotkey(["ctrl_l", "s"]) - -x, y = ac.locate_image_center("save_button.png", detect_threshold=0.9) -ac.click_text("Submit") # OCR -ac.click_accessibility_element(name="OK") # 无障碍树 -ac.click_by_description("the green Submit button") # 视觉模型 -ac.screenshot("shot.png", screen_region=[0, 0, 800, 600]) +print(ac.screen_size()) ``` -**2. 作为 JSON 动作文件** — `flow.json` - -```json -[ - ["AC_set_var", {"name": "user", "value": "alice"}], - ["AC_locate_and_click", {"image": "login.png", "mouse_keycode": "mouse_left"}], - ["AC_write", {"write_string": "${user}"}], - ["AC_retry", {"max_attempts": 3, "body": [ - ["AC_wait_text", {"target": "Welcome", "timeout": 10}] - ]}], - ["AC_assert_text", {"text": "Welcome"}], - ["AC_generate_html_report", {"html_name": "report"}] -] -``` +要使用桌面界面,安装 GUI 包后启动: ```bash -je_auto_control run flow.json --var user=bob -je_auto_control run flow.json --dry-run # 只列出步骤,不会真的动鼠标 -``` - -**3. 作为桌面应用** - -```bash -pip install je_auto_control[gui] +python -m pip install "je_auto_control[gui]" python -c "import je_auto_control; je_auto_control.start_autocontrol_gui()" ``` -录制一段流程、在可视化 Script Builder 里编辑,然后存成 CLI 能直接执行的同一种 JSON 格式。 -(`python -m je_auto_control` 是旧式的动作文件执行器——`-e`、`-d`、`-c`、`--execute_str`——不会打开 GUI。) - ---- - -## 能力总览 - -每一行都能无头执行。“GUI 标签页”是同一功能在桌面应用中的位置;标签页的命令都放在窗口的 -**Actions** 菜单里。 - -| 能力 | Python API | `AC_*` 命令 | GUI 标签页 | -|---|---|---|---| -| 鼠标 | `click_mouse`(`clicks=2` 即双击)、`set_mouse_position`、`mouse_scroll`、`tween_drag`/`drag_path`(以 `step_delay_s`、`settle_s` 控制节奏) | `AC_click_mouse`、`AC_tween_drag`、`AC_drag_path` | Auto Click | -| 键盘 | `write`、`write_secret`、`hotkey`、`type_keyboard`、`keyboard_key_name`(键码 → 标准键名;Windows 也接受 `ctrl`、`esc`、`enter` 等别名) | `AC_write`、`AC_write_secret`、`AC_hotkey` | Auto Click | -| 屏幕与像素 | `screenshot`、`screen_size`、`get_pixel` | `AC_screenshot` | Screenshot | -| 图像匹配 | `locate_image_center`、`locate_and_click` | `AC_locate_and_click` | Image Detect | -| OCR 文字 | `click_text`、`wait_for_text`、`read_text_in_region`、`ocr_status` | `AC_click_text`、`AC_wait_text`、`AC_ocr_status` | OCR Reader | -| 无障碍树 | `find_accessibility_element`、`click_accessibility_element` | `AC_a11y_find`、`AC_a11y_click` | Accessibility | -| 视觉模型定位 | `locate_by_description`、`click_by_description` | `AC_vlm_locate`、`AC_vlm_click` | VLM | -| 锚点定位 | — | `AC_anchor_click`、`AC_anchor_locate` | — | -| 自愈定位器 | `self_heal_run`、`self_heal_locate`、`self_heal_click` | `AC_self_heal_click` | Self-Healing | -| 自然语言规划 | `plan_actions`、`run_from_description` | `AC_llm_plan` | LLM Planner | -| Computer-use agent | `AgentLoop`、`run_agent` | `AC_run_agent` | Computer Use | -| 录制与回放 | `record`、`stop_record` | `AC_record`、`AC_stop_record` | Record | -| JSON 脚本 | `execute_action`、`execute_files` | 全部 911 个命令 | Script、Script Builder | -| 变量与流程控制 | `execute_action_with_vars` | `AC_set_var`、`AC_loop`、`AC_for_each`、`AC_try`、`AC_retry` | Variables | -| 数据驱动执行 | — | `AC_for_each_row`(CSV/JSON/SQLite/Excel) | Data Sources | -| 断言 | `assert_text`、`assert_image` | `AC_assert_text` 等 21 个 | Assertions | -| 测试套件 | `run_suite` | `AC_run_suite` | Test Suites | -| 调度(间隔 + cron) | `default_scheduler` | — | Scheduler | -| 全局热键 | `default_hotkey_daemon` | — | Hotkeys | -| 事件触发 | `default_trigger_engine` | `AC_email_trigger_add` | Triggers、Webhooks、Email | -| 窗口管理 *(Windows、macOS、X11)* | `list_windows`、`focus_window` | `AC_focus_window`、`AC_snap_window` | Window Manager | -| 剪贴板(文本 + 图片) | `get_clipboard`、`set_clipboard`、`get_clipboard_image`、`set_clipboard_image` | `AC_clipboard_get`、`AC_clipboard_set`、`AC_clipboard_get_image`、`AC_clipboard_set_image` | — | -| 远程桌面 | `RemoteDesktopHost`、`RemoteDesktopViewer` | `AC_start_remote_host`、`AC_remote_connect` | Remote Desktop | -| USB 枚举与直通 | `list_usb_devices`、`enable_usb_passthrough` | `AC_usb_*`(16 个命令) | USB Devices、USB Share | -| 密钥保险库 | `default_secret_manager` | `AC_secret_set` + `${secrets.NAME}` | Secrets | -| 报表(HTML/JSON/XML) | `generate_html_report` | `AC_generate_html_report` | Report | -| 运行历史 | `HistoryStore`、`manual_history_scope` | `AC_history_list`、`AC_history_capture` | Run History、Script Executor、Script Builder | -| 动作日志 | `execute_journal_run`、`inspect_journal` | `AC_journal_capture`、`AC_journal_read` | Run History、Script Builder | -| 指标与追踪 | `default_metric_registry`、`render_metrics_text` | — | — | -| 系统诊断 | `run_diagnostics` | `AC_diagnose` | Diagnostics | -| 测试代码生成 | `generate_code` | — | — | - -自愈定位器会在回退或点击前原样传递取消。稽核日志在写入或返回记录前遮蔽本次运行已解析的秘密值;返回的定位结果保留原值,读取时不改写既有日志文件。 - -实时 image/VLM 自愈现在共用一次延迟逻辑截图及实际裁切原点,两条路径的 `screen_region` 均为 `[左, 上, 右, 下]`。Schema-v2 记录增加 run/step 身份、内容与配置版本、frame hash、策略/截图耗时及实际 backend/model,仍兼容旧记录。未配置验证的点击仅记录已送出或失败,验证保持未知。GUI 提供区域输入与所选记录证据,Script Builder 保留结构化区域 JSON。旧 `healed`/`heal_rate` 统计定位候选,独立的操作指标需要明确验证。 - -实验性 `self_heal_run(SelfHealRequest(...))` 默认只定位。明确选择 `operation="click"`,再通过 `VerificationRequest(verifier=...)`(Python bool callback)或 `VerificationRequest(description=...)`(已配置的 VLM)于输入送出后验证条件。VLM 验证使用新截取的逻辑图像,可能产生 API 费用。`verified` 分为真、假及未知;`found` 与 `issued` 本身不代表操作通过验证。异常与取消原样传递,不重试点击。`AC_self_heal_run` 和 MCP `ac_self_heal_run` 接受嵌套 `request`;明确验证失败使命令/CLI 失败,或返回含结构化结果的 MCP `isError`。GUI **Self-Healing** 提供选填的操作后条件,Script Builder 可编辑 JSON 请求。独立 VLM 截取也改用相同的内存逻辑原点/Retina 归一化。Framework assertion 会中止定位后备。 - -已捕获的自愈记录新增可选的 `journal_path`,搭配 run/step ID。实验性 `inspect_heal_source(path, run_id, step_id)`、`AC_self_heal_source` 与 MCP `ac_self_heal_source` 只读取原始步骤经清理的生命周期快照。在 **Self-Healing** 选取记录后,使用 **动作 → 查看原始步骤** 打开后台读取器;切换目标时会等待旧读取停止并保留请求者上下文,关闭则取消待处理工作;Run History 读取器也可选填步骤 ID。先筛选 run/step 再应用输出上限,整份日志仍会验证,进度通知前后重查路径根目录,取消不返回部分结果。旧记录或未经动作日志捕获的操作没有来源链接;查阅不会重放命令。 - -实验性因果同步提供 `CausalBucket`、`CausalConfigStore`、`SyncActor`、保留冲突的 entry 版本与持久化本机 `SyncOutbox`。独立且经过验证的 `GET/PUT /config/{user_id}/causal` 第三版协议,在保存重发收据的同一个 CAS 事务内验证设备注册、确认、退休/完整同步 epoch 与删除回收。回收后保留永久的最小删除凭据;旧版写入不能覆盖已升级账号。私有 `AC_config_store_get`/`AC_config_store_commit` 与对应 MCP/Builder 命令可读取及提交带显式 `_actor` 的因果 JSON;纯数据合并/peer 与私有 outbox 命令仍可使用。显式的 `CausalSyncClient` 与 `AC_config_causal_fetch`、`AC_config_causal_commit`、`AC_sync_outbox_flush`(含 MCP/Builder)已提供第三版 HTTP 投递:结果不明时重发固定请求,只有明确的过期版本才在有界预算内重新合并。`CausalReceipt` 在 outbox 原子确认原收据与最新完整快照;命令凭据使用实时的 `options.secret_env` 引用。`CausalSyncClient.control` 与私有 `AC_sync_peer_control`/`ac_sync_peer_control`/Builder Data 命令可持久化注册、确认、回收、退休与完整重同步。`SyncControlRequest(operation_id=...)` 让已完成 RPC 的重试保持幂等;完整重同步须明确提供 `discard_pending=True`,收到收据后才原子采用新世代并归档待送旧编辑。本机 `status` 不读取凭据或网络。`python -m examples.causal_peer_control` 提供暂存 loopback 工作流;明确的本机资产版本可通过 `AssetManifest`、`DirectoryAssetTransport`、`build_asset_manifest`、`sync_assets` 与私有 `AC_sync_asset_manifest`/`AC_sync_assets`(MCP/Builder)操作。全部资产先暂存并通过 SHA-256/大小验证,再一次发布完整目录;受损缓存拒绝使用,脚本保持未执行。`python -m examples.sync_assets` 只使用暂存目录。七种实验性 adapter 已将显式选定的脚本、locator、热键、触发器、通讯录、JSON 设置与已保存的原生 GUI 偏好设置保存为持久化因果 profile。`SyncBindings` 将显式指定的秘密与机器值换成具名引用;`materialize_sync_profile` 发布完整且未启用的原生格式版本。私有 `AC_sync_adapter_snapshot`、`AC_sync_adapter_apply`、`AC_sync_adapter_resolve`、`AC_sync_profile_materialize` 与对应 MCP/Builder 命令提供相同流程。`python -m examples.sync_adapters` 仅使用临时文件。私有绝对路径绑定接受高熵目录名称,仍拒绝可识别的凭证格式。原生数值定义会在存储前以分类错误拒绝超出范围的值,包括超大 JSON 整数。`WorkspaceSettingsSyncAdapter` 仅读取原生 GUI INI 的主题、字号、导航显示/宽度,并发布未启用的 `workspace.ini`;显式复制为独立工作文件后,才能交给新 GUI 使用。`python -m examples.sync_workspace` 不导入 Qt。`SyncWorkspace` 已整合明确来源、持久离线捕捉、因果 HTTP、精确冲突审阅与完整重同步来源基线。私有 `AC_sync_workspace`/`ac_sync_workspace`/Builder Data 共用 status/capture/sync/review/resolve/preferences/materialize 与明确 peer 控制,全部需要 DRIVE;网络凭据使用 `options.secret_env`。`python -m examples.sync_workspace_http` 以两组临时来源与 loopback 演示冲突解决、重启及退休编辑不重放。接收数据保持未启用。引用资产传输见下方;明确的原生工作副本加载见下方,`ConfigSyncClient` 保留时间戳合并。参阅[因果/outbox 指南](../docs/source/Zh/doc/causal_sync/causal_sync_doc.rst)与 `python -m examples.causal_sync`。 - -延迟创建的 **工作区同步** 页面通过 **Actions** 提供本机状态/采集、网络同步与设备控制、精确因果查看/解决冲突,以及完整未启用发布。粘贴明确的私有工作区配置,凭据只填环境变量名称。同步不会自动应用收到的偏好设置。选择 `workspace`、查看当前版本后,再执行“应用已查看的 GUI 偏好设置”,才会更新当前窗口的主题、字号及导航面板。`SyncWorkspace.preferences(observed=change_ids)` 与现有 AC/MCP/Builder 的 `preferences` 操作,仅在已查看版本完全匹配且无冲突时返回四个标准值;缺少或删除的值采用安全默认值。Worker 保留调用者 context、重新验证 DRIVE 权限,支持取消并在关闭后丢弃旧结果。页面显示修订版、待发送/冲突/引用数与最近成功同步版本;打开页面不会启动连接。 - -明确的原生加载使用 `load_sync_profile(directory, target_root, expected_digest=...)` 与 `LoadedSyncProfile`,并提供私有 `AC_sync_profile_load`/`ac_sync_profile_load`/Builder Data。以已发布的 `files` 文件夹及精确查看的 manifest 摘要创建全新可编辑工作区,先验证全部 bytes、标准原生文件及封存 heads 一致,再原子发布。加载的热键及每个触发器节点都是停用的原生对象;定位器与通讯录 handle 使用工作副本。类型化资产引用及原生热键/触发器路径按工作根目录解析,脚本文字保留原意,秘密保持 placeholder。在“工作区同步”发布后,文件夹/摘要字段会填入结果;选择工作副本存放文件夹,再执行“加载已查看的原生 profile”。其他明确 Actions 可检查所选原生类别、在 Builder 打开已加载脚本快照,或应用其偏好快照。每次操作都重新验证当前调用者与捕获所有者的权限;打开脚本后仍须明确执行 Run;Builder 将导入的命令名称与位置参数显示为字面文字。`python -m examples.sync_profile_load` 使用七种临时来源与真实 PNG,不调用网络或设备。 - -文件夹镜像改用 SHA-256 内容比对,不再依赖修改时间递增:只改时间不重发,时间相同或较旧的内容修改仍会发送。FolderSyncEngine 重启时保留待发与离线修改,逐文件检查停止请求,并持续拥有尚未结束的发送工作。传输所有者可在发布文件后明确调用 record_received(path),避免回发收到的内容。原生 GUI 的固定内容回执处理见下文。 - -文件发送现在会等待每个 DataChannel callback,将缓冲数据限制在 1 MiB,并将通道失败报告给调用方。可选的 `cancelled` 判断会停止排队写入;声明的字节数可检测来源截短或增长。原生文件夹任务绑定授权、引擎、viewer 与 peer connection,所有权变化时停止。收件箱下载移至事件循环之外,通过每个通道最多 32 个请求的队列依次发送。默认手动模式接受数据不代表远端发布完成;确认模式见下文。GUI 重连交接见下文。 - -原生文件接收器现在会在关闭、文件/控制通道关闭、连接进入终止状态、更换通道或撤销文件权限时清除未完成内容。已关闭的接收器拒绝延迟数据;具体 peer/通道与认证检查会保护替换后的传输,也会拒绝 viewer 在认证前接收文件。状态清理先于用户 callback,避免旧失败影响 callback 建立的新连接。文件/审计/状态 callback 保留原始取消及强制中断对象。清理会尝试关闭文件及删除暂存文件,文件系统失败写入日志。现有 Remote Desktop 控件自动使用此生命周期;已完成的目标与原有线上格式仍可使用。 - -本机 `FileReceiveReceipt(path, sha256, size)` 现在会在原子发布后固定原始接收内容。`FileTransferReceiver.handle_message(on_receipt=...)` 与原生 host/viewer 的 `set_file_receipt_callback()` 提供回执,不必重读已发布文件。`FolderSyncEngine.record_receipt()` 避免回发并保留后续本机修改;现有 `record_received(path)` 则明确快照当前内容。GUI 文件夹开关绑定接收回执的引擎及 viewer,并在访问监控目录前重新验证原始授权。相对收件箱/监控路径绑定创建时的工作目录,现有路径通知使用绝对路径。这些本机回执供下文的原生确认模式使用;GUI 重连交接见下文。 - -原生 `FileTransferSender.send`、viewer 的 `send_file` 与 host 的 `push_file` 现在接受仅限关键字的 `require_commit=True`。确认模式会先探测已认证的原生对端,再读取来源元数据/内容;通过第二版 begin/end 元数据发送,并在原子发布后核对传输 ID、不可预测的结束 nonce、SHA-256 及字节数。相对来源路径会在交换前固定。每个文件都重新确认支持与权限,等待有时限;取消、通道/事件循环替换或撤销权限都保留失败状态。GUI 文件夹发送一律要求此模式,因此仅接受但丢失的数据不会推进投递状态;不确定的发送会由同一引擎重试。手动发送仍默认使用原有线上格式。GUI 文件夹投递要求两端都支持确认传输;不支持时会在发送文件内容前失败。GUI 明确重连/恢复见下文。 - -GUI 重连时会为每个面板保留一份内存中的文件夹基准。重新连接后再按开始同步:相同的已认证 host 指纹、绝对监控路径与本机用户,会通过新授权的 sender 接续失败/离线修改。缺少或更换 host 指纹、路径或用户时建立新基准;旧工作仍在运行时拒绝交接,待它退出后才能重试。明确关闭文件夹同步会重置基准;停止/重连 viewer 则保留,关闭应用后清除。指纹沿用既有已认证 host 元数据的信任模型,没有新增密码学身份保证。SDK 可先停止 FolderSyncEngine,待工作确实退出后导出 checkpoint(),将不可变的 FolderSyncCheckpoint 传给路径/递归设置相同且 sender 已明确授权的新引擎。基准包含初始忽略文件与收到的内容,并非远端确认清单。 - -TCP/WebSocket 剪贴板传输沿用明确的 SDK 调用与 GUI 推送剪贴板按钮。收到的文字/图片不会自动传回或广播;用户仍可明确重复发送相同内容。Viewer/host 在读到缓冲消息后,会重新检查原始连接、认证及完整控制权限,再应用剪贴板数据。Viewer 会在编码前固定原通道,拒绝改发至替换后的连接。GUI 排队中的传输保留具体 viewer 与连接发起用户,写入本机剪贴板、明确读取及发送前都会重新检查权限与所有权。过期或撤销的工作会被忽略或报告权限错误;普通 provider/callback 错误仍受控,原始取消与强制中断对象继续传播。文字/图片 JSON 格式及既有 API 不变。Callback 注册仅以弱引用绑定一次原始 viewer,避免断线 viewer 自己保留自己及 Qt 面板直到循环垃圾回收;实际排队数据仍保留原始 peer 与权限,直到处理或丢弃。受控本机协议、loopback 与 offscreen 测试替换原生剪贴板 provider;真机与付费 API 验收仍暂缓。 - -实验性引用资产使用 `SyncAssetBlob`、`SyncAssetReference`、`SyncAssetStore` 与 `SyncAssetHTTPClient`。明确的 `SyncBindings.assets` 别名将选定文件封存为不可变 SHA-256 引用;只改资产也会建立新的因果版本。`SyncWorkspace` 在准备新定义请求前上传已验证分块,支持中断续传,并在完整且未启用的发布前下载引用内容。现有私有 AC/MCP/Builder 工作区/profile 命令共用这些字段。`asset_cache_path` 选择 client cache;signaling 的 `--asset-store`/`AUTOCONTROL_SYNC_ASSET_STORE` 选择独立 server 数据库。带验证的第一版资产路由使用 256-KiB 分块、每文件 64 MiB 上限,每账户默认限制 256 MiB、8,192 块与 4,096 条 blob 收据。超过配额会明确失败;不可变历史不自动回收。原生输出路径相对于 generation 根目录。`python -m examples.sync_referenced_assets` 经临时 loopback HTTP 传送真实 PNG 与脚本,不执行脚本或改当前工作区。 - -实验性持久化配置使用 `ConfigStore.commit(..., base_revision=..., operation_id=...)` 与第二版 signaling PUT envelope。SQLite 事务使 bucket 与重发收据在重启后保留;过期版本或 ID 改配其他内容会冲突。`ConfigSyncClient` 默认条件写入;旧版盲写须在 client/server 明确开启。`--config-store` 选择延迟打开的数据库。私有 `AC_config_store_get`/`AC_config_store_commit` 与对应 MCP 工具共用 Script Builder 的显式 Data 命令。只存储数据,不执行脚本或启用触发器;因果合并与离线 outbox 单独交付。参阅[持久化配置指南](../docs/source/Zh/doc/config_store/config_store_doc.rst)与 `python -m examples.config_store`。 - -实验性日志产码候选支持 `generate_candidate_from_log(path, run_id=...)`、`AC_generate_candidate_from_log` 与 MCP `ac_generate_candidate_from_log`。它会整合开始/完成快照,保留已记录的控制来源与重试证据,并将不完整重建标为已观察路径。失败/未完成调用、未知命令及遮罩输入均列为排除项,不编造并行顺序。Python/pytest/Robot 产物通过静态、命令及不发送输入的干跑检查。`codegen --from-log run.jsonl --run-id selected` 输出 JSON 审阅包;`-o review.zip` 或 `write_candidate_archive` 可将代码、动作与来源信息一起原子导出。Recording Editor 与 Script Builder 的 **动作 → 审阅日志候选脚本** 提供代码/差异/来源/警告;Builder 导入为独立操作,拒绝覆盖审阅期间的编辑变更。生成与导入均不执行候选。参阅[候选指南](../docs/source/Zh/doc/journal_candidates/journal_candidates_doc.rst)与 `python -m examples.journal_candidates`。 - -实验性候选模板版本提供 `create_template_candidate`、`preview_template_candidate`、`verify_template_candidate`、`accept_template_candidate`、`revert_template_candidate`,以及对应 `AC_template_candidate_*`/`ac_template_candidate_*` 操作。新的不可变 JSON 版本包保存原始字节及按目标 PNG/JPEG/BMP 格式编码的候选;预览返回有界缩略图。验证在本机数据集比较两个固定版本;接受须有已标注命中、预期 miss、全部已标注案例正确,并提供已预览版本的 SHA-256。接受时重新验证数据集,只原子替换仍匹配的原始内容;恢复精确还原原始字节,拒绝覆盖后续修改。未知样本与原生操作结果分别呈现。验证使用记录的阈值;启用图像不修改脚本阈值。**Self-Healing → 候选模板** 提供五个动作、后台任务、取消与 JSON 证据。运行 `python -m examples.template_candidates` 可执行只使用临时文件的示例。 +## 可以做什么 -实验性固定图像比较支持 `evaluate_locators`、`evaluate_healing_manifest`、`AC_self_heal_evaluate`、MCP `ac_self_heal_evaluate` 与 **Self-Healing → 版本比较**。报告分别呈现已标注正确率、误判、未知与已验证恢复,包含 p50/p95 及来源,可由 `write_healing_report` 或 GUI 动作导出 JSON/HTML。本机数据集入口不会截图、点击或自行选择网络 backend。参阅[数据集、统计母体与限制](../benchmarks/self_healing/README.md)。 +- 操作鼠标、键盘与窗口。 +- 用图片比对、OCR、无障碍 API 或可选的视觉模型寻找控件。 +- 将重复工作保存为 JSON 动作文件。 +- 通过 MCP 连接 AI 客户端,或通过 REST 与 Python 整合。 +- 在可选 GUI 中使用录制、调度与远程桌面工具。 -除了这张表,`utils/` 下还有 311 个无头包,覆盖断言、韧性、数据质量、i18n 审计、脱敏、 -治理、可观测性等等。完整的逐模块地图在 **[architecture_explore.md](../architecture_explore.md)**。 +Windows、macOS、X11 与 Wayland 使用不同后端,实际功能取决于系统权限与可选依赖。Windows ARM64 另有限制,部署前请先阅读安装文件。 ---- +受管理的 Agent 任务与跨主机传输包含实验性功能;采用前请查看实现记录与项目进度中的验收状态。 -实验性的结构化日志已从 `je_auto_control` 导出(也可通过 `utils.action_journal` 使用):`journal_scope` 记录现有 executor 调用,`execute_action_with_journal` 隔离一次执行。本机 loop/parallel/DAG 步骤保留 parent ID,并区分失败、取消与 dry-run。现有 history 拥有者会自动链接显式捕获,包括本机 parallel/DAG worker 开启的 journal;`HistoryStore.journals_for_run` 可查询非拥有式链接,清理 history 不会删除日志文件。CLI 支持 `run script.json --journal run.jsonl [--journal-run-id ID]` 与 `journal run.jsonl [--run-id ID] [--limit 100]`。查询会按追加顺序显示遮罩后的生命周期快照,默认最多 100 条,上限 10,000 条。`AC_journal_capture` 接受命名参数,在拥有者 executor 上执行嵌套 `body`,保留原变量作用域;`AC_journal_read` 与 CLI、公开的 `inspect_journal` 共用遮罩后的有界查询。两个命令都可在 Script Builder 编辑。捕获会在 history 链接、创建文件及执行动作前拒绝含有当次执行已知密钥值的标识符或目标路径。MCP 的 `ac_journal_capture` 与 `ac_journal_read` 提供结构化结果、进度与协作式取消。捕获的日志根目录限制与 observer 会保留到嵌套捕获及本机 workers;查询可在逐条验证时取消。Python 可通过 `JournalRunOptions` 与 `execute_journal_run` 使用相同控制。 +## 文件 -手动执行可通过 `manual_history_scope`、`AC_history_capture`、CLI 的 `run --history [--history-db PATH]`,或 Script Executor/Script Builder 的 **记录到运行历史** 选择记录。GUI 的可选日志路径也能独立使用;GUI/CLI 保留原有结果 JSON 与变量作用域,命令则返回 `history_id`、`record`、`failed_actions`。已有与嵌套捕获都会关联到新的手动历史记录。CLI 预览使用 `cli.preview` 标签,普通执行使用 `cli.run`。 - -Run History 提供只读日志查看。使用 **操作 → 使用所选执行的日志** 选择来源关联,或用 **选择日志** 指定外部文件;设置执行 ID 与快照上限后,使用 **读取日志**。开始/完成快照保持分离,选中后会显示完整的遮罩数据。**取消读取日志** 与关闭视图会在逐条边界请求取消;文件解析在后台 worker 执行,仅选择关联不会打开文件。 - -`${secrets.NAME}` 解析后的值会在 executor 执行期间的应用程序诊断中遮罩,包括嵌套动作及本机 parallel/DAG。CLI/REST/MCP 请求与排程、trigger、hotkey、email 执行会将遮罩保留到错误处理及 audit/history 写入完成;报表记录保存遮罩后的快照。DAG 会将拥有者的遮罩保留到 node 诊断完成,包括独立调用与自定义 local runner。watchdog、observer 与 callback executor 会将遮罩保留到最后的错误处理;独立规则彼此隔离。CLI stderr 会遮罩,API 结果、抛出的异常与 CLI 结果数据保留原始值。遮罩于拥有者的请求或执行结束时清除。中止的 history 记为 `error`,journal 步骤保持 `cancelled`,不再获取错误截图。取消会穿过非严格执行、恢复/重试、回调与本机 worker;history 结算失败也不会取代原始硬中止信号。 - -## 命令行界面 - -每次 `je_auto_control run`(包括 `--dry-run` 与未带 `--var`)使用独立变量作用域。顶层 `run_from_description` 与 `StateMachine.run()` 也会隔离变量,同一次执行内的动作与状态仍可共享;嵌套调用沿用已有的执行作用域。自行创建的 `Executor()` 保留自己的变量。 - -```bash -je_auto_control run script.json [--var name=value] [--dry-run] [--allow-package NAME] -je_auto_control validate script.json # 别名:lint -je_auto_control fmt script.json [--check] -je_auto_control list-commands [--filter mouse] [--json] -je_auto_control record out.json [--duration 5] -je_auto_control codegen script.json --target pytest -o test_flow.py -je_auto_control failure-bundle failure.zip --error "login timed out" -je_auto_control list-jobs -je_auto_control start-server --port 9938 # TCP socket 服务器 -je_auto_control start-rest --port 9939 # REST API -je_auto_control version -``` - -`--var name=value` 会尽量以 JSON 解析(`count=10` 会变成整数),否则视为字符串。 -`run` 只要有任何动作失败就以 1 退出(仍会跑完整份脚本),CI 步骤会随之失败。旧版 `python -m je_auto_control -e file.json` 入口仍然可用,它的 `-e`、`-d` 与 `--execute_str` 标志也同样在有动作失败时以 1 退出。由 [TestPioneer](https://github.com/Integration-Automation/TestPioneer) 启动时(它会设置 `TEST_PIONEER_ARTIFACT_DIR`),以相对名称要求的 HTML、JSON、XML 报告会写到该目录底下。 - ---- - -## 服务器与集成 - -| 接口 | 启动方式 | 说明 | -|---|---|---| -| **MCP 服务器** | `je_auto_control_mcp`(stdio)或 `AC_start_mcp_http_server` | 820 个工具,供 Claude Desktop/Claude Code/自定义 tool loop 使用:完整的 `ac_*` 工具接口,以及常用 GUI 操作的短名称 alias。除了以 `initialize` 握手的各版协议,也支持无状态的 MCP 2026-07-28。Bearer 认证、TLS、审计日志、限流、插件热重载、CI 假后端。 | -| **REST API** | `je_auto_control start-rest` | Bearer token、按 IP 限流与锁定、SQLite 审计 hook、`/metrics`、`/openapi.json`、`/docs` Swagger UI、`/dashboard`。 | -| **TCP socket 服务器** | `je_auto_control start-server` | 以换行分隔的 JSON 动作列表。默认绑定 `127.0.0.1`。 | -| **pytest 插件** | 安装后自动生效 | 提供 fixture 与供 pytest-bdd/behave 使用的 Gherkin step library。 | -| **语言服务器** | `python -m autocontrol_lsp.server` | 为 `AC_*` 动作 JSON 提供补全与诊断,命令清单直接取自运行期的命令表。 | -| **远程桌面** | `RemoteDesktopHost` 或 GUI | TCP、WebSocket 或 WebRTC;TOTP、信任列表、TURN 配置、文件/剪贴板/音频同步。 | - -除非明确指定,所有服务器都绑定在 `127.0.0.1`。 - -MCP 窗口状态工具 `ac_window_minimize`、`ac_window_maximize` 与 `ac_window_restore` 在后端接受请求时返回窗口 handle,被拒绝时回复 `isError: true`(包括 handle 失效或激活请求被拒)。Win32 原始 `ShowWindow` 的先前可见性由后端规范化处理。 - -**包闸门。** `AC_add_package_to_executor` 与 `AC_add_package_to_callback_executor` 会导入 Python 包并把成员注册成命令,所以从上面任何一个入口送来的动作列表都可能加载 `os` 或 `subprocess`。没有被放行的包不会加载:不在允许清单上的包在导入前就被拒绝,该动作以 `AutoControlExecuteActionException` 失败。放行包(含子模块)的方式:在 Python 里调用 `executor.allow_packages("name", …)`;对所有入口——两个 CLI、socket/REST/MCP 服务器与调度器——设置环境变量 `JE_AUTOCONTROL_ALLOWED_PACKAGES`(以逗号分隔的名称,进程启动时读取);或只对一次 CLI 执行使用 `je_auto_control run script.json --allow-package NAME`(可重复)。`executor.set_allow_arbitrary_packages(True)` 会对所有包打开闸门,也就是先前版本的默认行为(当时会发 `DeprecationWarning`)。这些都不是 `AC_*` 命令,所以动作列表不能自己打开闸门。 - -**可选的加固设置。** 下列各项在设置之前都是关闭的,没设置的服务器行为与先前相同。`JE_AUTOCONTROL_RBAC_USERS=<用户文件>` 让 REST API 与 MCP HTTP 传输把 bearer token 对应到用户,并按角色(viewer/operator/admin)授权每一个路由、工具与特权 `AC_*` 命令;此时共用 token 会被拒绝。`JE_AUTOCONTROL_MCP_PATH_ROOTS`(以操作系统的路径分隔符分开的目录)把每一个属于文件路径的 MCP 工具参数限制在这些目录里,`JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT=1` 再加上 client 的 `roots/list`,`JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` 限制 `ac_resolve_ref` 可以读哪些 `env://` 名称。`JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` 让端点只能验证 Ed25519 签名的动作文件而不能签名(`create_signing_keypair`;私钥留在签名的机器上)。远程桌面的 viewer 只把 host 推来的文件写在 `~/Downloads/AutoControl` 下面(`JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR`);这一项默认就是开的。 - -REST GUI 在用户存储文件启用时显示 RBAC 模式并禁用共用 token 字段。`rest_api_registry.status()` 提供 `rbac_enabled`,该模式的 `token` 为 `null`;请使用个别用户 token。只实现 `check()` 的自制 REST gate 仍可用于共用 token 模式;RBAC 要求已验证的用户 context,会拒绝没有身份的成功结果。 - -RBAC viewer 不会取得列管的敏感读取工具,即使 MCP `readOnlyHint` 为 true:剪贴板/历史、本机文档/数据/SQL 与 dotenv 读取、引用解析、认证数据生成、持久存储读取、对外检查、麦克风捕获与外部 VLM 请求都需要 operator/admin。断言容器的 spec 也可能读取这些资源,因此同样需要 operator。屏幕观察与纯输入解析保持既有分类。`ac_realize_item`、`ac_idempotency_begin` 与 `ac_rate_limit` 会改变状态,已从 `--read-only` 模式排除。 - -间隔/cron 调度、触发器、热键、watchdog 规则、webhook、e-mail 触发器与 observer 回调会保留注册者身份。每次触发重新检查来源用户文件与角色;已删除的用户、无法使用的来源文件与 viewer 不能执行后台工作。启动 daemon 不会改变已有工作的所有者。所有者信息不保存 RBAC bearer token;未带 `store_path` 的显式 Python `AuthorizationContext` 保留角色快照,未在 RBAC 下注册的工作会清除 worker 原有身份。observer/watchdog 回调使用独立变量作用域,watchdog 动作失败不会算成成功消除弹窗。嵌套回调会保留调用端的失败计数;webhook 所有者被撤销权限时响应 HTTP 403 与 `fired: false`。 - -### 远程桌面的线路协议 - -TCP host 在发送 `AUTH_FAIL` 前就释放认证失败的 client 名额。Viewer 即使因错误 token、错误握手消息或拒绝批准而失败,也能立即重试,不必等待 socket 清理或日志完成;待处理握手仍有独立的资源上限。 - -把主机开放出去之前值得先了解,而且这一段在其他文档里都没有写。默认传输是**裸 -TCP 上的长度前缀分帧**(不需要额外依赖),连接一开始就是 **HMAC-SHA256 的 -challenge/response 握手**:认证不通过的观看端在拿到任何一帧之前就会被断开。 -JPEG 帧按配置的 FPS 与质量编码,再通过一个共享的**最新帧槽**发给已认证的观看 -端——所以慢的观看端是**丢帧**,不会把其他人一起卡住。观看端发来的输入是 JSON, -会先比对**动作允许列表**才交给既有的输入包装层执行,观看端无法自己发明新的操作。 - -```python -# 让别人连进来——启动一个主机,把 token 与 port 给对方 -from je_auto_control import RemoteDesktopHost -host = RemoteDesktopHost(token="hunter2", bind="127.0.0.1", - port=0, fps=10, quality=70) -host.start() -print("listening on", host.port, "viewers:", host.connected_clients) -``` - -```python -# 控制另一台机器——连上去并发送输入 -from je_auto_control import RemoteDesktopViewer -viewer = RemoteDesktopViewer(host="10.0.0.5", port=51234, token="hunter2", - on_frame=lambda jpeg: ...) -viewer.connect() -viewer.send_input({"action": "mouse_move", "x": 100, "y": 200}) -viewer.disconnect() -``` - -也可以用 IP 允许列表(CIDR 网段或具体地址)限制谁能连进来,列表外的对端在握手 -阶段就会被拒绝: - -```python -RemoteDesktopHost(token="tok", ip_allowlist=["10.0.0.0/8", "192.168.1.100"]) -``` - ---- - -## 平台支持 - -| 平台 | 后端 | 输入 | 屏幕捕获 | 录制 | 窗口管理 | -|---|---|:---:|:---:|:---:|:---:| -| Windows 10 / 11 | Win32 ctypes(可选 Interception 驱动) | ✅ | ✅ | ✅ | ✅ | -| macOS 10.15+ | pyobjc / Quartz | ✅ | ✅ | ✅¹ | ✅ | -| Linux X11 | python-Xlib(可选 `uinput`) | ✅ | ✅ | ✅ | ✅ | -| Linux Wayland | 经桌面 portal 的 libei,或 ydotool/wtype + 截图工具 | ✅ | ✅ | ❌ | ❌ | -| FreeBSD/OpenBSD/NetBSD | python-Xlib,与 Linux 同一套 X11 后端 | ✅² | ⚠️² | ✅² | ✅² | -| Android | adb + uiautomator2 | ✅ | ✅ | — | — | -| iOS | WebDriverAgent / facebook-wda | ✅ | ✅ | — | — | - -¹ macOS 的录制走 Quartz event tap,需要**辅助功能**权限 -(系统设置 → 隐私与安全性 → 辅助功能)。没有授权时会直接抛出并指名 -缺的是哪个权限,而不是安静地录到一个空的 session。 - -² BSD 直接跑同一套 X11 后端——同一个 X server、同一个 `python-Xlib`,而输入、 -录制与窗口管理就只依赖这一个包。`freebsd` CI job 在真的 FreeBSD 14 上驱动真的 -输入,再从 X server 读回来;OpenBSD 与 NetBSD 走同一条代码路径,只是没有 CI -runner。唯一的例外是屏幕截取,卡住的是打包而不是平台:它走 Pillow/mss 与 -OpenCV,而 `opencv-python`、`pillow`、`cryptography` 都没有发 FreeBSD wheel。 -从 ports 构建之后,截取、图像匹配、OCR 与动作加密也都能用—— -`import je_auto_control` 本身已经不需要它们任何一个。 - -Wayland 的按键、按钮与指针输入在 `auto` 模式下,仅在可选原生后端缺失时改用 CLI。 -portal 请求开始后,拒绝、超时、握手失败、设备暂停或权限撤销都会停止输入, -不会自动切换提供者;重复调用保留不含原生资源的失败状态,不重开同意对话框。 -`JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND=libei` 强制原生输入,`=cli` 明确选择 CLI。 -解决权限问题后,可明确调用 `je_auto_control.linux_wayland.libei.reset_default_backend()` -以允许重新请求。原生组合键中断时会在同一后端尝试释放所有已按下的按键,并保留原始取消。 -此行为不改变明确的 wtype 文本输入路径或屏幕截取选择。 - -`ydotool` 退路需要 -**ydotool 1.0 以上**。AutoControl 送的每一个参数都是那一版才有的;0.1.x -(Debian bookworm 与目前所有 Ubuntu 仍以这个名字提供,Debian trixie 则根本没有) -对同一批参数返回 0 却不送出任何事件。AutoControl 会检测并直接拒绝, -而不是为根本没送出的输入回报成功。Arch、Fedora 与 Debian unstable 提供的是 1.0。 - -这条退路要能**准确定位**,还有一个前提:合成器的指针加速度必须是关的。 -`ydotool mousemove --absolute` 并不发任何绝对事件——它先把光标推到合成器夹取的 -那个角落,再发相对位移,所以这段位移会被合成器加速。对真的 wlroots session 量到的是: -libinput 的默认 profile 让光标走的距离正好是请求的两倍。ydotool 自己的 `--help` -也是这样写的;AutoControl 每个进程会记一次警告,而不是安静地把点击放到错的地方。 -请对 ydotoold 的设备关掉加速度(sway:`input type:pointer accel_profile flat` -加上 `pointer_accel 0`),或者装上 `liboeffis`,改走协议层本来就是绝对坐标的 libei。 - -倍率是合成器自己的设置,客户端读不回来,所以只有你知道它关了没有: -`JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL=flat` 表示已经关掉,移动就不再出声; -`=strict` 则宁可拒绝这次移动,也不让点击落在别的地方;不设置就维持 -“警告一次后照样移动”的默认。 - -Wayland 的屏幕截取需要合成器对应的工具,因为没有单一工具能覆盖全部:wlroots 系 -(sway、Hyprland、river)用 `grim`,GNOME 用 `gnome-screenshot`,KDE 用 `spectacle`。 -装好其中一个之后,所有截取路径——截图、图像与锚点定位、OCR、屏幕录制、远程桌面——都会 -经由它。三个都没装时,内置 D-Bus client 会通过 session bus 尝试 `xdg-desktop-portal`,第一次可能会弹 -同意对话框。再不行,截取会带着安装提示明确失败,而不是返回空白的 XWayland root; -`je_auto_control.api.run_diagnostics()`(以及 GUI 的 Diagnostics 标签页)的 `screen_capture` -检查会报告当前使用的是哪一层。 - -原生 Wayland 指针坐标在原始坐标与布局原点换算后仍不属于任何授权 EIS 区域时, -会以 `state="failed"` 的 `LibeiUnavailable` 拒绝,停止自动 CLI 备用, -不发送移动、frame 或后续点击。有效坐标、未提供区域的设备、同一 sender 的后续有效请求, -以及显式选择 CLI 的现有行为保持不变。 - -**输入/截取能力**提供 `je_auto_control.api`(也由包根目录导出)的 -`BackendContext`、`CapabilityStatus`、`CapabilitySnapshot` 与 `probe_capabilities`。 -调用 `probe_capabilities(BackendContext.current()).to_dict()`、无参数的 -`AC_probe_capabilities`/只读 `ac_probe_capabilities`,或选择 -**Diagnostics → Actions → 查看输入与截取能力**;Builder 提供相同无参数命令。 -`python -m examples.capabilities` 显示本机前置条件与确定性的 XWayland 范围示例,不操作桌面。 - -输入项描述按键/指针事件;现有 wtype 文字路径独立。探测只读环境、PATH 与不等待锁的现有原生状态, -不加载可选原生库、不连接、不读取事件、不截取或请求授权。找到工具或 bus 地址只代表 -`unverified`,不等于可用。缓存 libei 须完成握手,且键盘、绝对指针、按钮与滚轮事件种类都在运行才报告可用; -部分授权保持未验证,事件种类暂停或必要设备移除则报告暂停/撤销。八种状态为 `available`、`unverified`、`needs_permission`、 -`needs_dependency`、`unsupported`、`paused`、`revoked`、`failed`。 -`available` 仅是最近的本机观察,可能过时;实际操作仍重新验证权限。XWayland 一律 -`desktop_wide=False`,无法覆盖原生 Wayland 窗口;其他范围标记仍受授权区域限制,不代表已验证每个屏幕。 - -Context 会复制环境/工具数据,可由拥有者提供无原生对象的输入/截取观察,但不授予权限。 -默认本机结果不含环境值、命令参数、可执行文件路径或原生错误文字;AC/MCP 不接受外部提供观察。 -显式选择 CLI 与观察到可选原生依赖缺失后的自动备用分开;拒绝、暂停、撤销与失败不表示改走 CLI。 -截取工具/portal 选择独立诊断,重绘与切换语言只使用现有快照。原生 portal 恢复、compositor 重启、 -截取结果与 context 的接合,以及原生 session 的重试/取消/停止控制仍列于 `Progress.md`。 - -GUI 工作基础提供 `gui.task_controller.TaskController`: -`submit(work, owner=widget)` 返回调用者持有的 `TaskHandle`,通过 -`TaskOutcome`/`TaskProgress` 传递终态与进度。工作取得不依赖 Qt 的 -`CancellationToken`,提供 checkpoint、有界且可被取消唤醒的等待与进度报告。 -提交时捕获 context,执行前重新读取 store 用户;工作须持有数据、不引用 widget,并验证自身操作所需的 capability。 -现有 `DeferredAuthorization.scope()` 保持输入权限要求,`context_scope()` 仅更新并绑定身份。 - -拥有者、handle 或 controller 销毁时会请求协作式停止并丢弃延迟结果;每项工作有独立 ID/token, -回调在 GUI 线程执行。不强制中断不配合的调用,也不把已成功提交的结果改标为取消。 -错误与进度使用捕获的秘密遮罩 scope,终态不保留异常 traceback;线程启动失败会恢复两层登记并保留原失败。 -Diagnostics 已接入此共用控制器;其余面板/backend 迁移与原生 session 操作仍列于 `Progress.md`。 - -主动 **Diagnostics → Actions → 运行诊断** 以共用控制器在 GUI 线程外运行。 -**停止诊断** 请求协作式停止;四种语言的状态区分运行中、清理中、已取消和失败,并显示已完成检查数。 -重复运行不另开工作,关闭后丢弃延迟进度/结果,显式重试会建立新的拥有者工作。 -GUI 以不保留异常 traceback 的 typed outcome 呈现取消;核心/SDK/CLI 与 MCP handler -保持原始直接/包装取消对象。普通检查错误仍计入报告并继续其余项目。 - -两个 SDK namespace 导出 `CancellationToken`、`TaskProgress`、`cancellation_scope`。 -使用 `with cancellation_scope(token): report = run_diagnostics()`,拥有者可由另一线程调用 -`token.cancel()`;现有无参数诊断签名不变。Scope 不授予权限,`cancellation_scope(None)` -只在有时限的自有资源清理期间暂停取消。`AC_diagnose` 与新增的只读 `ac_diagnose` 共用报告; -MCP 不接受参数,使用请求取消/进度,与显式 GUI 操作同样需要 `read_screen`,拒绝外部 token/授权数据。 -这些是主动检查,截取可能请求同意;`ac_probe_capabilities` 保持独立的被动选项。 - -Scoped Wayland D-Bus 的连接/读取/部分写入,以最多 0.1 秒的间隔轮询,保持原本总时限。 -取消时在原 bus 以独立 0.25 秒预算尝试 Request.Close,再释放连接;取消的已返回图片会删除。 -Scoped CLI 截取会停止并回收自己建立的 helper/process group,清理有时限,pipe close 失败也不覆盖原取消, -已回收的数字 PID 不再作为信号目标。liboeffis 获取 session 时会观察停止并释放自身 context。 -不强制中断不配合或原生调用,清理期间 GUI 仍可操作;restore/重启、原生 session 控制、 -截取拥有者 metadata 与其余面板/backend 迁移保留于 `Progress.md`。 - -`python -m examples.cancellable_diagnostics` 默认只做受控取消示例,不调用 provider。 -`--active --cancel-after 2` 才显式运行诊断并在两秒后请求停止;真机/设备/API 验收另外列管。 - -打开 Diagnostics 只显示已翻译的「尚未运行」状态,不执行检查。 -选择 **Actions → 运行诊断** 才会启动现有主动检查,可能截取屏幕或需要 portal 同意; -切换语言不启动检查。显式的 `run_diagnostics`、`AC_diagnose` 与 MCP 诊断调用保持主动行为; -无副作用的能力查看使用下方独立操作。 - -未完成的 screenshot portal 请求会在断开原始 bus 前尝试 `Request.Close`, -使用独立的 0.25 秒 D-Bus I/O 预算。服务器返回替代 handle 时会跟随该 handle; -方法回复不确定时则使用预测 handle,已完成的 Response 不重复关闭。 -普通清理错误不覆盖主要截取失败;原始取消与强制中断对象会穿过包装及清理继续传播。 -D-Bus 写入与回复共用调用预算,连接建立有明确时限,connect/认证/Hello 中断时, -即使 `__enter__` 失败也会释放自己拥有的描述符。实际合成器/对话框取消仍待平台验收。 - -有一件只在 Wayland 出现、需要事先规划的事:**截取回来的图里可能有鼠标光标。** -这里没有任何一条截取请求光标,但只要 backend 没有光标平面(包含任何以 -`WLR_NO_HARDWARE_CURSORS=1` 运行的 session),wlroots 就会画**软件光标**并把它 -合成进输出缓冲区,而截取交回来的正是那一份。Windows 与 X11 都不含光标,所以 -“定位器、模板匹配或 OCR 在目标中间看到一个光标形状的洞”只会在这里发生。 -Wayland 不让客户端读光标位置,所以没有东西可以可靠地遮或避开:请在截取之前 -把指针移离要拍的区域。`screen_capture` 检查会以 `cursor_may_be_captured` 报告这件事。 - -如果以上都不适用你的环境,可以直接指定自己的命令——它优先于所有检测,`{output}` 会被 -换成临时 PNG 路径: - -```bash -export JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND="mycapture --png {output}" -``` - -Wayland 禁止非特权客户端进行全局输入录制——若要录制,请设置 -`JE_AUTOCONTROL_LINUX_DISPLAY_SERVER=x11` 并在 X11 会话下运行。窗口管理支持 -Windows、macOS(pyobjc)与 X11(含 XWayland);纯 Wayland 会话的协议不让客户端看到其他程序的窗口, -所以 `list_windows()` 返回空列表,其余窗口操作一律抛出带原因的 `AutoControlUnsupportedOperationException`。对于会忽略合成输入的应用, -可选用驱动层后端(`JE_AUTOCONTROL_WIN32_BACKEND=interception`、 -`JE_AUTOCONTROL_LINUX_BACKEND=uinput`、ViGEm 虚拟手柄);驱动未安装时会自动回退到原有行为。 - ---- - -## 配置 - -AutoControl 读取的每一个环境变量。这里没有任何一项是必填的:完全不设置时,AutoControl 会自行选择平台后端,服务器只绑定 `127.0.0.1`,所有需要主动开启的功能(签名强制、RBAC、USB 直通、工具路径限制)都是关闭的。[配置参考](https://autocontrol.readthedocs.io/en/latest/Zh/doc/configuration/configuration_doc.html)([源文件](../docs/source/Zh/doc/configuration/configuration_doc.rst))列出完整的可接受值,并把每个变量链接到说明该功能的页面;CI 会拿它以及下面的表格和代码比对。 - -### 平台后端 - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_WIN32_BACKEND` | `sendinput` | 设为 `interception` 时键盘与鼠标改走 Interception 驱动程序;找不到驱动或 DLL 时会警告并回退到 `SendInput`。 | -| `JE_AUTOCONTROL_LINUX_BACKEND` | `x11` | 设为 `uinput` 时直接写入内核输入事件;`/dev/uinput` 无法写入时会警告并回退到 XTest。 | -| `JE_AUTOCONTROL_LINUX_DISPLAY_SERVER` | `auto` | 决定加载哪一个 Linux 后端:`auto` 读取 `XDG_SESSION_TYPE` 与 `WAYLAND_DISPLAY`;`wayland` 或 `x11` 则强制指定(在 Wayland 会话设为 `x11` 只能操作 XWayland 窗口)。 | - -### Windows Interception 驱动程序 - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_INTERCEPTION_DLL` | 未设置:先找 `PATH`,再找包旁边 | `interception.dll` 的完整路径。 | -| `JE_AUTOCONTROL_INTERCEPTION_KEYBOARD` | `1` | 键盘事件要发往的 Interception 设备编号(`1`–`10`)。 | -| `JE_AUTOCONTROL_INTERCEPTION_MOUSE` | `11` | 鼠标事件要发往的 Interception 设备编号(`11`–`20`)。 | - -### Wayland - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND` | `auto` | 设为 `cli` 时通过 `ydotool` 发送输入,完全不向桌面 portal 提出请求。这是启动前就做好的选择:用户拒绝授权后,AutoControl 不会自行切换过去。 | -| `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL` | `warn` | 只影响 `ydotool` 路径的绝对移动(那其实是会被合成器加速的相对位移):`warn` 警告一次后照样移动,`flat` 表示加速已关闭、不再警告,`strict` 直接拒绝移动。 | -| `JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND` | 未设置 | 自定义的截图命令行,以 `{output}` 表示 PNG 的输出路径。优先于 `grim`、`gnome-screenshot`、`spectacle` 与 portal。 | -| `JE_AUTOCONTROL_WAYLAND_RECORD_DEVICES` | 未设置:一个都不读 | `PhysicalRecorder` 可以读取的 `/dev/input/event*` 设备(以逗号分隔);物理输入录制必须逐一指定设备才会启用。 | - -### MCP 服务器 - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_MCP_READONLY` | 未设置 | 设为 `1` 时只提供、也只能调用标记为只读的工具。 | -| `JE_AUTOCONTROL_MCP_TOOL_PROFILE` | 未设置 | `static` 模式的工具清单:以逗号分隔的工具名称与 `category:<名称>`。 | -| `JE_AUTOCONTROL_MCP_ALIASES` | `1` | 设为 `0` 时不注册 `ac_*` 工具之外的简短别名(`click`、`screenshot` …)。 | -| `JE_AUTOCONTROL_MCP_TOKEN` | 未设置 | HTTP 传输的 Bearer 令牌。启用 RBAC 之后不再接受。 | -| `JE_AUTOCONTROL_MCP_ALLOWED_ORIGINS` | 未设置:只接受本机来源 | HTTP 传输额外接受的浏览器来源(以逗号分隔,须完全相符,例如 `https://example.test:8443`)。 | -| `JE_AUTOCONTROL_MCP_CONFIRM_DESTRUCTIVE` | 未设置 | 设为 `1` 时具破坏性的工具在执行前先向客户端请求确认(MCP elicitation)。 | -| `JE_AUTOCONTROL_MCP_PATH_ROOTS` | 未设置:不限制 | 工具的每一个文件参数都必须落在这些目录内(以操作系统的路径分隔符分隔)。 | -| `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` | 未设置 | 设为 `1` 时同时接受 MCP 客户端通过 `roots/list` 报告的根目录。 | -| `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` | 未设置:不限制 | `ac_resolve_ref` 可以读取的环境变量名称(以逗号分隔,可用 `fnmatch` 模式);设了却没有指名任何变量时,一个都不允许。 | -| `JE_AUTOCONTROL_MCP_AUDIT` | 未设置 | JSON-lines 文件的路径,每一次 `tools/call` 写入一条记录。 | -| `JE_AUTOCONTROL_MCP_ERROR_SHOTS` | 未设置 | 工具每次失败时存放截图的目录。 | -| `JE_AUTOCONTROL_FAKE_BACKEND` | 未设置 | 设为 `1` 时 MCP 服务器只在内存中记录鼠标、键盘与剪贴板调用而不实际执行,供没有显示器的 CI 使用。 | - -### REST/RBAC 与 chat-ops - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_RBAC_USERS` | 未设置:沿用共享令牌 | 用户文件的路径。设置它就等于为 REST API 与 MCP HTTP 传输启用角色。 | -| `JE_AUTOCONTROL_CHATOPS_SCRIPT_ROOT` | 未设置:`run` 会被拒绝 | chat-ops 的 `run` 命令唯一可以加载动作文件的目录。 | - -### 执行与签署动作文件 - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_ALLOWED_PACKAGES` | 未设置:一个都不允许 | `AC_add_package_to_executor` 可以加载的包(以逗号分隔,含子模块),对所有入口生效。只在进程启动时读取一次。 | -| `JE_AUTOCONTROL_REQUIRE_SIGNED_ACTIONS` | 未设置 | 设为 `1` 时所有会执行动作文件的路径,都拒绝没有有效签名文件的动作文件。 | -| `JE_AUTOCONTROL_ACTION_SIGNING_PRIVATE_KEY` | 未设置 | Ed25519 私钥(PEM)的路径。只在负责签署的机器上设置;设置后签署会写出第 2 版的签名文件。 | -| `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` | 未设置 | 对应公钥的路径。在每一台执行端设置:它只能验证,不能签署。 | -| `JE_AUTOCONTROL_ACTION_SIGNING_PASSPHRASE` | 未设置 | 私钥创建时若设置了口令,在这里提供。 | -| `JE_AUTOCONTROL_ACCEPT_LEGACY_ACTION_SIGNATURES` | 未设置 | 设为 `1` 是迁移模式:设置公钥之后,第 2 版之前写出的 HMAC 签名文件会被拒绝,除非设置了这个变量。所有文件重新签署后请再关掉。 | - -### 远程桌面与信令 - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR` | `~/Downloads/AutoControl` | 远程桌面查看端存放主机传来文件的目录。收到的路径一律限制在这个目录内。 | -| `JE_AUTOCONTROL_USB_PASSTHROUGH` | 未设置 | 设为 `1` 时在远程桌面通道上启用 USB 直通指令。 | -| `AC_SIGNALING_SECRET` | 未设置 | 信令/配置同步服务器的共享密钥(`X-Signaling-Secret`)。服务器在没有 `--shared-secret` 时读取它。 | - -### GUI - -| 变量 | 默认 | 作用 | -|---|---|---| - -### 日志、数据与测试 - -| 变量 | 默认 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_LOG_FILE` | `~/.je_auto_control/logs/AutoControlGUI.log` | 日志文件写入的位置。指定空设备(`/dev/null`、`NUL`)即可关闭文件输出。在写入第一条记录时才读取,而不是在 import 时。 | -| `JE_AUTOCONTROL_ENV` | `default` | 资产库当前使用的环境(`active_environment()`),让同一份脚本在 `dev` 与 `prod` 读到不同的值。 | -| `JE_AUTOCONTROL_REDACTION` | `off` | 截图遮蔽的默认策略:`off`、`moderate` 或 `strict`。未知的名称会报错,不会被当成 `off`。 | -| `JE_AUTOCONTROL_PYTEST_ARTIFACTS` | `./autocontrol_screenshots` | 测试没有使用 `autocontrol_screenshot_dir` fixture 时,pytest 插件写入失败截图的目录。 | - ---- - -## 文档与示例 - -| 资源 | 内容 | -|---|---| -| [`examples/`](../examples/) | 45 个自包含脚本:截图点击、OCR、调度器、远程桌面、agent loop、可观测性、录制、变量、热键、触发器、报表、MCP、REST、密钥、插件、computer use、Wayland、跨主机 DAG、chat-ops、pytest/BDD、锚点定位、动作日志。 | -| [Read the Docs](https://autocontrol.readthedocs.io/en/latest/) | 完整 API 参考,含英文与中文。 | -| [architecture_explore.md](../architecture_explore.md) | 逐层记录每个模块的职责。 | -| [docs/CAPABILITY_MATRIX.md](../docs/CAPABILITY_MATRIX.md) | 能力 × 平台对照矩阵。 | -| [docs/API_LIFECYCLE.md](../docs/API_LIFECYCLE.md) | 稳定 API 与弃用策略。 | -| [docs/updates/](../docs/updates/README.md) | 更新记录:各版本说明与完成的工作,每月一个文件(原 `WHATS_NEW.md`)。 | -| [CHANGELOG.md](../CHANGELOG.md) | 兼容性变更记录。 | -| [SECURITY.md](../SECURITY.md) | 安全策略与报告方式。 | - ---- - -## 开发 - -```bash -git clone https://github.com/Integration-Automation/AutoControlGUI.git -cd AutoControl -pip install -r dev_requirements.txt -uv sync # 或:以已提交的 uv.lock 做可重现安装 -``` - -```bash -python -m pytest test/unit_test/headless # 无头单元测试 -python -m pytest test/integrated_test/ # 跨模块流程测试 - -ruff check je_auto_control/ -pylint je_auto_control/ -bandit -c pyproject.toml -r je_auto_control/ - -python test/verify/typing_contract_verify.py # mypy,整个包,三个目标平台 -python test/verify/typing_contract_verify.py --extras # 同一项检查,改用真正的 PySide6/aiortc 类型 -python -m sphinx -b html -W docs/source docs/_build/html # 文档,警告视为错误 -``` - -dev/main 的无头任务会保留七天的 `native--` artifact,内含合并进程输出、 -包/运行环境版本与退出码。Linux 经 GDB 保留各线程原生堆栈;其他平台保留 Python -faulthandler 输出,测试失败仍会使任务失败。可在 repo 执行单一命令 -`python scripts/ci_native_diagnostics.py --artifact-dir test-artifacts -- python -m pytest -v --tb=short --timeout=120`; -Linux 安装 GDB 后,可在 `--` 前加入 `--native`。 -含空格/引号的 argv 仍是原始参数,已处理的 `SIGINT` 会传给子进程。 -Linux 先在完整套件的 debugger 外验证诊断工具;前置检查记录也收在同一 artifact。 - -选定的 dev 推送由 `.github/workflows/ei-lifecycle.yml` 在隔离 libei/libeis -容器执行,将版本及两份原生记录保留于 `ei-lifecycle--` artifact 十四天。 -半开与 live 释放子进程分别有十/六十秒时限与 faulthandler;其他子进程失败使 CI 失败, -释放成功必须有 begin/end 标记。半开探测另须有相同整数 fd 数量,live 清理先释放拥有的 -device refs。run 39507190704 在 libei/libeis 1.3.901-1 通过 9/9 与 20/20 检查, -包含坐标越界拒绝且不转用 CLI。半开 `ei_unref` 仍会 SIGSEGV,因此保留 runtime 保护, -helper 隔离仍待完成。设备暂停与序号回读仍未验证;受控 socket peer 不代表合成器授权、 -真机或多屏幕验收。 - -欢迎贡献——请见 [CONTRIBUTING.md](../CONTRIBUTING.md) 与 -[CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md)。CI 会强制两条规则:`import je_auto_control` -绝不能加载 PySide6;每个功能都必须同时具备无头 API 与 GUI 界面。 - ---- +- [安装、平台支持与配置](../docs/guides/zh-CN/setup.md) +- [Python、JSON 与命令行用法](../docs/guides/zh-CN/usage.md) +- [AI Agent、MCP 与服务器整合](../docs/guides/zh-CN/integrations.md) +- [完成验证与证据移交](../docs/guides/zh-CN/evidence.md) +- [开发与相关资源](../docs/guides/zh-CN/development.md) +- [实现记录](../docs/guides/zh-CN/implementation-notes.md) +- [文档目录](../docs/README.md) +- [示例](../examples/README.md) +- [项目进度](../Progress.md) ## 许可 -[MIT License](../LICENSE) © JE-Chen。 -内含与可选第三方组件的许可请见 [Third_Party_License.md](../Third_Party_License.md)。 - -- **主页**:https://github.com/Integration-Automation/AutoControlGUI -- **PyPI**:https://pypi.org/project/je_auto_control/ -- **文档**:https://autocontrol.readthedocs.io/en/latest/ - -旧式 MCP 动作包装、并行分支及本机 DAG worker 也会保留相同的来源限制。 - -受管指针动作可指定该次观察的元素索引或缩略图坐标,由主机检查当前画面并换算原生坐标,包括缩放与负屏幕原点。收据保存几何依据,不保存图像字节。`AgentObservationStale` 表示分派前已拒绝动作;本机 agent 只在 adapter 确认没有按住或待处理输入时,在重试预算内重新观察。 - -紧急停止先返回带有 metadata.details_deferred 的精简状态,完整产物链接可由单个任务查询。 - -托管鼠标按下前会规范按钮所有权并确认实际光标位置。Windows 指针检查会拒绝其他窗口遮挡。影像仅将指定窗口绘制到清空的私有 GDI 内存,几何变化会拒绝该画面;绘制或读取失败也会释放资源。不改用桌面捕获。这些路径已用模拟原生 API 测试,实际原生验收仍未验证。 - -Agent 任务界面将任务范围、工作流程设置、触发器、技能及恢复分页。观察页显示只读元素和已验证、严格遮罩的 JPEG,每个逻辑画面像素对应一个呈现像素。选择元素或影像坐标只会编辑该次观察的动作请求;由 Actions 的「执行观察动作」通过共用任务 API 发送。切换任务会清除预览,迟到回复不能替换当前任务;新画面必须重新选择,旧索引不能直接复用。关闭界面仅解除请求订阅。 - -托管工作流程可用 workflow_wait/AC_workflow_wait 等待指定控件的精确值或状态,只重复读取;可取消且受动作预算限制,默认五秒、上限六十秒,不重发写入或提交。固定技能每一步都验证已有收据与固定顺序,恢复也不能跳过读回失败的步骤;模型自主循环仍保留停滞检测。新表单/跨应用模板会在提交前拒绝原本已匹配的确认值,提交后等待新的状态转换。批次可设置 new_record_selector 逐条重置;确认仅证明配置的界面转换,有交易标识值时应使用它。归档模板完成时会重读指定清单及文件摘要,清单上限一 MB,总验证数据上限六十四 MiB。 - -AgentHumanReview 表示未保存内容或未知对话框需人工审核;包括外部观察请求都会记录 waiting_user 并释放输入控制权,明确恢复后仍会重新检查。Windows 依据原生对话框/禁用所有者及英中日已知未保存文字判断。Workspace 也会拒绝标题首尾带星号的文档,并可在窗口设置中加入 unsaved_selector 与 unsaved_value,在改变排列前检查应用特有指示;不声称能推断所有程序的未保存状态。标准文件对话框沿用 AC_handle_file_dialog 执行器,托管 driver 只接受唯一精确标题、相同 PID、已确认前景,以及授权根目录内的绝对路径。UIA 控件须属于实际指定的根窗口,同 PID 的其他窗口也会拒绝。模拟原生与本机 HTTP 测试已有覆盖,实际平台验收仍未验证。 - -主机目标通过 AgentTargetProfile 与 manage_agent_target(AC_agent_target,register/get/disable/enable/probe)设置。名称及设置固定不可替换,目前提供 desktop/files/browser adapter,未实现类型会被拒绝;浏览器可使用主机审阅的 helper_python。任务固定主机设置摘要,不能扩大工具、应用、根目录或网络来源。启停状态会跨重启保存并在分派时检查;禁用会请求暂停及清理,重新启用仍须明确恢复任务。list_agent_targets/AC_agent_target_list/CLI agent-task targets 仅提供被动信息,readiness=not_probed、native_evidence=not_recorded;完整设置需要 manage_hosts。CLI agent-task target 及 GUI「主机目标」页使用同一服务。匿名有效 MCP 工具 session 的直接及旧式包装调用都以 operator 权限执行;MCP 主机管理需要已验证的管理员,可信任的直接 Python 调用维持原行为。浏览器自动化统一由 WebRunner(je_web_runner)提供,本机开发来源为 D:/Codes/WebRunner;browser profile 使用受管 je_web_runner SDK 契约,依赖诊断不代表原生可用。 - -既有浏览器自动化(包括 open_path(URL) 与 AC_open_path)统一交由 WebRunner,Python 包名为 je_web_runner。URL 计划的 backend 现为 je_web_runner,原本比较 webbrowser 描述值的调用端需改用新值;函数接口与本机文件打开维持兼容。实际 URL 执行需要配置的 WebRunner 项目,缺少时传出 WebRunnerBridgeError,不改用 OS 浏览器。本机开发来源为 D:/Codes/WebRunner;纯计划及注入 opener 测试不需要该包。协议支持由 WebRunner 与所选浏览器决定。既有浏览器 GUI/MCP/AC 及录制的 WR_* 动作都使用同一桥接。 - -## Local DAG 完成证据的明确移交 - -其他 caller 持有的既有恢复子任务,可通过明确且可撤销的移交,向原 local DAG 提供完成证据。 -以 `manage_agent_recovery` 的 `review_handoff` 提供最终 `task_id`、`batch_id`、`node_id`, -有权管理者再用相同 ID、将返回的 `handoff_review` 填入 `review`,并附非空 `note` 执行 -`create_handoff`。接收者由服务依真实原始 admission 决定。在 `review_continuation` 的 successor -决策中,除 `node_id`、`action`、`task_id` 外明列 `handoff_id`,再审核并批准整份 continuation。 -最多支持十六层真实恢复链,包含经私有 admission 的永久只读最终验证者;一般任务归属保持原样。 - -`get_handoff`/`revoke_handoff` 使用 `handoff_id`;`list_handoffs` 使用 `batch_id`、`node_id`。 -创建与采纳时重查实际 owner、创建审核者、签发 session 的来源根限制、当前接收端限制、固定 scope、 -效果快照、独立完成及资源退役。批准、开始及后续依赖验证都重查同意;撤销或证据丢失会阻止采纳。 -期限不超过最早终止见证既有的三十天保留期限。公开响应只含有限 ID、摘要与状态,不含私有参数、 -capture 或 principal 数据库路径;不授予一般任务读取/输入权、不转移归属或重放。 -跨主机及非 DAG 的移交契约仍列于 `Progress.md`。 - -Agent Tasks 的成果移交页提供操作菜单与 JSON 编辑器;Actions 只准备审核、创建、撤销请求, -不自动派发。五个可编辑的 `agent_handoff_*.json` 示例涵盖 review/create/get/list/revoke。 -Python、AC、CLI、具名 MCP、REST、Builder 共用这些 recovery 操作。本次证据涵盖契约及自有文件 -流程;暂缓的原生桌面、浏览器、设备及二十四小时验收仍须各自提供证据。 - -## 明确续授权只读完成验证 - -原来源的 origin 引用过期或不可用时,明确调用 -`manage_agent_recovery("review_completion_authorization", {"task_id": ""})`。 -审核服务产生的 `verification_spec`、保留/替换/当前 origin 限制,再以相同 `task_id`、返回的 -`snapshot`、`authorization_review` 及非空 `note` 调用 `create_authorized_completion`。 -可选 `owner_policy="source_owner"` 在创建时另须返回的 `ownership_review`;不能自行提供新验证 -规范。仍有效的旧限制保留,新根目录与原上限、前一读取者上限及当前 session 取交集。 -已重新授权的读取者不能改用一般完成审核来移除这些限制。 - -子任务永久只读,依真实已确认的原效果独立检查当前条件,不输入、不重放、不恢复 capture, -也不修改旧见证。来源/效果快照、实际 owner/reviewer 及原 DAG admission 都会重查。 -创建任务与最终完成各自在自己的 SQLite writer 内写入后重验,变化时共同回滚。 -最多支持十六层真实恢复链;已退役且成功的读取者可再次明确续授权,但保留前次较窄上限及所有仍有效 -的继承限制。来源/效果证据已改变时仍拒绝,不能借 scope 续授权默默修复旧证据。 - -历史 `get` 保留 succeeded 状态;新授权失效时,当前 `completion_contract` 为零、 -`completion_authorization` 为 unavailable,DAG 采纳与后续依赖验证会拒绝这份证据。 -新的只读标记损坏/丢失时,在 helper 启动前拒绝。以 `completion_task_id` 录制时沿用原语义动作及 -已审核的限缩 scope,但草稿仍须自己的新验证试跑。此流程不发布过期候选,也不续授权已发布技能; -既有技能重新授权流程保持分开。 - -Python、AC、CLI、具名 MCP、REST、Builder 共用两个操作;Recovery 页的两个明确 Actions -沿用所选任务、owner policy 与请求编辑器。可编辑示例为 `agent_completion_authorization_review.json` -与 `agent_completion_authorization_create.json`。remote 只读来源、跨主机移交、 -实际应用状态重建,以及暂缓的原生/设备/浏览器/二十四小时验收仍列于 `Progress.md`。 - -## 明确移交已续授权读取者的完成证据 - -现有 `review_handoff`/`create_handoff` 现在可明确将已重新授权、永久只读读取者的完成 -证据交给实际原 local DAG。指定该读取者的 task ID 与原 batch/node,由服务推导证明;不能自行提供 -policy、所有者覆盖或授权 bundle。一般成果移交沿用现有规则。 - -预览的 `evidence.completion_authorization` 显示完成任务/审核、固定的审核摘要、根目录数量及 -替换/保留/当前 origin ID,不含私人 principal 路径、动作参数或 capture。创建时以最上层返回的 `handoff_review` -作为请求的 `review`,并提供非空 `note`。每个真实任务都保留已审核的上限与所有仍有效的历史限制;不可用的 -引用须明确审核替换,发出移交时额外的 session 限制也持续有效。移交沿用读取者已实际验证的相同 -根目录;交集改变时须重新审核及执行只读完成验证,接收者的 session/profile 限制也会持续应用。 - -最多十六层真实恢复链可混合先前已审核的可执行子任务及私人读取者。成功的中间读取者必须具备实际 -私人历史 scope 与退役证明,一般已成功来源没有这个例外。发出或采纳移交时不启动 helper、不重放 -输入;旧来源状态、见证、收据及所有任务所有者维持原样。原所有者只取得有限完成投影,不能因此 -一般读取其他 caller 的任务。撤销或授权失效会阻止采纳及后续依赖验证。 - -原 accepted-request hash、原始提交见证、私人 admission、graph、owner/reviewer、整条来源/子任务 -快照与最后读取者的续授权都固定在证明内。读取与写入后重验使用同一个 SQLite writer,包含尚未提交 -的变更;发现变动即回滚任务/移交创建。继承的 `dag_batch` 选项不等于 admission,必须沿有界真实 -恢复链找到原请求及实际授权身份,不补造 admission。旧的一般完成 binding hash 保持兼容;各历史 -任务各自审核限制,不能通过合并历史绕过正常十六个有效 origin 上限或原根目录边界。 - -相同有效重试沿用原 note 与 ID,已撤销 ID 不会重新启用;重启与采纳保留最早终止见证的三十日期限。 -origin 失效后仍可查 get/list 历史与 revoke,但历史不代表可用完成证据或输入授权。Python、AC、 -CLI、具名 MCP、REST、Builder 共用五个现有操作,Handoffs Actions 与 JSON 编辑器/结果区可显示 -明确续授权审核,不自动派发同意。跨主机移交、remote 读取者、实际应用/设备 -来源及暂缓的原生/浏览器/真机/二十四小时验收仍列于 `Progress.md`。 - -## 明确移交任务来源的完成证据 - -现有五个移交操作也接受真实非 DAG 来源任务: - -- `review_handoff` 提供 `source_task` 与实际最后证据的 `task_id`。 -- `create_handoff` 再以最上层返回的 `handoff_review` 作为 `review`,并填写非空 `note`。 -- `list_handoffs` 提供 `source_task`;`get_handoff`/`revoke_handoff` 仍使用 `handoff_id`。 - -任务来源与 DAG batch/node 字段互斥,服务依实际保存的 grant 判断存储类别。真实 DAG 祖先仍须走 -原 batch/node 路径,不能借由已移除 `dag_batch` 的只读读取者绕过,也不补造 DAG 节点或 admission。 -一般任务不必虚构提交见证或 idempotency key;实际存在的原请求须固定并在同一 SQLite writer 重验。 - -现有技能操作明确选择 `handoff_id`。`record` 以 `completion_task_id` 采纳独立读取者,建立的 draft -仍须自己的新验证 trial;`accept` 使用完成读取者时,仍保留原 candidate 的真正验证任务。 -`review_execution` 与对应 `accept` 可选实际 `execution_task_id`;最后证据是独立读取者时,再提供 -`completion_task_id`。服务核对原本完整语义动作计划、真实执行 ID 及独立完成条件,不能把读取者 -当执行任务或替代验证 trial。 - -grant 只提供私人有限证据视图,原所有者、来源状态与收据维持原样,一般 get/list/observe/act/ -resume 权限不扩大。发出或采纳时不启动 helper、不重放输入。真实快照、可选原请求、实际 owner/ -reviewer、退役输入与有效历史 origin 均持续核对;新录制的 draft 保留发出与接收 session 上限。 -失效限制须经真实私人完成续授权,不能靠相同 hash 或自填 scope flag 替代;只读采纳也不会续授权 -已发布技能原本的输入权限。 - -来源祖先与后续移交链合计最多十六条真实恢复连接。期限沿用最早终止证据的三十日,改锚定较新的 -读取者不会延长旧祖先。DAG 与任务 grant 的 INSERT 后及相同重试都重验撤销墓碑;来源/请求/角色/ -origin/撤销变动会回滚 grant、draft 或发布。已撤销 ID 不重启,origin 失效后的 get/list/revoke -历史只显示有限 ID/hash,不代表持续有效的完成证据或输入授权。 - -Handoffs 页可明确选原本机 DAG 或原任务来准备 JSON;三个技能 Actions 准备带 grant 占位符的录制、 -发布与执行审核,不自动同意或发布。Python、AC、CLI、具名 REST/MCP 与 Builder 共用相同操作及 -真实 caller。`examples/` 提供 `agent_task_handoff_review.json`、`agent_task_handoff_create.json`、 -`agent_skill_recording_handoff.json`、`agent_skill_completion_handoff.json`、 -`agent_skill_execution_handoff_review.json` 与 `agent_skill_execution_handoff_accept.json`。 - -跨主机移交、remote 读取者、实际应用/设备来源、暂缓的原生与二十四小时验收,以及未解的 -HTTP409/bootstrap 问题仍列于 `Progress.md`。 - -wheel 与源码分发包包含 REST Dashboard 和 Swagger 的 HTML、CSS、JavaScript 资源。 -安装后的套件沿用相同的本机 REST 路由与授权规则;提供静态页面不授予任务或桌面输入权限。 +[MIT](../LICENSE) © JE-Chen. [第三方许可](../Third_Party_License.md). diff --git a/README/README_zh-TW.md b/README/README_zh-TW.md index 9e684a4ee..bab0a7129 100644 --- a/README/README_zh-TW.md +++ b/README/README_zh-TW.md @@ -1,1331 +1,56 @@ # AutoControl -成果移交管理已共用 `manage_agent_transfer(operation, request)`、`AC_agent_transfer`、 -`ac_agent_transfer`、具授權的 `POST /agent/transfer` 與 Script Builder metadata。CLI 使用 -`agent-task transfer --operation review_export --request request.json`。審閱回傳批准 token; -建立須提供該 token、原請求 key 與明確 note。匯出/匯入管理可指定已登記主機; -可攜證據管理也可指定已登記主機,由來源核實私有權限。傳輸頁提供四語 Actions、可編輯 JSON 與服務回覆; -審閱不自動核准,核准範本保留原主機、token 與 key 並留白備註。選項變更或關閉頁面後, -舊回覆不覆寫畫面,已接受的匯入仍由服務持有。遠端核准先保存明確同意,失聯或協調端重啟後以原鍵重送,維持同一授權。 -被動診斷僅列出本機契約,不代表即時授權或遠端/原生能力已驗證。只讀完成證據在建立與取用時重新核對原私有同意,不恢復原輸入權限。 -實作驗證紀錄見 docs/updates/README.md;其餘交付與驗收見 Progress.md。 -examples/agent_transfer_export_review.json、agent_transfer_import_review.json 與 -agent_transfer_evidence_review.json 提供可編輯請求,並各有獨立的 create 範本。 +[English](../README.md) | [繁體中文](README_zh-TW.md) | [简体中文](README_zh-CN.md) -實驗性的來源主機技能操作,可透過既有 `handoff_id` 明確選取可攜授權與完成/執行任務。 -來源在技能交易內重新核對實際同意、接收者與私有證據,候選/發布寫入後再次核對。 -保留原始動作、候選自己的驗證試跑與明確版本批准;新的技能試跑建立服務產生的全新請求 key, -不為舊有未帶 key 的試跑補造紀錄。此流程不將外部動作或政策移交協調端; -技能證據保留來源主機的原動作/試跑/版本;其餘跨主機驗收與交付見 Progress.md。 -選取移交證據的技能操作,全程保留 runtime 擁有權,操作結束後才釋放。 +AutoControl 是用來操作桌面應用程式的 Python 自動化框架。你可以控制滑鼠與鍵盤、擷取畫面,並透過圖片、OCR 或無障礙 API 尋找介面元素。支援 Python、JSON 動作檔、桌面 GUI 與 MCP 用戶端。 -目的端匯入目前仍為實驗功能。明確啟動的服務可透過 runtime 移交控制器與經驗證的 -`/agent/transfer` 接受 `review_import`/`create_import`/`get_import`/`run_import`/ -`cancel_import`/`list_imports`。協調端可透過自己的不透明同意 token 路由這些有限操作; -目的端使用自己的來源登錄與帳號,不轉送協調端 principal/origin 或來源憑證。 -核准意圖在派送前提交;回覆遺失後的精確重試仍對應同一筆匯入。 -啟動時接回已核准且尚未領取的工作;未結算 claim 會轉為待審閱。明確的 `run_import` -以新佇列世代重新核對原收件者、profile、即時 origin 與來源 grant,可重用已驗證私有分塊, -或唯讀核對既有完整目錄與雜湊,不重新下載/發布。續行時新增的 origin 限制仍持續生效。 -已明確排入佇列且未領取的唯讀核對可跨再次重啟;採認前重驗目前位元組、profile 與保留的 origin。 -匯入收據確認完成前,目的端會在最後一次來源回應後重新核對完整檔案清單與內容摘要。 -檔案遭改寫、遺失或增加未列入清單的檔案時,匯入保留 requires_review, -保留使用者修改與原發布成果供審閱。 -目錄身分、位元組或授權變更不能確認發布。取消會使產生者失效;尚未完成收據確認的 -發布保留 requires_review,已確認發布的檔案保留為使用者成果。 -取消或到期的私有分塊帳戶須確認產生者退場才清理;失敗時保留配額,成功重試後才釋放。 -收據維持原本固定期限。 -暫存目錄與預先建立的檔案會在複製位元組前記錄檔案系統身分。產生者退場後, -到期清理可於重啟後重試;遇到置換或無關物件時保留配額待審閱,不遞迴刪除。 -來源維護會清理到期或已撤銷的私有匯出帳戶,包含重啟或授權者移除後;失敗時保留配額。 -來源或目的端清理完成前持續保有 runtime 擁有權;無待清理資料時不取得 runtime 寫入鎖。 -建立/續行回覆會在喚醒新派送前讀取已提交的收據;後續以 get_import 查詢目前進度,避免回覆被新 writer 擋住。 -後續維護會修剪已清理、撤銷且到期的來源中繼資料以回收筆數配額,保留同意/撤銷憑證與其他記錄類別。 -冷啟動維護以唯讀探測發現待處理來源記錄;沒有待處理記錄時不建立移交控制器。 -runtime 最後釋放擁有權時會與控制器建構互斥,並重驗晚建立的控制器是否退場;忙碌時保留擁有權供稍後重試關閉。 -私有快取路徑轉向會在開啟儲存前拒絕;清理失敗時保留配額。 -後續維護會在私有資料確定清理後,回收到期的目的端匯入/派送中繼資料及其已結束佇列紀錄。 -仍在執行、身分被替換或未知狀態的佇列會阻止回收;原同意/撤銷憑證與已發布使用者檔案保留。 -冷啟動維護不啟動監聽端或產生者;待清理帳戶的掃描不受大量未到期歷史紀錄遮蔽。 -可攜證據保留與共用介面已接入;其餘故障交錯與正式交付見 Progress.md。 -來源證據實驗功能已接入 owning runtime 與具名/共用帳戶的本機 transfer HTTP 管理路徑, -提供 review_evidence/create_evidence/get_evidence/revoke_evidence/list_evidence。 -獨立持久授權沿用真實恢復/完成驗證、當前帳戶與原本機 DAG 審核;已登錄 peer 的 evidence -讀取核對實際接收的 key/規格與 DAG 節點,只回傳 ID、雜湊及有限驗證,不授予一般任務讀取或輸入。 -審閱摘要不含 node.request_digest;即時讀取才依精確已審閱原請求補入。 -來源主機技能證據、遠端管理路由與共用介面已接入;其餘故障驗收與交付見 Progress.md。 -協調端 DAG 的實驗採認已接入獨立審閱的遠端恢復授權,固定原來源/key/規格/graph/node 與主機。 -核准與啟動先持久保存暫定狀態,離開本機 writer 後即時查驗來源,再核對原同意及認領,才啟用。 -停止會取消暫定狀態;中斷後只可用同一明確核准請求續接。確認期間保留 runtime 擁有權, -不把獨立 peer 讀取序列化;認領/紀錄及最終採認前後重新驗證。 -授權失效會阻擋後續排程,只對精確已接收的下游任務請求有限暫停;回覆未知或遺失時保留認領並待審閱。 -已完成副作用與無關任務保留;不宣稱已證明原生輸入退休或完成整份故障矩陣。 -舊派送格式升級會保留原核准 origin 與固定期限;多次續行的額外 origin 仍累積生效。 -停止附加的 REST 觀察端不會重派或取消服務持有的匯入,也不釋放 runtime 擁有權;重新連線可讀取同一筆成果。兩主機與獨立程序三主機測試已核對實際位元組及帳號範圍。 -更多重啟/取消交錯、更多暫存故障交錯、完整保留、可攜證據、client/GUI 介面與完整階段檢查 -仍列於 Progress.md;移交收據不授予任務輸入權限,也不能證明任務完成。 +## 開始使用 -來源匯出的遠端審閱/建立/查詢/撤銷已接合。協調端發出自己的不透明審閱 token, -綁定實際本機呼叫者、目前主機/憑證摘要、來源審閱、清單摘要與原 key。批准意圖在轉送前 -耐久提交;回覆遺失或協調端重啟後,相同批准仍取回同一來源成果。改換呼叫者、主機、憑證、 -note/key 或來源回覆摘要即拒絕。待審閱與耐久路由各限128筆;到期只清理本機路由 metadata, -保留同意邊界。關閉 runtime 會清除尚未批准的本機審閱快取,已批准的耐久意圖仍可恢復。 -來源使用自身帳號,本機 principal/origin 不轉送。目的端匯入、可攜完成證據與公開介面均已接入; -其餘驗收與正式交付見 Progress.md。 - -既有遠端 DAG 在固定主機設定及每次保留連線呼叫前後,均讀取實際持久化通訊錄。 -其他程序替換/移除端點或憑證、設定損壞或原本本機呼叫者被撤權時,操作會失效。 -讀取不建立 console,也不隔離通訊錄;既有本機服務委派與封閉遠端路由保持相容。 - -跨主機成果移交依明確審閱與各主機本機授權運作。來源核心可審閱已完成檔案成果,建立不可變 blob, -並核對實際發行者/接收者。來源管理與 peer 唯讀 HTTP 路由已可提供經審閱的清單/分塊。 -Peer 使用接收端本身的 bearer/RBAC 與速率限制,在外部 principal/使用者資料庫查詢前拒絕 -本機 principal/origin header;本機服務 client 僅在管理流程保留實際擁有者委派。 -移交要求在伺服器讀取前限制為1MiB;受限 client 在派送要求與解碼成功/錯誤回覆前核對上限, -不變更一般 HTTP 的既有上限。完整私有授權鏈/生命週期驗收、目的端發布/ -證據採認及共用公開介面已接入;其餘驗收與交付見 Progress.md。移交收據不授予任務輸入權限。 - -來源匯出在開啟選定檔案前,排除實際 runtime/移交資料庫與 sidecar、目前來源擁有者及 -發行者的使用者資料庫、服務連線檔與專屬證據目錄。服務登記實際私有檔案,不保留一般成果的 -同名檔名;manifest 只核對選中的輸出。Peer 讀取與相同要求重試會重新核對目前路徑權限, -不重新雜湊歷史使用者成果,並保留操作期限。DAG 成果沿最多十六層真實恢復鏈核對原始 -提交任務、實際請求及本機 DAG admission,重新授權接納者,並排除其不同位置的帳號資料庫。 -恢復子任務不補造提交列;正常 standalone 不要求 DAG 提交列。私有恢復鏈摘要在審閱、建立、 -相同要求重試與 peer 讀取時重驗;實際私有恢復擁有者/審閱者綁定也納入摘要,其資料庫保持私有。 -來源操作在位元組存取與 grant 寫入邊界配合取消;提交後回覆被取消仍可依固定意圖精確取回。 -成果期限依完成來源 updated+30 天計算,不因重試/重啟刷新,也不改用較早祖先的期限。 -本機唯讀 reader 依目前私有完成授權匯出,舊輸入仍撤銷;自動清理、目的端發布與證據採認已接入。 -其餘提交/撤權交錯驗收與正式交付見 Progress.md。 - -Runtime 透過實際 batch 主機 adapter 保管 TransferPeer;具名傳輸固定端點/憑證,於 HTTP 前後 -重讀持久化通訊錄並核對目前本機呼叫者。來源端使用自身憑證驗證,不接收本機 principal/origin -header。來源私有排除只取得實際通訊錄路徑,不建立/重載 console 或隔離檔案。封閉清單與正規 base64 分塊須符合 -匯出 ID/摘要、每塊最多256KiB及原始期限;URL 路徑前綴同樣套用1MiB移交上限,一般 HTTP -保留既有上限;無效預算(含過大整數)在派送前回報型別化錯誤。兩/三主機 -匯入交付仍待完成。 - -閒置背景 worker 以唯讀預檢辨識空佇列,減少輪詢與任務狀態、完成交易的寫入鎖競爭。 -發現工作後仍須在原有交易內重新核對與認領;保留 claim 世代、過期工作回收與重試上限, -不延長任務或傳輸期限。 - -租約維護會在停止交易內核對實際輸入擁有者與世代。延遲的監看程序不能改寫已退休任務的 -恢復證據,也不能取消新租約;接受的最終停止狀態與取消 token 會先於停止交易發布。 -仍有效的撤權與原有期限持續生效。 - -副作用已確認的瀏覽器任務,可透過既有完成審閱與技能流程讀取原本的 WebRunner context。 -原 helper 先永久結束 SDK 輸入/網路,再釋放輸入 journal/租約;runtime 最多保留 16 個 context, -自分離前預留起最多保留 300 秒,不因分離耗時延長。預覽/建立核對實際 effect task 的即時 SDK view;驗證只借用原 context -讀取最新有界 DOM/欄位值,不重新配置輸入、不 ACK 原生輸入、不傳輸,也不另開瀏覽器或 helper。 -退休切換、能力探測與清理也拒絕巢狀工具與原生輸入。 -同 profile 的不同任務分開保管,context ID 本身不授權。私有完成授權審閱可在原上限內明確續授權 -驗證 scope,原輸入規格不變;已失效輸入 origin 與有限私有保管本身均不授予讀取權限。 -擁有者刪除、目標停用、來源變動、期限或讀取失敗會使 context 失效;只有確認程序結束才釋放 -程序擁有權,清理失敗持續追蹤。重啟不還原頁面,網路結束後的 DOM 不能當作新伺服器資料。 -Python/AC/MCP/REST/CLI/Builder 與 GUI Actions 共用原審閱 request;技能錄製保留原動作, -發布須使用自己的實際新驗證試跑與明確選取的完成證據。範例見 -`examples/agent_browser_retained_completion.py`。冷啟動瀏覽器前綴重建、remote reader、正式部署, -以及暫緩的原生/瀏覽器/真機/24 小時驗收仍待完成。 - -已停止且副作用已確認的任務,可用 `manage_agent_recovery("preview_completion", {"task_id": id})` -審閱獨立驗證任務,再將精確 task_id/snapshot 與審閱說明交給 `create_completion`,最後完成新任務。 -私有原子綁定只選擇永久唯讀 helper,不重播來源動作;須有新鮮獨立完成條件與輸入退休證據。 -skill 計畫須全部確認;動態任務不得含未處理的有限計畫或未知效果。 -可先 observe 再 finish;相同 helper 設定只重新檢查就緒,不替換權限,也不快取就緒結果。 -來源/審閱者權限持續有效,涵蓋清理後、明確重試與重啟。API/AC/MCP/REST/CLI/Builder 及 GUI Actions 共用此流程。 -remote reader、正式部署仍列於 Progress.md;桌面能力仍須另行原生驗證。 - -只有受管任務節點的 DAG,可用 `manage_agent_dag("register", {"definition": graph, -"max_parallel": 4})` 註冊耐久批次,再明確 `run_dag(graph, batch_id=batch["batch_id"])`。 -註冊不操作目標;保存整張圖的拓樸、節點契約、主機設定與並行數,目的端 key/規格標記綁定批次。 -可能派送前先提交 claim,目的端精確規格、完成及輸入釋放證據通過後才放行相依節點。成功、中斷或 -提交回覆遺失後都不能再次 begin;`get/list/inspect` 讓協調紀錄跨重啟保留。API/AC/MCP/REST/ -CLI/Builder 及 DAG Actions 的批次註冊/讀取、選填批次 ID 共用流程。 -停止後以 `review_continuation` 取得唯讀整圖快照及逐節點決策,再把審閱的 `snapshot`、`decisions` -與非空 `note` 放入 `run_dag(graph, batch_id=id, recovery=request)`,核准並使用一次續接機會。 -只能採認獨立完成的原任務或真實 recovery 後繼任務;派送限從未 claim 且目的端未接收的 pending -節點。本機授權可在相等或更窄根目錄內更新,未知 claim 永不重播。DAG Actions 提供停止新派送、 -審閱及明確續接;已接受任務仍依自身生命週期處理。將協調交給已明確啟動的服務,可呼叫 -`manage_agent_dag("run_background", {"batch_id": id, "definition": graph, "max_parallel": 4})`; -明確批准的續接另帶 `approval_id`。DAG Actions 提供兩個背景動作;關閉視圖不停止已接受的服務工作, -`get.background` 提供有限佇列狀態。重啟使舊 attempt 失效並要求審閱,不重播排隊或未知派送。 -原 owner 與提交者的權限持續重新驗證,本機任務綁定所屬 runtime。 -既有 `prune_agent_tasks()` 與每小時維護會回收過期且未使用的註冊及已安全結束的成功批次,預設 30 天。 -未決批次持續保護任務/復原證據與接收 gate;結果新增 `deleted_batches`、`deleted_dag_deliveries`。 -其他佇列與使用者成果不受影響,遠端證據保留仍須明確移交契約。 -caller 協調的受管批次固定來源服務路徑、端點、憑證指紋及世代,本機節點共用同一 client;連線檔 -身分變更就停止後續呼叫並要求明確審閱。服務端批次證據直接讀取所屬 runtime,綁定不快取 bearer -憑證。一般非批次 client 保留動態連線行為;受管批次須有含世代的連線資料。 -本機批次節點在耐久 claim 後使用來源服務的封閉 `local_task` transport,以原 owner 接收精確規格/ -key,並在交易內記錄真正 caller。輸入前更新雙方權限及 attempt;管理員失去跨 owner 管理權也會 -阻止執行。沒有可信接收紀錄的舊請求不補造見證。任務 metadata 提供有限 `local_dag_admission` -稽核資料,已接受輸入仍依既有清理契約處理。 -若復原後繼任務須讓原擁有者讀取,preview/review_authorization 請求加入 -`owner_policy="source_owner"`,明確 create/create_authorized 時另帶回 `ownership.review` 為 -`ownership_review`。後繼任務保留來源擁有者,交易內另記實際審閱者,輸入前持續驗證雙方權限。 -GUI 提供擁有者選擇;省略政策仍由建立者持有,沿用既有讀取隔離。DAG 可用正常復原證據採認獨立完成 -的原 owner 後繼任務;已存在的 caller-owned 子任務不自動變更歸屬或補造此紀錄。 -詳見[續接協定](../docs/source/Zh/doc/ai_agents/agent_dag_batches_doc.rst)。 - -觸發器可明確使用 `manage_agent_trigger("review_authorization", {"trigger_id":"..."})`,再以 -`create_authorized` 提供 `trigger_id`、`snapshot`、`authorization_review`、經審閱的 `spec` 與 `note`。 -新註冊保留完整模板/設定/待處理上限,受原授權、仍有效限制與目前權限交集約束;交易內退休舊綁定, -並啟用未來通知。共用歷史讓已接受事件與未完成任務跨更新、移除及重啟保留,沿用的舊排隊事件不再派送。 -排程從未來時段開始,檔案檢查點保留。API/AC/MCP/REST/CLI/Builder 及 GUI 觸發器選單共用流程; -一般啟用不能取代失效授權,審閱只準備註記留空的請求。 - -已發布技能可用 `manage_agent_skill("review_authorization", {"candidate_id":"..."})`,再明確 -`create_authorized`,提供 `candidate_id`、`snapshot`、`authorization_review`、經審閱的 `spec` 與 -`note`。完整計畫與參數定義固定;保留原根目錄上限及仍有效限制,與目前權限取交集。流程只建立 -同一技能的新草稿及稽核證據,須重新驗證並明確發布下一版,舊版本不變。相同核准去重,過期版本/ -授權內容拒絕。API/AC/MCP/REST/CLI/Builder 與 GUI 技能操作選單共用此流程;trigger 更新使用上方獨立流程。 - -來源授權失效的停止任務,可明確使用 `review_authorization`,再以 `create_authorized` 提供 -`task_id`、`snapshot`、經審閱的 `spec`、`note` 與 `authorization_review`。新任務保留所有仍有效的 -來源限制,將目前權限與原根目錄上限取交集;根目錄只可維持或縮小,其餘權限、模式/模型、預算及 -完成條件固定。核准證據與唯一新任務在同一交易保存;來源及已撤銷的見證不變。既有共用介面均提供 -這兩種操作,GUI Actions 另有授權審閱/建立命令,詳見[恢復指南](../docs/source/Zh/doc/ai_agents/agent_recovery_doc.rst)。 -任務恢復不解除輸入隔離,也不重建應用狀態;技能與 trigger 使用上方獨立更新流程。 - -停止的任務可用 `manage_agent_recovery("preview", {"task_id": "..."})` 審閱來源收據與快照, -不接觸應用程式。有限 skill 提供剩餘動作及逐筆結果;外部 agent/本機模型任務則提供空白目標的 -`review_template`,須由操作人明確填寫剩餘工作目標,不複製舊動作清單。明確 `create` 時提供 -快照、經審閱的規格與註記,建立有來源關聯的新任務,重新觀察並從零收據開始;重複核准回傳同一 -任務。執行模式、模型/端點、範圍、預算及完成條件固定,未知副作用須先人工核對;不移植舊 -capture、索引、座標或已完成歷史。可用 `AC_agent_task_recovery`、MCP/REST、 -`agent-task recovery preview|create request.json`,或「Agent 任務 → Actions → 審閱剩餘工作/ -重新規劃/建立經審閱的新任務」。已移交的來源不能再恢復,須由新任務繼續。 -登入與視窗狀態的恢復須明確宣告,不能推論:繼任任務(或任何任務)可列出 `resume_conditions`,只接受 -`screen`、`browser` 與 `file_*` 條件(收據是歷史,不能證明現況);第一個動作只在新觀察全部通過時 -才被接受,任一不成立或無法判定就轉為 `waiting_user`,不會動作;有任何動作收據後此關卡即結束。 - -Android/iOS 內建受管 profile 仍未提供。內部遠端副作用防護會依實體裝置識別保存動作前/後確認; -本機 helper 結束但動作未確認時,仍保留隔離。恢復須在 writer 退出後取得可信裝置證據,並以 -後續能使舊指令失效的世代證明安全。尚無內建 SDK 證據來源、裝置 profile 或原生驗收; -剩餘接合列於 `Progress.md`。 -內部 Android 傳輸只連明確設定的既有 loopback ADB server,不呼叫 CLI、不管理 daemon、 -不重試或退回舊 shell;shell-v2 的退出證據有封包/輸出上限,但不代表應用完成、實體裝置 -身分或輸入已釋放。 -內部 Android session 會核對指定端點、實體序號、boot 與預設顯示器焦點,並以原子方式固定 -boot。有限輸入提案在命令連線內重驗身分/焦點,限制文字與結果;提案不授權輸入,仍須接合 -輸入視窗、遮擋、鎖定/真人活動與自有 worker。 -Android 檢查後提案會綁定目前的原生輸入視窗/佇列及 keyguard 證據,核對完整觸控路徑、 -外部攔截與遮擋,並在命令連線內重驗摘要。舊 ANR/歷史紀錄不能證明目前狀態;真人活動、 -全域監看器審閱仍須可信來源授權,內建受管裝置執行仍未開放。 -內部 Android 動作協定 v2 區分完整前置拒絕、輸入失敗、輸入後拒絕與輸入返回。 -缺少/錯誤階段或退出碼不符都維持未知;輸入返回不代表遠端輸入已清空或任務完成,也不授權重試。 -內部自有遠端 SDK worker 會核對精確任務/擁有者範圍、重新授權與真人接回;可信主機 factory -建立前先啟動 parent 監看。持久化 begin 並收到 ACK 後才呼叫 SDK,相符裝置/世代的清理證據 -通過後才送 end;缺證據維持隔離。可信裝置控制來源、WDA adapter 與受管 profile 仍待接合。 -命令編譯器以一次帶標籤的擷取核對三個原生焦點欄位,接受六種順序,缺少/重複/空值仍拒絕。 -前後身分與輸入安全檢查、原本動作期限均保留。自有 POSIX 假裝置減少 Git Bash 讀取程序且維持 -原始檔案 bytes;有限階段/耗時診斷不含命令、參數或輸出。 -內部 AndroidRemoteAdapter 已透過逐命令 AndroidCommandLease 接合 checked session 與 worker; -每個動作消耗一次新的身分/輸入路由/安全觀察,SDK 重新編譯有限命令後才透過 ADB 送出一次。 -裝置端防護須在真人接回、取消或到期後阻止舊寫入;沒有預設 provider,標準 ADB 或停止本機 -helper 不能提供這項保證。清理證據還須綁定新的隨機命令 ID、boot 及獨立輸入/佇列狀態。 -可明確配置主機 hierarchy_reader,提供有界、限 app 的語義元素及經審閱的非敏感文字;未配置時 -仍只有身分 metadata。XML 不授予文字權限;編輯/密碼值及受保護子節點持續遮罩,不發布原始 -XML 或私有 freshness hash。公開觀察版本隨來源及動作更新;Android 元素參照須來自目前可操作 -的語義元素。新的畫面讀回可確認已審閱文字出現,缺少/部分/遮罩內容不能證明文字不存在。 -不新增 CLI/SDK 啟動或擷取備援;真實來源、受保護欄位值驗證、Unicode/IME 與受管 profile 仍待交付。 - -受管畫面完成驗證將內建桌面與 WebRunner 預覽視為部分文字證據;檔案目標與等待視窗階段沒有 -語義畫面證據。已知安全文字可確認出現或推翻不存在條件,遮罩與明確隱藏的標籤不可作證。 -組合條件缺少任一必要證據時保持未知,已知矛盾則判定失敗。精確 DOM/欄位值應使用明確的 -瀏覽器完成讀回;未宣告覆蓋旗標的自訂 target 保留既有行為。 - -`lookup_agent_task("鍵", reviewed_spec)` 可選擇由目的地主機正規化規格,與原擁有者提交時保存的 -不可變摘要比對;回覆宣告 `spec_match_contract=1`,並提供一致/不同/無法核對/查無紀錄。 -CLI 可加 `--spec reviewed.json`;AC/MCP/REST/Builder 共用可選物件。DAG 檢視先查鍵,再於 -目的地明確支援契約時核對已審閱的節點規格;舊端維持 `unverified`,本機來源 witness 不送到遠端。 -鍵改指向別的任務會使舊快照失效;比對一致時仍須核對完成報告的種類、數量與通過結果。 -節點比對不等於整張 DAG 拓樸/原批次批准, -`resume_permitted=false` 仍保留明確續接審閱。 - -`inspect_agent_dag(definition, timeout_seconds=30)` 可檢視本機/已登錄遠端主機的既有提交, -不提交、不暫停、不續跑。提供 `AC_agent_dag_inspect`、MCP、REST 動作、CLI -`agent-task inspect-dag reviewed.json`、Builder 與 DAG Actions。最多 100 節點、最長 300 秒; -遠端仍須主機管理權限,不傳送本機身分/資料庫路徑/來源 metadata,不回傳遠端路徑或原始錯誤。 -`recorded_completion` 只描述查回的任務;節點規格可選擇核對,`resume_permitted=false` 仍表示尚未 -授權整張 DAG 續接。查無紀錄不代表拒絕;GUI 在圖形編輯後捨棄舊檢視。 - -提交回覆遺失時,可用 `lookup_agent_task("原去重鍵")`、`AC_agent_task_lookup`、MCP、 -`POST /agent/lookup`、CLI `agent-task lookup 原去重鍵` 或任務視圖 Actions 查詢。只讀取原身分及 -使用者資料庫範圍,不提交、不續跑、不取得輸入控制權;`found=false` 只是當下快照,晚到請求仍 -可能被接收。GUI 不會讓舊查詢回覆覆蓋後來選取的任務/鍵。DAG 檢視亦沿用此查詢;規格綁定及續接審閱仍待完成; -唯讀查詢仍須具任務存取權限。 - -既有 `run_dag`/`AC_run_dag`/MCP `ac_run_dag`、REST/CLI 動作檔、Script Builder 與 DAG -Actions 選單支援受管任務節點:以 `task` 取代 `actions`/`action_file`,內容包含 `spec`、必填的 -`idempotency_key` 與可選的 `wait_seconds`。省略 `host` 使用明確啟動的本機服務;遠端使用管理員 -已登錄的主機。該端須已配置有背景派送的授權 runtime,本功能不部署服務。規格限 skill 或明確 -配置的本機模型模式,工具、目的地主機路徑及完成條件由該端驗證。 -節點只提交一次,等待完成條件通過、持久完成契約及輸入釋放證據後才啟動下游。同一批次恢復 -須保留去重鍵;不自動恢復暫停任務或重播副作用。停止、逾時或通訊/權限失敗時,已知任務 ID -才會提出有時限的暫停;未收到確證仍為未知。失敗結果保留 ID/去重鍵並阻擋相依節點,GUI -表格顯示任務 ID。本機身分、使用者資料庫路徑及來源 witness 不送到遠端。正式多機部署及原生/ -裝置驗收仍分開追蹤。 - -DAG 型別與函式亦可由 `je_auto_control.api`/`je_auto_control.api.core` 匯入。 - -受管 HTTP 暫停/取消/停止全部/關閉服務使用獨立的每 IP 配額,與一般流量同為每分鐘 120 次、 -突發 30 次;狀態查詢不會耗盡停止請求的配額。登入、即時角色、任務歸屬、稽核與有界輸入清理仍須 -通過。共用客戶端也為 DAG 批次/節點暫停保留傳輸容量;`/agent/dag` 的控制標頭僅接受封閉的暫停 -請求,其他帶標記的操作在派送前拒絕。自訂驗證閘門保留自己的契約;這不保證 OS/網路飽和時的優先權。 - -受管任務在確認輸入清理後才發布成功。清理失敗或仍忙碌時保留輸入租約並要求審閱;確認前 -中斷仍需恢復。完成發布採條件式狀態轉換,不覆寫同時到達的取消要求。既有 GUI/API 任務 -結果以 `metadata.input_released` 顯示釋放狀態;新成功紀錄保存 `completion_contract=1`,舊紀錄 -維持零而不自動認證。成果報告依最終狀態更新,供後續 DAG 協調判定。 - -DAG 節點在執行緒池中保留呼叫者授權、取消與指令限制,自訂 runner 亦適用。每個節點執行前 -重新讀取使用者權限;已刪除的使用者會使節點失敗,後續相依節點略過,各操作依更新後的角色 -檢查權限。預設遠端節點在開啟主機通訊錄或動作檔案前要求 `manage_hosts`,避免透過主機憑證 -擴大本機操作權限。管理員及受信任的直接 Python 呼叫仍可遠端派送。受管節點沿用上述完成 -驗證與停止契約;正式多機部署及原生驗收仍待完成。 - -瀏覽器主機目標可透過可選的 `settings.helper_python` 指定已審閱且已安裝套件的 Python -環境(本機絕對直譯器路徑)。明確指定的 helper 使用 `-I`,從該環境載入已安裝套件;虛擬環境 -直譯器的符號連結保留環境身分。任務選項不能指定直譯器。 -主機管理者可使用 `manage_agent_target("probe", {"name":"reviewed-browser"})`、`AC_agent_target`、 -MCP/REST、`agent-task target probe request.json` 或 GUI 主機目標的診斷操作。 -診斷以獨立且有時限的自有 helper,透過 `je_web_runner` 檢查瀏覽器依賴後結束,過程不取得輸入 -擁有權或啟動瀏覽器。結果可顯示 `python_dependencies_ready`;瀏覽器啟動及原生證據仍明確保持 -`not_probed`/`not_recorded`。`last_probe` 僅為記憶體中的具時間診斷快照,不授予任務權限, -也不啟用停用的目標。桌面/裝置的原生診斷仍待完成。 -已準備的隔離環境安裝兩個功能工作樹建置的 wheel;共用環境與正式工作樹保持原狀。正式服務 -設定及實際瀏覽器驗收仍分開追蹤;所有瀏覽器自動化仍統一由 WebRunner(`je_web_runner`)提供。 - -桌面固定技能現在與瀏覽器技能共用工作階段連續性檢查。桌面 scope 或自有 helper 結束後, -沿用舊前綴前必須審閱,不能用歷史紀錄證明暫停後的表單/視窗狀態。未中斷的工作階段可正常 -執行;檔案 adapter 仍以持久化產物處理復原。檢查在替代 helper 啟動前執行,既有續跑/狀態/ -紀錄介面會顯示人工審閱結果。暫存表單/登入/視窗狀態恢復與可審閱的剩餘步驟重建仍待完成; -原生驗收維持暫停。 - -固定瀏覽器技能的已驗證前綴,現在必須保有原本仍存活的瀏覽器/helper 工作階段。 -暫停、清理、helper 中斷或 runtime 重啟後,舊動作紀錄無法證明表單仍保有先前欄位值; -續跑會在啟動替代 helper 或送出下一動作前進入人工審閱。請明確檢視剩餘步驟並建立新任務。 -尚無保留嘗試紀錄的暫停,以及已審閱為 failed/not_applied 的嘗試,允許全新開始。 -外部擁有者仍可重新觀察新工作階段,再規劃授權範圍內的新動作;未中斷的固定技能沿用原 -工作階段。登入及暫存表單狀態的恢復仍是未完成工作。 - -本機 runtime 的使用者及即時根目錄授權轉送,現在必須由明確的本機服務呼叫啟用。 -一般具驗證的 HTTP 請求只帶指定的 Bearer token;runtime client 驗證 loopback 服務目的地與 -路由後,才附上本機使用者/來源儲存庫/witness 資訊。版本化 `je_auto_control.api` 現在提供 -所有已宣告的 `api.core` 名稱,包含受管瀏覽器命令、目標復原及技能;動作型別 stub 也涵蓋 -所有出貨命令。未解析的延後專案型別沿用產生器既有的 `Any` 政策,避免產生無效名稱。 -並行預算讀取改在資料庫獨佔交易內取樣時鐘,避免鎖取得順序不同造成任務誤判逾時;真正的 -時鐘倒退仍會停止任務。GUI/MCP/REST/CLI 共用這些修正;正式工作樹及既有原生/瀏覽器/ -裝置/24 小時驗收暫停維持原狀。 - -受管瀏覽器檔案命令 `browser_link`、`browser_download`、`browser_upload`(對應 `AC_browser_*`) -委派給 WebRunner 傳輸契約版本 1。上/下載授權必須具有明確的主機及任務根目錄;下載讓瀏覽器 -Cookie 保留於自有 SDK/helper,核對完整長度及可選 SHA256,且不覆寫既有檔案;重用必須符合 -指定 SHA256。上傳將最多 4 MiB 的單一一般檔案讀成核對過的不可變快照,驗證可選 SHA256 與 -SDK 中繼資料,不自動提交表單。網路操作仍全部位於 `je_web_runner`。 -瀏覽器 `download_archive` 預覽接受查詢頁 `url`、明確 `allowed_origins`、授權範圍內 `directory`, -以及具有單純 `name`、`url` 或連結 `selector`/可選 `frame` 的 `files`;每檔可用 `page_url` 覆寫 -查詢頁。流程擷取新連結、下載每檔最多 16 MiB,並產生供獨立核對名稱/大小/雜湊的歸檔清單。 -GUI Actions 只草擬檔案目標/流程/上傳範例,不啟動資源;MCP/REST/CLI/Builder/模型工具 -共用命令,連結讀取仍需輸入控制權限。部署與實際瀏覽器驗收仍待完成,既有驗收暫停保持生效。 - -瀏覽器任務可固定完成條件,例如 -`{"kind":"browser","operation":"value","selector":"#field","value":"expected"}`。 -操作為精確的 `text`、`value`、`visible`(布林)或 `url`(不含定位);必須明確授權 -`AC_browser_read` 與任務 origins,完成條件不會增加權限。Finish 由同一個自有 helper 檢查 -目前頁面位於允許的 HTTP(S) origin,再透過受控讀取命令獨立取得 SDK 完整值;既有 receipt、 -有界預覽或模型停止訊號不能代替讀回。空白/不可用/範圍外頁面、被拒讀回或錯誤驗證回覆 -保持未知;比較不符保持失敗。取消、權限撤銷及人工審閱錯誤保留原類型。 -GUI Actions 可草擬不啟動資源的瀏覽器完成範例;API/MCP/REST/CLI finish 共用驗證器。 -SPA URL fragment 會保留,origin 比對僅略去 fragment。實際瀏覽器/應用驗收及已審閱傳輸仍待完成。 - -受管瀏覽器啟動前,必須先確認 WebRunner 的 `ManagedBrowserSession.contract_version == 1`, -通過後才建立 policy 或開啟代理/瀏覽器。缺少、布林、文字、過舊或未知標記會保留可處理的 -就緒錯誤。SDK 來源 `575e5d2` 提供完整 text/value 讀回:最多 8,000 個 UTF-16 code unit, -超限或無效 Unicode 就拒絕,不截短。AutoControl 對瀏覽器參數與流程預覽資料套用相同 Unicode -上限,在副作用前拒絕。跨來源契約透過真正的自有 helper 與替身 Chromium 驗證;部署與實際 -瀏覽器/原生驗收保持分列。 - - -`draft_agent_workflow("batch_form", config)` 與 `transfer` 可設定 `backend: browser`, -並提供明確的 `allowed_origins` 與已審閱 browser target。CSV/XLSX 來源仍受 roots 限制; -瀏覽器草稿只產生 `AC_browser_*` 動作,不退回桌面輸入。填表提供 `url`、CSS `fields`、 -可選 frame/新增資料控制項、送出與確認 selector;每次填入都有獨立的精確 value 讀回。 -可用 `confirmation_column` 從每列取得預期確認文字。轉填提供 `source_url`/`destination_url`, -擷取 text/value、套用白名單轉換、填入並讀回目的欄位,再驗證儲存;送出前拒絕陳舊確認。 -`AC_browser_wait`/`browser_wait` 只輪詢 text/value,也支援稍後才出現的元素;`wait_seconds` -預設 5 秒,受 action budget 限制,逾時才回來的相符結果仍拒絕,不重播填入或點擊。 -Python/core、共用 catalog/模型 schema、MCP、CLI/REST 任務操作、Builder 及 GUI 流程預覽 -使用同一編譯器。瀏覽器讀回可作為獨立技能證據。實際應用驗收與正式上/下載設定仍待完成; -SDK 啟動前須通過完整有界讀回契約版本 1 的檢查。 - -受管瀏覽器 profile(`kind: browser`)統一委派給 WebRunner 的 `je_web_runner` SDK; -開發來源為 `D:\Codes\WebRunner`,整合來源位於其隔離的受管 session 功能分支。 -Profile 必須提供精確的 `settings.allowed_origins`、瀏覽器專用工具,且不能授權桌面 app; -每項任務另須設定非空、較窄的 `options.allowed_origins`,每次啟用均重新核對兩層範圍。 -註冊不啟動資源;helper 環境須明確安裝已審閱的受管 SDK 與 Chromium,缺少時就緒失敗,不自動安裝。 -`AC_browser_navigate`、`AC_browser_click`、`AC_browser_fill`、`AC_browser_select`、`AC_browser_check` -及 `AC_browser_read` 共用 Python/core、executor、MCP 與 Builder 定義。命令只在受管 helper 中 -運作,透過既有 task submit/observe/act 週期驅動。讀取操作為 `text`、`value` 或 `visible`; -WebRunner 拒絕秘密表單欄位。DOM 索引在目前 observation 內解析 selector/frame,再核對新鮮度。 -失敗副作用保持不確定且需對帳;暫停/取消會結束擁有的資源。GUI Actions 可產生瀏覽器目標範例 -供審閱;DOM 選取只編輯動作請求。專用 helper 跨就緒檢查保留同一個全新 session,正常清理先 -取得瀏覽器 ACK,再結束自己的程序樹;符合完成審閱條件的來源則將原本已凍結的 context -移交 runtime 有界保管。瀏覽器任務不取得共用桌面輸入控制權。跨來源受控測試使用真正 SDK、 -替身 Chromium、自有 IPC/loopback;實際瀏覽器/原生驗收、正式傳輸設定及其餘瀏覽器流程種類仍列於 `Progress.md`。 - -MCP 非同步呼叫會保留接受請求時的角色、session、原路徑政策與工具清單;session 或路徑政策 -結束後,延遲分派會被拒絕。非同步無狀態呼叫仍使用固定 profile。外掛工具清單變更會送達所有 -有效 HTTP session 串流;session 啟停只通知擁有者,並避免重複發送。串流註冊與 HTTP 標頭 -共用鎖,避免提早送出的通知破壞 HTTP 回應。 -純 metadata 的 `benchmarks/mcp_discovery.py --repeats 20` 量測工具數、JSON bytes、暖機後的 -程序內交握、搜尋與啟用耗時。Windows/Python 3.14.4 的紀錄中,完整模式初始有 732 個授權工具、 -358,029 bytes;逐步模式為 5 個、2,029 bytes,回應大小減少 99.43%。交握為 58.263/47.439 ms, -搜尋中位數為 16.243/19.718 ms;逐步啟用中位數為 42.486 ms。此本機量測不含冷啟動匯入及原生操作。 -有日期的 JSON 紀錄位於 `docs/benchmarks/`;既有參數政策的涵蓋限制仍列於 `Progress.md`。 - -MCP 可選擇 session 逐步揭露:`je_auto_control_mcp --tool-mode progressive` 初始只提供五個 -探索控制工具;`ac_mcp_tools_enable`/`ac_mcp_tools_disable` 只改變該 session。 -不會更新工具清單的客戶端可使用 `--tool-mode static --tool-profile ac_screen_size,ac_list_windows`; -預設 `full` 保留不分頁的授權工具清單。逐步/固定模式的 cursor 不透明、只能使用一次,並綁定 -快照與呼叫者;工具、角色或清單設定變更,以及 cursor 過期時,須重新執行 `tools/list`。 -啟停只通知擁有者連線;session 結束會回收 cursor 並使尚在執行中的 metadata callback 失效。 -HTTP/嵌入式使用 `MCPServer.configure_tool_disclosure(...)`;主機環境變數為 -`JE_AUTOCONTROL_MCP_DISCLOSURE` 與逗號分隔的 `JE_AUTOCONTROL_MCP_TOOL_PROFILE`。 -`plan_mcp_tool_profile(...)` 及 Diagnostics Actions 可預覽啟動參數,不會啟動服務。 -無狀態協定使用不分頁的初始固定清單,不保留 session 啟用狀態。唯讀限制也涵蓋後續新增的外掛。 -未驗證/共享 token 連線顯示 operator 工具,與既有呼叫上限一致;主機管理工具仍須已驗證身分。 - -MCP 工具探索提供 `search_mcp_tools(query, limit=10)`、`get_mcp_tool_schema(name)`、 -對應 AC/MCP 指令及 Diagnostics → Actions。搜尋回傳有界摘要、分類與所需權限;完整 schema -須指定單一工具查閱。兩種查詢都重新驗證角色,並遵守 registry 的唯讀篩選;MCP 查詢使用該 -server 的即時 registry,包含外掛變更。CLI 可執行 -`je_auto_control_mcp --search-tools document --limit 5` 或 `--tool-schema ac_mcp_tool_search`。 -完整模式仍為預設;各 session 的逐步揭露可依前述設定啟用。 - -Agent 工具呼叫經 `executor.execute_one(name, arguments)` 回傳原始結果,與動作腳本共用 -授權、變數插值、取消及日誌邊界;拒絕私有 executor 參數。受管任務交付進度見 `Progress.md`。 - -輸入控制權會在分派及輸入確認前寫入持久紀錄。服務崩潰後,先手動放開按鍵與滑鼠按鈕,再以主機管理權限呼叫 `recover_agent_target(target, note)` 記錄審閱並恢復目標;任務未知結果仍須另外核對。工作區文件由輸入 helper 之外的程序啟動,指定的聚焦步驟會等待授權應用程式視窗就緒。 - -受管技能將已驗證的語義流程錄製為不可變候選。`manage_agent_skill` 可預覽具型別的參數、執行獨立驗證任務,並在明確審閱該候選的成功證據後發布編號版本。定位器修復會產生須重新驗證的候選;任務固定使用原版本與摘要。AC/MCP/REST/CLI 與 Agent Tasks 的 Actions 選單提供相同操作。 - -原驗證試跑的動作若已全部確認,可明確審閱/建立並完成獨立唯讀驗證任務,再以 -`manage_agent_skill("accept", {...})` 提供原 `task_id` 與可選的 `completion_task_id`。 -發布保留精確候選/試跑摘要與 pin,核對最多十六層真實唯讀復原鏈、即時權限及獨立完成/清理證據。 -原試跑維持停止,動作不重播;Actions 選單可準備待審閱請求。發布紀錄在暫存 reader 證據到期後 -仍保留歷史 ID/摘要;尚未發布的採認仍須有留存證據。 - -停止的原流程也可透過 `manage_agent_skill("record", request)` 明確提供 `completion_task_id`。 -`task_id` 仍指原流程,草稿保留其已確認語義動作,另採認唯讀 reader 的私有獨立完成證據。 -錄製不重播動作、不改來源狀態;來源/證據檢查與草稿寫入共用交易,並重驗即時權限。 -`provenance.completion_review` 在 reader 保留期後只是歷史紀錄,不授予當前權限。 -草稿與新增驗證條件仍須自己的新驗證試跑,不能直接發布;Actions 選單只準備錄製請求。 - -原驗證試跑只執行部分動作時,先呼叫 `manage_agent_skill("review_execution", request)`, -提供 `candidate_id`、原 `task_id` 與另一個最終 `execution_task_id`;再以相同 ID、返回的 -`execution_review`、`expected_version` 及非空 `note` 明確 `accept`。最多十六層真實可執行復原鏈 -必須確認完整原語義計畫;不同的剩餘流程即使成功也不足。比對包含 JSON 型別、capture 值、預期結果 -與 grounding,但不恢復舊 capture 或重建歷史 UI 狀態。各任務保留原限制與獨立批准;當前 caller、 -全部 owner 及實際建立審閱者都須持續有權限。版本、發布及歷史 `publication.execution_review` -共同提交或回滾,寫入後再查證據與權限。原試跑維持停止並保留 `publication.task_id`,不補造子任務 -為 validation trial。可選 `completion_task_id` 必須驗證最終可執行任務的效果,其證據巢狀存於 -execution 審閱紀錄;過期證據不能批准未發布候選。兩個 Actions 範例只準備審閱/接受請求, -`agent_skill_execution_review.json` 與 `agent_skill_execution_accept.json` 可編輯後使用。 - -受管任務保留來源路徑政策:移除根目錄後,後續動作、事件觸發及技能驗證會受阻。MCP 客戶端根目錄依連線階段隔離,來源授權結束後撤銷;主機設定的固定政策則在明確更換前保留。服務停止會取消實際執行中的工作,包含取得輸入前的模型初始化,尚未啟動的派送則持續保存。 - -實驗性的[受管 Agent 任務](../docs/AGENT_TASKS.md)提供擁有者範圍內的提交、觀察、動作、驗證、 -暫停、恢復、取消、控制權世代、持久化回執、WorkQueue 派送與本機 Ollama 推論。 -Python、AC、MCP、REST、CLI 與 Agent 任務面板共用背景服務,明確執行 -`je_auto_control agent-task start` 才啟動;新流程不強制依賴外部服務。 -四條可預覽範本涵蓋下載歸檔、CSV/XLSX 填表、跨應用轉移與工作區準備; -使用 `agent-task draft` 或 Actions 的「預覽工作流程」檢查後提交。 -持久化間隔、Cron、檔案與事件綁定會保留核准範圍,每次觸發重新授權並去重; -提交識別碼避免重試與重啟時建立重複任務。 -提供擁有者範圍內的回執與結果不明對帳,連結執行歷史、journal 及逐筆報告; -服務快取預設保留 30 天,保留使用者輸出與外部 journal。 -證據快取以完整資料庫路徑及持久資料庫身分綁定於 `.agent-evidence-cache/`。 -還原的資料庫與舊版快取保留原歷史參照;下次動作或報告建立新的自有 journal 分段, -不讀取或搬移歷史檔案。任務 metadata 的 `artifact_cache_state` 為 `owned` 或 `historical`。 -保留清理只移除目前資料庫可辨識的自有快取檔;歷史檔案保留,留存的私有根目錄禁止成果匯出。 - -Linux 上的 helper 程序可改由選用的 [owner 服務](../native/owner_service/README.md) 執行: -root guardian 把每個 helper 放進它自己的 cgroup v2 樹,helper 帳號無法離開;關閉 channel 會 -結束整棵樹(含逃離的後代),guardian 重啟後會清理崩潰留下的程序。root 擁有的 -`/etc/je_auto_control/owner_service.json` 綁定檔只讓完全列出的 helper argv 經由服務啟動; -驅動桌面或瀏覽器的 helper 一律以本機程序執行,因為受保護的 helper 以獨立 ID、空環境執行,無法存取顯示; -沒有綁定檔時 helper 仍以本機程序執行,`agent-task status` 在 `helper_containment` 回報模式。 -Python 套件不會建置、安裝或啟動服務,且在審閱後的版本開啟閘門前,建置出的服務拒絕受保護啟動。 - -`agent-task readiness`(`agent_runtime_readiness`、`AC_agent_runtime_readiness`、MCP 工具及 Agent 任務面板的 -Actions 選單)回報桌面輸入與擷取、真人在場來源、Android 與 iOS 控制、瀏覽器和本機模型各自的狀態: -`unsupported`、`missing_dependency`、`unauthorized`、`not_probed`、`not_recorded` 或 `measured`。它只讀環境變數、 -`PATH` 與已安裝套件,不連線裝置、不啟動 helper、不要求權限,所以不會回報 `measured`,每一項的 -`native_evidence` 都是 `not_recorded`;已安裝的工具只算 `not_probed`,不代表可用。 - -部署或回復前須比對來源與成品雜湊,不能只憑相同版本號判斷私有快取相容性。 -不具此私有根目錄保護的舊程式不得沿用新版資料庫/快取。經審閱的回復須使用相符的升級前狀態 -及其原記錄位置,先取得自有輸入退場確證,並從所有舊版任務根目錄排除留存的新版私有檔案; -保留不明 journal,不重播副作用。無法核實時維持相容版本。 - -Windows USB 列舉明確以 UTF-8 輸出及解碼,PowerShell 子程序維持隱藏。 -Python UTF-8 模式開啟或關閉時,Unicode 裝置名稱與診斷均完整保留;列舉仍為唯讀。 -原生呼叫使用專屬 helper,支援取消、逾時、輸入記錄清理與跨資料庫的桌面排他控制。 -Windows 共用桌面的持續來源跨 runtime/任務/helper 共用,監看開始後須重新累積解鎖閒置 60 秒。 -僅支援已確認的作用中本機 console;遠端、shadow 及不明 session 一律拒絕。 -每個 helper 在輸入 ACK 前後即時查核同一主機租約;來源/reader 失效會暫停輸入, -未確認的按住輸入清理仍保持隔離,須明確重試。關閉一個 runtime 不會停止其他 runtime 的來源。 -目標說明只公開粗略 `presence` 狀態與 `native_evidence=not_recorded`,不啟動探測。 -`agent-task stop-all` 停止可見任務。 -其他共用桌面須有可信活動 adapter。原生平台驗收與其餘待辦列在 `Progress.md`。 - -Linux 內部 presence_peer_linux 以不可繼承的 pidfd 保留原始 Unix stream 或 seqpacket 連線者, -查核帳戶、程序建立時間、namespace 與存活狀態,不另依 PID 開啟程序。程序身分不代表桌面或輸入權限。 - -內部 LinuxListener 與 LinuxChannel transport 擁有受保護的 Unix endpoint、socket 與 peer。 -每個有界 JSON 封包須有仍存活的原始 writer 的核心憑證與 pidfd;額外、遺失、負值或截斷的控制資料 -直接拒絕,收到的描述元在交付前釋放。排隊與 I/O 共用同一期限;取消撤銷交付,尚未完成或失敗的 -清理維持未確定。未知檔案系統物件保留不動。路徑權限不能隔離同 UID 的敵對程序,使用者空間的有界 -等待也不保證核心 syscall 的硬即時完成。 - -X11 與 macOS 已有真人活動來源。X11 只計入真實裝置的 XInput2 raw 事件(XTEST 從屬裝置一律排除), -並從 logind 讀 `Active`/`LockedHint`;沒有 logind 或 `XDG_SESSION_ID` 時視為鎖定。macOS 用唯讀的 session -event tap(需要輔助使用權限);只有程序從非 HID 來源狀態送出的事件才算注入,有疑義時讓任務等待而不是接手。 -Wayland 沒有可信來源。Linux 的 presence broker、worker 與 server 已改經此 transport:自有 worker 綁定 -全新的私有 endpoint 並在 bootstrap 回覆中回報,broker 只採用該 endpoint,連線時先核對 listener 即其所列 -程序,再做 presence challenge。macOS 尚無 presence transport;原生驗收前 runtime 仍拒絕非 Windows 共用 -桌面任務;此 transport 不是完整 Linux 應用或原生輸入驗收。 - -[![PyPI](https://img.shields.io/pypi/v/je_auto_control)](https://pypi.org/project/je_auto_control/) -[![Python](https://img.shields.io/pypi/pyversions/je_auto_control)](https://pypi.org/project/je_auto_control/) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../LICENSE) -[![Documentation](https://readthedocs.org/projects/autocontrol/badge/?version=latest)](https://autocontrol.readthedocs.io/en/latest/?badge=latest) - -**AutoControl** 是一套開源、跨平台的 **computer-use 與 GUI 自動化框架**,面向 AI agent、Python 應用程式與自動化測試。它能驅動滑鼠與鍵盤、透過樣板比對、OCR、作業系統無障礙樹或視覺模型找到 UI 目標、錄製與重播流程,並以 JSON 動作檔執行——支援 Windows、macOS、Linux(X11 與 Wayland)、BSD、Android 與 iOS。 - -每項能力都以三種形式提供:**Python API**、可在 JSON 檔/CLI/伺服器使用的 **`AC_*` 動作指令**, -以及 **GUI 分頁**。沒有任何功能只存在於 GUI。 - -**[English](../README.md)** · **[简体中文](README_zh-CN.md)** - ---- - -## 為什麼選擇 AutoControl - -- **一套 API,七個平台。** `wrapper/platform_wrapper.py` 在匯入時挑選後端;同一份腳本在 - Windows、macOS、X11 與 Wayland 上都不需要改寫。 -- **不寫 Python 也能腳本化。** 911 個 `AC_*` 指令涵蓋全部功能,因此一個 JSON 檔能做到函式庫 - 能做的任何事——包含迴圈、分支、try/catch、巨集與變數。 -- **預設無頭執行。** `import je_auto_control` 絕不會載入 Qt。GUI 是選用套件,包在同一個無頭核心之外。 - 公開匯出項目在被存取時才載入來源模組。`__all__` 與 `dir()` 可列出名稱,不必載入全部功能; - 萬用字元匯入會要求所有名稱。尚未解析的名稱不會出現在 `vars(je_auto_control)`。 - X11 的一般套件匯入不開啟顯示連線或輸入裝置,也不啟動鍵盤監聽。 - 桌面操作在呼叫時才取得資源。讀取 `keyboard_keys_table` 或呼叫 - `get_keyboard_keys_table()` 會解析實際伺服器鍵碼,因此需要 X 連線。 -- **四種定位方式。** 樣板比對、OCR、無障礙樹、視覺語言模型——可透過錨點定位器與自癒後備串接組合。 -- **相依基線輕薄。** REST 伺服器、JSON Schema 驗證、JWT、TOTP、WebSocket 框架、ACME 用戶端、 - USB/IP 協定與 Prometheus 指標全部以標準庫實作;較重的相依都是選用。 - - -## AI Agent 與 Computer Use - -**AutoControl 是開源、跨平台的 computer-use 與 GUI 自動化框架。** - -當 AI agent 需要操作真實桌面、原生應用程式、真正的瀏覽器視窗、遠端桌面或行動裝置,而不只是操作瀏覽器 DOM/API 時,使用 AutoControl。 - -### 何時選擇 AutoControl - -- 真實滑鼠與鍵盤輸入 -- 螢幕擷取與座標操作 -- OCR 與原生無障礙樹 -- 影像/樣板比對 -- Vision-Language Model UI 定位 -- Anchor 與 self-healing locator -- 跨平台桌面/行動裝置自動化 -- JSON 動作檔 -- MCP computer use - -建議的 agent loop: - -**observe → identify → act → wait → verify → recover** - -完整的 [AI Agent 指南](../AI.md) 提供 MCP 設定、工具選擇、OpenAI 整合、安全性與 computer-use 關鍵字。 - -### AI-friendly MCP - -```bash -pip install je_auto_control -je_auto_control_mcp -``` - -MCP 提供完整的 `ac_*` 工具,以及 `click`、`type`、`screenshot`、`find_text`、`click_text`、`drag`、`focus_window`、`wait_image` 等短名稱 alias。 - -只做檢查: - -```bash -je_auto_control_mcp --read-only -``` - -只需要 canonical `ac_*` 名稱: - -```bash -JE_AUTOCONTROL_MCP_ALIASES=0 je_auto_control_mcp -``` - -OpenAI agent 請使用 `export_openai_tools(only=[...])` 提供聚焦工具集,不要一次提供整個 AutoControl 命令目錄。 - -### 專案識別 - -**專案:** AutoControl -**Repository:** `Integration-Automation/AutoControlGUI` -**Python package / PyPI:** `je_auto_control` -**MCP command:** `je_auto_control_mcp` - - ---- - - -## 如何選擇自動化層 - -AutoControl 不需要取代所有自動化工具;應該選擇最符合介面的那一層: - -| 需求 | 適合工具 | -|---|---| -| 穩定的瀏覽器 DOM/API 自動化 | Playwright/Selenium | -| 簡單的 Python 滑鼠鍵盤腳本 | PyAutoGUI 或 AutoControl | -| 原生桌面應用程式自動化 | **AutoControl** | -| 無障礙樹 GUI 自動化 | **AutoControl** | -| OCR GUI 自動化 | **AutoControl** | -| 截圖/視覺模型 GUI 定位 | **AutoControl** | -| Self-healing 跨平台 GUI locator | **AutoControl** | -| AI agent 操作真實桌面 | **AutoControl + MCP** | -| 確定性的 JSON GUI workflow | **AutoControl** | - -AutoControl 的差異在於把 **真實電腦輸入 + 語意/視覺定位 + self-healing + agent/MCP 整合** 放在同一個跨平台自動化介面。 - - -## 安裝 - -```bash -pip install je_auto_control # 核心 -pip install je_auto_control[gui] # 加上 PySide6 桌面應用程式 -``` - -需要時才安裝的選用套件: - -| Extra | 啟用的功能 | -|---|---| -| `gui` | PySide6 桌面應用程式(51 個分頁):左側可搜尋的導覽面板(`Ctrl+K`)依分類列出全部功能,分頁在第一次開啟時才建立,**View → Theme** 切換深色/淺色。窄視窗的內容可捲動;關閉視窗時,主題、字級、導覽面板顯示(`Ctrl+B`)與寬度會存入 `~/.je_auto_control/gui.ini`。主題直接使用 Qt,不需要 `qt-material`。 | -| `webrtc` | WebRTC 遠端桌面、USB 直通(`aiortc`、`av`) | -| `signaling` | 獨立的訊令/rendezvous 伺服器(`fastapi`、`uvicorn`) | -| `discovery` | mDNS / Zeroconf 區網主機探索 | -| `pdf` / `office` | PDF 與 Excel/Word/PowerPoint 讀取 | -| `fuzzy` / `locale` | `rapidfuzz` 模糊比對、`babel` 地區解析 | -| `s3` / `audio` | S3 產出物儲存、系統音量控制 | - -以分頁關閉鈕關閉 factory 建立的功能面板時,下一次 Qt event loop 會釋放 widget、訂閱與計時器;重新開啟會建立新面板。**View → Tabs** 與嵌入用的 `hide_tab` 只隱藏並保留狀態。`tab_registry.open/close` 與 `close_tab` 提供明確的生命週期介面。既有的擁有者表單與 Remote Desktop 在生命週期遷移完成前,關閉後仍保留以供重用。 - -**Windows arm64** 裝得起來也跑得起來,少的是上游在那裡發不出來的那些: -`opencv-python` 與 `cryptography` 都沒發 `win_arm64` wheel。所以 `find_image*`、 -`screenshot()`(OpenCV/BGR 那一支——Pillow 截圖仍可用)、秘密金庫、動作檔加密、 -ACME/TLS 與加密錄影會拋出指名缺哪個 wheel 的錯誤,而不是難以追查的失敗。 -滑鼠、鍵盤、螢幕尺寸、視窗管理、無障礙樹、動作執行器、MCP/REST/TCP 伺服器 -與 GUI 都正常——這是實測的,不是推論的。其他平台不受影響。 - -**系統需求:** Python ≥ 3.11。 -Linux 請先安裝建置前置套件: +需要 Python 3.11 以上版本。 ```bash -sudo apt-get install cmake libssl-dev +python -m pip install je_auto_control ``` -OCR、VLM 與 LLM 後端(`pytesseract`、`easyocr`、`paddleocr`、`anthropic`、`openai`) -都是按需載入——只裝你實際會用到的。Tesseract 的部分,`find_tesseract_cmd()` 找出執行檔 -(依序是 `$TESSERACT_CMD`、`PATH`、安裝程式的預設資料夾),`set_tessdata_dir()` 把它指到 -語言資料夾,`ocr_status()`/`ocr_languages()` 在第一次 OCR 之前就說出缺了什麼。 - -**記錄檔:** 函式庫寫到 `~/.je_auto_control/logs/AutoControlGUI.log`,第一筆記錄時 -才建立(只 import 不會寫任何檔),同一個帳號的所有行程共用(附加寫入、每行帶行程 ID, -超過 10 MB 就改名成 `.1`)。要寫到別處就設定 -`JE_AUTOCONTROL_LOG_FILE`,設成 `os.devnull` 則不寫檔。 - ---- - -## 60 秒上手 - -**1. 當成 Python 函式庫** +先讀取螢幕尺寸,這個範例不會送出鍵盤或滑鼠輸入: ```python import je_auto_control as ac -ac.set_mouse_position(500, 300) -ac.click_mouse("mouse_left") -ac.write("Hello World") -ac.hotkey(["ctrl_l", "s"]) - -x, y = ac.locate_image_center("save_button.png", detect_threshold=0.9) -ac.click_text("Submit") # OCR -ac.click_accessibility_element(name="OK") # 無障礙樹 -ac.click_by_description("the green Submit button") # 視覺模型 -ac.screenshot("shot.png", screen_region=[0, 0, 800, 600]) +print(ac.screen_size()) ``` -**2. 當成 JSON 動作檔** — `flow.json` - -```json -[ - ["AC_set_var", {"name": "user", "value": "alice"}], - ["AC_locate_and_click", {"image": "login.png", "mouse_keycode": "mouse_left"}], - ["AC_write", {"write_string": "${user}"}], - ["AC_retry", {"max_attempts": 3, "body": [ - ["AC_wait_text", {"target": "Welcome", "timeout": 10}] - ]}], - ["AC_assert_text", {"text": "Welcome"}], - ["AC_generate_html_report", {"html_name": "report"}] -] -``` +要使用桌面介面,安裝 GUI 套件後啟動: ```bash -je_auto_control run flow.json --var user=bob -je_auto_control run flow.json --dry-run # 只列出步驟,不會真的動滑鼠 -``` - -**3. 當成桌面應用程式** - -```bash -pip install je_auto_control[gui] +python -m pip install "je_auto_control[gui]" python -c "import je_auto_control; je_auto_control.start_autocontrol_gui()" ``` -錄製一段流程、在視覺化 Script Builder 裡編輯,然後存成 CLI 能直接執行的同一種 JSON 格式。 -(`python -m je_auto_control` 是舊式的動作檔執行器——`-e`、`-d`、`-c`、`--execute_str`——不會開 GUI。) - ---- - -## 能力總覽 - -每一列都能無頭執行。「GUI 分頁」是同一功能在桌面應用中的位置;分頁的指令都放在視窗的 -**Actions** 選單裡。 - -| 能力 | Python API | `AC_*` 指令 | GUI 分頁 | -|---|---|---|---| -| 滑鼠 | `click_mouse`(`clicks=2` 就是雙擊)、`set_mouse_position`、`mouse_scroll`、`tween_drag`/`drag_path`(以 `step_delay_s`、`settle_s` 控制節奏) | `AC_click_mouse`、`AC_tween_drag`、`AC_drag_path` | Auto Click | -| 鍵盤 | `write`、`write_secret`、`hotkey`、`type_keyboard`、`keyboard_key_name`(鍵碼 → 標準鍵名;Windows 也收 `ctrl`、`esc`、`enter` 等別名) | `AC_write`、`AC_write_secret`、`AC_hotkey` | Auto Click | -| 螢幕與像素 | `screenshot`、`screen_size`、`get_pixel` | `AC_screenshot` | Screenshot | -| 影像比對 | `locate_image_center`、`locate_and_click` | `AC_locate_and_click` | Image Detect | -| OCR 文字 | `click_text`、`wait_for_text`、`read_text_in_region`、`ocr_status` | `AC_click_text`、`AC_wait_text`、`AC_ocr_status` | OCR Reader | -| 無障礙樹 | `find_accessibility_element`、`click_accessibility_element` | `AC_a11y_find`、`AC_a11y_click` | Accessibility | -| 視覺模型定位 | `locate_by_description`、`click_by_description` | `AC_vlm_locate`、`AC_vlm_click` | VLM | -| 錨點定位 | — | `AC_anchor_click`、`AC_anchor_locate` | — | -| 自癒定位器 | `self_heal_run`、`self_heal_locate`、`self_heal_click` | `AC_self_heal_click` | Self-Healing | -| 自然語言規劃 | `plan_actions`、`run_from_description` | `AC_llm_plan` | LLM Planner | -| Computer-use agent | `AgentLoop`、`run_agent` | `AC_run_agent` | Computer Use | -| 錄製與重播 | `record`、`stop_record` | `AC_record`、`AC_stop_record` | Record | -| JSON 腳本 | `execute_action`、`execute_files` | 全部 911 個指令 | Script、Script Builder | -| 變數與流程控制 | `execute_action_with_vars` | `AC_set_var`、`AC_loop`、`AC_for_each`、`AC_try`、`AC_retry` | Variables | -| 資料驅動執行 | — | `AC_for_each_row`(CSV/JSON/SQLite/Excel) | Data Sources | -| 斷言 | `assert_text`、`assert_image` | `AC_assert_text` 等 21 個 | Assertions | -| 測試套件 | `run_suite` | `AC_run_suite` | Test Suites | -| 排程(間隔 + cron) | `default_scheduler` | — | Scheduler | -| 全域熱鍵 | `default_hotkey_daemon` | — | Hotkeys | -| 事件觸發 | `default_trigger_engine` | `AC_email_trigger_add` | Triggers、Webhooks、Email | -| 視窗管理 *(Windows、macOS、X11)* | `list_windows`、`focus_window` | `AC_focus_window`、`AC_snap_window` | Window Manager | -| 剪貼簿(文字 + 影像) | `get_clipboard`、`set_clipboard`、`get_clipboard_image`、`set_clipboard_image` | `AC_clipboard_get`、`AC_clipboard_set`、`AC_clipboard_get_image`、`AC_clipboard_set_image` | — | -| 遠端桌面 | `RemoteDesktopHost`、`RemoteDesktopViewer` | `AC_start_remote_host`、`AC_remote_connect` | Remote Desktop | -| USB 列舉與直通 | `list_usb_devices`、`enable_usb_passthrough` | `AC_usb_*`(16 個指令) | USB Devices、USB Share | -| 機密保險庫 | `default_secret_manager` | `AC_secret_set` + `${secrets.NAME}` | Secrets | -| 報表(HTML/JSON/XML) | `generate_html_report` | `AC_generate_html_report` | Report | -| 執行歷史 | `HistoryStore`、`manual_history_scope` | `AC_history_list`、`AC_history_capture` | Run History、Script Executor、Script Builder | -| 動作日誌 | `execute_journal_run`、`inspect_journal` | `AC_journal_capture`、`AC_journal_read` | Run History、Script Builder | -| 指標與追蹤 | `default_metric_registry`、`render_metrics_text` | — | — | -| 系統診斷 | `run_diagnostics` | `AC_diagnose` | Diagnostics | -| 測試碼產生 | `generate_code` | — | — | - -自癒定位器會在後備或點擊前原樣傳遞取消。稽核記錄在寫入或回傳記錄前遮蔽本次執行已解析的秘密值;回傳的定位結果保留原值,讀取時不改寫既有紀錄檔。 - -即時 image/VLM 自癒現在共用一次延遲邏輯截圖及實際裁切原點,兩條路徑的 `screen_region` 均為 `[左, 上, 右, 下]`。Schema-v2 記錄增加 run/step 身份、內容與設定版本、frame hash、策略/截圖耗時及實際 backend/model,仍相容舊記錄。未設定驗證的點擊僅記錄已送出或失敗,驗證維持未知。GUI 提供區域輸入與所選記錄證據,Script Builder 保留結構化區域 JSON。舊 `healed`/`heal_rate` 統計定位候選,獨立的操作指標需要明確驗證。 - -實驗性 `self_heal_run(SelfHealRequest(...))` 預設只定位。明確選擇 `operation="click"`,再透過 `VerificationRequest(verifier=...)`(Python bool callback)或 `VerificationRequest(description=...)`(已設定的 VLM)於輸入送出後驗證條件。VLM 驗證使用新擷取的邏輯影像,可能產生 API 費用。`verified` 分為真、假及未知;`found` 與 `issued` 本身不代表操作通過驗證。例外與取消原樣傳遞,不重試點擊。`AC_self_heal_run` 和 MCP `ac_self_heal_run` 接受巢狀 `request`;明確驗證失敗使指令/CLI 失敗,或回傳含結構化結果的 MCP `isError`。GUI **Self-Healing** 提供選填的操作後條件,Script Builder 可編輯 JSON 請求。獨立 VLM 擷取也改用相同的記憶體邏輯原點/Retina 正規化。Framework assertion 會中止定位後備。 - -已擷取的自癒紀錄新增可選的 `journal_path`,搭配 run/step ID。實驗性 `inspect_heal_source(path, run_id, step_id)`、`AC_self_heal_source` 與 MCP `ac_self_heal_source` 只讀取原始步驟經清理的生命週期快照。在 **Self-Healing** 選取紀錄後,使用 **動作 → 檢視原始步驟** 開啟背景讀取器;切換目標時會等待舊讀取停止並保留請求者脈絡,關閉則取消待處理工作;Run History 讀取器也可選填步驟 ID。先篩選 run/step 再套用輸出上限,整份日誌仍會驗證,進度通知前後重查路徑根目錄,取消不回傳部分結果。舊紀錄或未經動作日誌擷取的操作沒有來源連結;查閱不會重播指令。 - -實驗性因果同步提供 `CausalBucket`、`CausalConfigStore`、`SyncActor`、保留衝突的 entry 版本與持久化本機 `SyncOutbox`。獨立且經驗證的 `GET/PUT /config/{user_id}/causal` 第三版協定,在保存重送收據的同一個 CAS 交易內驗證裝置註冊、確認、退休/完整同步 epoch 與刪除回收。回收後保留永久的最小刪除憑證;舊版寫入不能覆蓋已升級帳號。私有 `AC_config_store_get`/`AC_config_store_commit` 與對應 MCP/Builder 命令可讀取及提交帶明確 `_actor` 的因果 JSON;純資料合併/peer 與私有 outbox 命令仍可使用。明確的 `CausalSyncClient` 與 `AC_config_causal_fetch`、`AC_config_causal_commit`、`AC_sync_outbox_flush`(含 MCP/Builder)已提供第三版 HTTP 投遞:結果不明時重送固定請求,只有明確的過期版本才在有界預算內重合併。`CausalReceipt` 在 outbox 原子確認原收據與最新完整快照;命令憑證使用即時的 `options.secret_env` 參照。`CausalSyncClient.control` 與私有 `AC_sync_peer_control`/`ac_sync_peer_control`/Builder Data 命令可持久化註冊、確認、回收、退休與完整重同步。`SyncControlRequest(operation_id=...)` 讓已完成 RPC 的重試保持冪等;完整重同步須明確提供 `discard_pending=True`,收到收據後才原子採用新世代並封存待送舊編輯。本機 `status` 不讀取憑證或網路。`python -m examples.causal_peer_control` 提供暫存 loopback 工作流;明確的本機資產版本可透過 `AssetManifest`、`DirectoryAssetTransport`、`build_asset_manifest`、`sync_assets` 與私有 `AC_sync_asset_manifest`/`AC_sync_assets`(MCP/Builder)操作。全部資產先暫存並通過 SHA-256/大小驗證,再一次發布完整目錄;受損快取拒絕使用,腳本保持未執行。`python -m examples.sync_assets` 只使用暫存目錄。七種實驗性 adapter 已將明確選定的腳本、locator、熱鍵、觸發器、通訊錄、JSON 設定與已保存的原生 GUI 偏好設定保存為持久化因果 profile。`SyncBindings` 將明確指定的秘密與機器值換成具名參照;`materialize_sync_profile` 發布完整且未啟用的原生格式版本。私有 `AC_sync_adapter_snapshot`、`AC_sync_adapter_apply`、`AC_sync_adapter_resolve`、`AC_sync_profile_materialize` 與對應 MCP/Builder 命令提供相同流程。`python -m examples.sync_adapters` 僅使用暫存檔。私有絕對路徑綁定接受高熵目錄名稱,仍拒絕可辨識的憑證格式。原生數值定義會在儲存前以分類錯誤拒絕超出範圍的值,包含超大 JSON 整數。`WorkspaceSettingsSyncAdapter` 僅讀取原生 GUI INI 的主題、字級、導覽顯示/寬度,並發布未啟用的 `workspace.ini`;明確複製為獨立工作檔後,才能交給新 GUI 使用。`python -m examples.sync_workspace` 不匯入 Qt。`SyncWorkspace` 已整合明確來源、持久離線捕捉、因果 HTTP、精確衝突檢視與完整重同步來源基準。私有 `AC_sync_workspace`/`ac_sync_workspace`/Builder Data 共用 status/capture/sync/review/resolve/preferences/materialize 與明確 peer 控制,全部需要 DRIVE;網路憑證使用 `options.secret_env`。`python -m examples.sync_workspace_http` 以兩組暫存來源與 loopback 示範衝突解決、重啟及退休編輯不重播。接收資料保持未啟用。引用資產傳輸見下方;明確的原生工作副本載入見下方,`ConfigSyncClient` 保留時間戳合併。參閱[因果/outbox 指南](../docs/source/Zh/doc/causal_sync/causal_sync_doc.rst)與 `python -m examples.causal_sync`。 - -延遲建立的 **工作區同步** 分頁透過 **Actions** 提供本機狀態/擷取、網路同步與裝置控制、精確因果檢視/解決衝突,以及完整未啟用發布。貼上明確的私人工作區設定,憑證只填環境變數名稱。同步不會自動套用收到的偏好設定。選取 `workspace`、檢視目前版本後,再執行「套用已檢視的 GUI 偏好設定」,才會更新目前視窗的主題、字級及導覽面板。`SyncWorkspace.preferences(observed=change_ids)` 與既有 AC/MCP/Builder 的 `preferences` 操作,僅在已檢視版本完全相符且無衝突時回傳四個標準值;缺少或刪除的值採安全預設。Worker 保留呼叫者 context、重驗 DRIVE 權限,支援取消並在關閉後捨棄舊結果。畫面顯示修訂版、待送/衝突/參照數與最近成功同步版本;開啟分頁不會啟動連線。 - -明確的原生載入使用 `load_sync_profile(directory, target_root, expected_digest=...)` 與 `LoadedSyncProfile`,並提供私有 `AC_sync_profile_load`/`ac_sync_profile_load`/Builder Data。以已發布的 `files` 資料夾及精確檢視的 manifest 摘要建立全新可編輯工作區,先驗證全部 bytes、標準原生檔案及封存 heads 一致,再原子發布。載入的熱鍵及每個觸發器節點都是停用的原生物件;定位器與通訊錄 handle 使用工作副本。型別化資產參照及原生熱鍵/觸發器路徑依工作根目錄解析,腳本字面文字保留原意,秘密維持 placeholder。在「工作區同步」發布後,資料夾/摘要欄位會填入結果;選擇工作副本存放資料夾,再執行「載入已檢視的原生 profile」。其他明確 Actions 可檢查所選原生類別、在 Builder 開啟已載入腳本快照,或套用其偏好快照。每次操作都重驗目前呼叫者與擷取擁有者的權限;開啟腳本後仍須明確執行 Run;Builder 將匯入的命令名稱與位置參數顯示為字面文字。`python -m examples.sync_profile_load` 使用七種暫存來源與真實 PNG,不呼叫網路或裝置。 - -資料夾鏡像改以 SHA-256 內容比對,不再依賴修改時間遞增:只改時間不重送,時間相同或較舊的內容修改仍會送出。FolderSyncEngine 重啟時保留待送與離線修改,逐檔檢查停止要求,並持續擁有尚未結束的傳送工作。傳輸擁有者可在發布檔案後明確呼叫 record_received(path),避免回送收到的內容。原生 GUI 的固定內容收據處理見下文。 - -檔案傳送現在會等待每個 DataChannel callback,將緩衝資料限制在 1 MiB,並將通道失敗回報給呼叫端。可選的 `cancelled` 判斷會停止排隊寫入;宣告的位元組數可偵測來源截短或增長。原生資料夾工作綁定授權、引擎、viewer 與 peer connection,擁有權變更時停止。收件匣下載移至事件迴圈之外,透過每個通道最多 32 筆請求的佇列依序傳送。預設手動模式接受資料不代表遠端發布完成;確認模式見下文。GUI 重連交接見下文。 - -原生檔案接收器現在會在關閉、檔案/控制通道關閉、連線進入終止狀態、更換通道或撤銷檔案權限時清除未完成內容。已關閉的接收器拒絕延遲資料;具體 peer/通道與授權檢查會保護替換後的傳輸,也會拒絕 viewer 在驗證前接收檔案。狀態清理先於使用者 callback,避免舊失敗影響 callback 建立的新連線。檔案/稽核/狀態 callback 保留原始取消及強制中斷物件。清理會嘗試關檔及刪除暫存檔,檔案系統失敗寫入日誌。既有 Remote Desktop 控制自動使用此生命週期;已完成的目標與原有線上格式仍可使用。 - -本機 `FileReceiveReceipt(path, sha256, size)` 現在會在原子發布後固定原始接收內容。`FileTransferReceiver.handle_message(on_receipt=...)` 與原生 host/viewer 的 `set_file_receipt_callback()` 提供收據,不必重讀已發布檔案。`FolderSyncEngine.record_receipt()` 避免回送並保留後續本機修改;既有 `record_received(path)` 則明確快照當前內容。GUI 資料夾開關綁定接收收據的引擎及 viewer,並在存取監看目錄前重新驗證原始授權。相對收件匣/監看路徑綁定建立時的工作目錄,既有路徑通知使用絕對路徑。這些本機收據供下文的原生確認模式使用;GUI 重連交接見下文。 - -原生 `FileTransferSender.send`、viewer 的 `send_file` 與 host 的 `push_file` 現在接受僅限關鍵字的 `require_commit=True`。確認模式會先探測已驗證的原生對端,再讀來源中繼資料/內容;以第二版 begin/end 中繼資料傳送,並在原子發布後核對傳輸 ID、不可預測的結束 nonce、SHA-256 及位元組數。相對來源路徑會在交換前固定。每個檔案都重新確認支援與權限,等待有時限;取消、通道/事件迴圈替換或撤銷權限都保留失敗狀態。GUI 資料夾傳送一律要求此模式,因此只接受但遺失的資料不會推進投遞狀態;不確定的傳送會由同一引擎重試。手動傳送仍預設使用原有線上格式。GUI 資料夾投遞要求兩端都支援確認傳輸;不支援時會在送出檔案內容前失敗。GUI 明確重連/恢復見下文。 - -GUI 重連時會為每個面板保留一份記憶體內的資料夾基準。重新連線後再按開始同步:相同的已驗證 host 指紋、絕對監控路徑與本機使用者,會透過新授權的 sender 接續失敗/離線修改。缺少或更換 host 指紋、路徑或使用者時建立新基準;舊工作仍在執行時拒絕交接,待它退出後才能重試。明確關閉資料夾同步會重設基準;停止/重連 viewer 則保留,關閉應用程式後清除。指紋沿用既有已驗證 host 中繼資料的信任模型,沒有新增密碼學身份保證。SDK 可先停止 FolderSyncEngine,待工作確實退出後匯出 checkpoint(),將不可變的 FolderSyncCheckpoint 傳給路徑/遞迴設定相同且 sender 已明確授權的新引擎。基準包含初始略過檔案與收到的內容,並非遠端確認清單。 - -TCP/WebSocket 剪貼簿傳輸沿用明確的 SDK 呼叫與 GUI 推送剪貼簿按鈕。收到的文字/圖片不會自動傳回或廣播;使用者仍可明確重複傳送相同內容。Viewer/host 在讀到緩衝訊息後,會重新檢查原始連線、驗證及完整控制權限,再套用剪貼簿資料。Viewer 會在編碼前固定原通道,拒絕改送至替換後的連線。GUI 排隊中的傳輸保留具體 viewer 與連線發起使用者,寫入本機剪貼簿、明確讀取及送出前都會重新檢查權限與擁有權。過期或撤銷的工作會被略過或回報權限錯誤;一般 provider/callback 錯誤仍受控,原始取消與強制中斷物件繼續傳播。文字/圖片 JSON 格式及既有 API 不變。Callback 註冊只以弱引用綁定一次原始 viewer,避免斷線 viewer 自己保留自己及 Qt 面板直到循環垃圾回收;實際排隊資料仍保留原始 peer 與權限,直到處理或丟棄。受控本機協定、loopback 與 offscreen 測試替換原生剪貼簿 provider;真機與付費 API 驗收仍暫緩。 - -實驗性引用資產使用 `SyncAssetBlob`、`SyncAssetReference`、`SyncAssetStore` 與 `SyncAssetHTTPClient`。明確的 `SyncBindings.assets` 別名將選定檔案封存為不可變 SHA-256 參照;只改資產也會建立新的因果版本。`SyncWorkspace` 在準備新定義請求前上傳已驗證分塊,支援中斷續傳,並在完整且未啟用的發布前下載引用內容。既有私有 AC/MCP/Builder 工作區/profile 命令共用這些欄位。`asset_cache_path` 選取 client cache;signaling 的 `--asset-store`/`AUTOCONTROL_SYNC_ASSET_STORE` 選取獨立 server 資料庫。具驗證的第一版資產路由使用 256-KiB 分塊、每檔 64 MiB 上限,每帳號預設限制 256 MiB、8,192 塊與 4,096 筆 blob 收據。超過配額會明確失敗;不可變歷史不自動回收。原生輸出路徑相對於 generation 根目錄。`python -m examples.sync_referenced_assets` 經暫存 loopback HTTP 傳送真實 PNG 與腳本,不執行腳本或改目前工作區。 - -實驗性持久化設定使用 `ConfigStore.commit(..., base_revision=..., operation_id=...)` 與第二版 signaling PUT envelope。SQLite 交易讓 bucket 與重送收據在重啟後保留;過期版本或 ID 改配其他內容會衝突。`ConfigSyncClient` 預設條件寫入;舊版盲寫須在 client/server 明確開啟。`--config-store` 選取延後開啟的資料庫。私有 `AC_config_store_get`/`AC_config_store_commit` 與對應 MCP 工具共用 Script Builder 的明確 Data 命令。只儲存資料,不執行腳本或啟用觸發器;因果合併與離線 outbox 另行交付。參閱[持久化設定指南](../docs/source/Zh/doc/config_store/config_store_doc.rst)與 `python -m examples.config_store`。 - -實驗性日誌產碼候選支援 `generate_candidate_from_log(path, run_id=...)`、`AC_generate_candidate_from_log` 與 MCP `ac_generate_candidate_from_log`。它會整合開始/完成快照,保留已記錄的控制來源與重試證據,並將不完整重建標示為已觀察路徑。失敗/未完成呼叫、未知命令及遮罩輸入均列為排除項目,不捏造平行順序。Python/pytest/Robot 產物經靜態、命令及不發送輸入的乾跑檢查。`codegen --from-log run.jsonl --run-id selected` 輸出 JSON 審閱包;`-o review.zip` 或 `write_candidate_archive` 可將程式、動作與來源資訊一起原子匯出。Recording Editor 與 Script Builder 的 **動作 → 審閱日誌候選腳本** 提供程式/差異/來源/警告;Builder 匯入為獨立操作,拒絕覆蓋審閱期間的編輯變更。產生與匯入均不執行候選。參閱[候選指南](../docs/source/Zh/doc/journal_candidates/journal_candidates_doc.rst)與 `python -m examples.journal_candidates`。 - -實驗性候選樣板版本提供 `create_template_candidate`、`preview_template_candidate`、`verify_template_candidate`、`accept_template_candidate`、`revert_template_candidate`,以及對應 `AC_template_candidate_*`/`ac_template_candidate_*` 操作。新的不可變 JSON 版本包保存原始位元組及依目標 PNG/JPEG/BMP 格式編碼的候選;預覽回傳有界縮圖。驗證在本機資料集比較兩個固定版本;接受須有已標註命中、期望 miss、全部已標註案例正確,並提供已預覽版本的 SHA-256。接受時重驗資料集,只原子替換仍符合的原始內容;回復精確還原原始位元組,拒絕覆蓋後續修改。未知樣本與原生操作結果分開呈現。驗證使用記錄的門檻;啟用影像不修改腳本門檻。**Self-Healing → 候選樣板** 提供五個動作、背景工作、取消與 JSON 證據。執行 `python -m examples.template_candidates` 可跑只使用暫存檔的範例。 - -實驗性固定影像比較支援 `evaluate_locators`、`evaluate_healing_manifest`、`AC_self_heal_evaluate`、MCP `ac_self_heal_evaluate` 與 **Self-Healing → 版本比較**。報告分別呈現已標註正確率、誤判、未知與已驗證恢復,包含 p50/p95 及來源,可由 `write_healing_report` 或 GUI 動作匯出 JSON/HTML。本機資料集入口不會截圖、點擊或自行選擇網路 backend。參閱[資料集、統計母體與限制](../benchmarks/self_healing/README.md)。 - -除了這張表,`utils/` 底下還有 311 個無頭套件,涵蓋斷言、韌性、資料品質、i18n 稽核、遮蔽、 -治理、可觀測性等等。完整的逐模組地圖在 **[architecture_explore.md](../architecture_explore.md)**。 - ---- - -實驗性的結構化日誌已從 `je_auto_control` 匯出(也可透過 `utils.action_journal` 使用):`journal_scope` 記錄現有 executor 呼叫,`execute_action_with_journal` 隔離一次執行。本機 loop/parallel/DAG 步驟保留 parent ID,並區分失敗、取消與 dry-run。既有 history 擁有者會自動連結明確擷取,包含本機 parallel/DAG worker 開啟的 journal;`HistoryStore.journals_for_run` 可查詢非擁有式連結,清理 history 不會刪除日誌檔。CLI 支援 `run script.json --journal run.jsonl [--journal-run-id ID]` 與 `journal run.jsonl [--run-id ID] [--limit 100]`。查閱會按附加順序顯示遮罩後的生命週期快照,預設最多 100 筆,上限 10,000 筆。`AC_journal_capture` 接受具名參數,在擁有者 executor 上執行巢狀 `body`,保留原變數範圍;`AC_journal_read` 與 CLI、公開的 `inspect_journal` 共用遮罩後的有界查閱。兩個指令皆可在 Script Builder 編輯。擷取會在 history 連結、開檔及動作執行前拒絕含有當次執行已知秘密的識別碼或目的地。MCP 的 `ac_journal_capture` 與 `ac_journal_read` 提供結構化結果、進度與合作式取消。擷取的日誌根目錄限制與 observer 會保留至巢狀擷取及本機 workers;查閱可在逐筆驗證時取消。Python 可透過 `JournalRunOptions` 與 `execute_journal_run` 使用相同控制。 - -手動執行可透過 `manual_history_scope`、`AC_history_capture`、CLI 的 `run --history [--history-db PATH]`,或 Script Executor/Script Builder 的 **記錄至執行歷史** 選用紀錄。GUI 的選填日誌路徑也能獨立使用;GUI/CLI 保留原本的結果 JSON 與變數範圍,指令則回傳 `history_id`、`record`、`failed_actions`。既有與巢狀擷取都會連結到新的手動歷史列。CLI 預覽以 `cli.preview` 標示,一般執行使用 `cli.run`。 - -Run History 提供唯讀日誌檢視。使用 **操作 → 使用所選執行的日誌** 選擇來源連結,或用 **選擇日誌** 指定外部檔案;設定執行 ID 與快照上限後,使用 **讀取日誌**。起始/完成快照保持分離,選取後會顯示完整的遮罩資料。**取消讀取日誌** 與關閉檢視會在逐筆邊界提出取消要求;檔案解析在背景 worker 執行,單純選取連結不會開檔。 - -`${secrets.NAME}` 解析後的值會在 executor 執行期間的應用程式診斷中遮罩,包含巢狀動作及本機 parallel/DAG。CLI/REST/MCP 請求與排程、trigger、hotkey、email 執行會將遮罩保留到錯誤處理及 audit/history 寫入完成;報表紀錄保存遮罩後的快照。DAG 會將擁有者的遮罩保留到 node 診斷完成,包含獨立呼叫與自訂 local runner。watchdog、observer 與 callback executor 會將遮罩保留到最後的錯誤處理;獨立規則彼此隔離。CLI stderr 會遮罩,API 結果、拋出的例外與 CLI 結果資料保留原始值。遮罩於擁有者的請求或執行結束時清除。中止的 history 記為 `error`,journal 步驟維持 `cancelled`,不再擷取錯誤截圖。取消會穿過非嚴格執行、復原/重試、回呼與本機 worker;history 結算失敗也不會取代原始硬中止訊號。 - -## 命令列介面 - -每次 `je_auto_control run`(包括 `--dry-run` 與未帶 `--var`)使用獨立變數範圍。頂層 `run_from_description` 與 `StateMachine.run()` 也會隔離變數,同一次執行內的動作與狀態仍可共享;巢狀呼叫沿用已有的執行範圍。自行建立的 `Executor()` 保留自己的變數。 - -```bash -je_auto_control run script.json [--var name=value] [--dry-run] [--allow-package NAME] -je_auto_control validate script.json # 別名:lint -je_auto_control fmt script.json [--check] -je_auto_control list-commands [--filter mouse] [--json] -je_auto_control record out.json [--duration 5] -je_auto_control codegen script.json --target pytest -o test_flow.py -je_auto_control failure-bundle failure.zip --error "login timed out" -je_auto_control list-jobs -je_auto_control start-server --port 9938 # TCP socket 伺服器 -je_auto_control start-rest --port 9939 # REST API -je_auto_control version -``` - -`--var name=value` 會盡量以 JSON 解析(`count=10` 會變成整數),否則視為字串。 -`run` 只要有任何動作失敗就以 1 結束(仍會跑完整份腳本),CI 步驟會跟著失敗。舊版 `python -m je_auto_control -e file.json` 進入點仍然可用,它的 `-e`、`-d` 與 `--execute_str` 旗標也同樣在有動作失敗時以 1 結束。由 [TestPioneer](https://github.com/Integration-Automation/TestPioneer) 啟動時(它會設定 `TEST_PIONEER_ARTIFACT_DIR`),以相對名稱要求的 HTML、JSON、XML 報告會寫到該目錄底下。 - ---- - -## 伺服器與整合 - -| 介面 | 啟動方式 | 說明 | -|---|---|---| -| **MCP 伺服器** | `je_auto_control_mcp`(stdio)或 `AC_start_mcp_http_server` | 820 個工具,供 Claude Desktop/Claude Code/自訂 tool loop 使用:完整的 `ac_*` 工具介面,以及常用 GUI 操作的短名稱 alias。除了以 `initialize` 握手的各版協定,也支援無狀態的 MCP 2026-07-28。Bearer 驗證、TLS、稽核記錄、限流、外掛熱重載、CI 假後端。 | -| **REST API** | `je_auto_control start-rest` | Bearer token、逐 IP 限流與鎖定、SQLite 稽核 hook、`/metrics`、`/openapi.json`、`/docs` Swagger UI、`/dashboard`。 | -| **TCP socket 伺服器** | `je_auto_control start-server` | 以換行分隔的 JSON 動作清單。預設綁 `127.0.0.1`。 | -| **pytest 外掛** | 安裝後自動生效 | 提供 fixture 與供 pytest-bdd/behave 使用的 Gherkin step library。 | -| **語言伺服器** | `python -m autocontrol_lsp.server` | 為 `AC_*` 動作 JSON 提供補全與診斷,指令清單直接取自執行期的指令表。 | -| **遠端桌面** | `RemoteDesktopHost` 或 GUI | TCP、WebSocket 或 WebRTC;TOTP、信任清單、TURN 設定、檔案/剪貼簿/音訊同步。 | - -除非明確指定,所有伺服器都綁在 `127.0.0.1`。 - -MCP 視窗狀態工具 `ac_window_minimize`、`ac_window_maximize` 與 `ac_window_restore` 在後端接受要求時回傳視窗 handle,遭拒時回覆 `isError: true`(包括 handle 失效或啟用請求被拒)。Win32 原始 `ShowWindow` 的先前可見性由後端正規化處理。 - -**套件閘門。** `AC_add_package_to_executor` 與 `AC_add_package_to_callback_executor` 會匯入 Python 套件並把成員註冊成命令,所以從上面任何一個入口送來的動作清單都可能載入 `os` 或 `subprocess`。沒有被放行的套件不會載入:不在允許清單上的套件在匯入前就被拒絕,該動作以 `AutoControlExecuteActionException` 失敗。放行套件(含子模組)的方式:在 Python 裡呼叫 `executor.allow_packages("name", …)`;對所有入口——兩個 CLI、socket/REST/MCP 伺服器與排程器——設定環境變數 `JE_AUTOCONTROL_ALLOWED_PACKAGES`(以逗號分隔的名稱,行程啟動時讀取);或只對一次 CLI 執行使用 `je_auto_control run script.json --allow-package NAME`(可重複)。`executor.set_allow_arbitrary_packages(True)` 會對所有套件打開閘門,也就是先前版本的預設行為(當時會發 `DeprecationWarning`)。這些都不是 `AC_*` 命令,所以動作清單不能自己打開閘門。 - -**選用的強化設定。** 下列各項在設定之前都是關閉的,沒設定的伺服器行為與先前相同。`JE_AUTOCONTROL_RBAC_USERS=<使用者檔>` 讓 REST API 與 MCP HTTP 傳輸把 bearer token 對到使用者,並依角色(viewer/operator/admin)授權每一個路由、工具與特權 `AC_*` 命令;此時共用 token 會被拒絕。`JE_AUTOCONTROL_MCP_PATH_ROOTS`(以作業系統的路徑分隔字元分開的目錄)把每一個屬於檔案路徑的 MCP 工具參數限制在這些目錄裡,`JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT=1` 再加上 client 的 `roots/list`,`JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` 限制 `ac_resolve_ref` 可以讀哪些 `env://` 名稱。`JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` 讓端點只能驗證 Ed25519 簽章的動作檔而不能簽章(`create_signing_keypair`;私鑰留在簽章的機器上)。遠端桌面的 viewer 只把 host 推來的檔案寫在 `~/Downloads/AutoControl` 底下(`JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR`);這一項預設就是開的。 - -REST GUI 在使用者存放檔啟用時顯示 RBAC 模式並停用共用 token 欄位。`rest_api_registry.status()` 提供 `rbac_enabled`,該模式的 `token` 為 `null`;請使用個別使用者 token。只實作 `check()` 的自製 REST gate 仍可用於共用 token 模式;RBAC 要求已驗證的使用者 context,會拒絕沒有身分的成功結果。 - -RBAC viewer 不會取得列管的敏感讀取工具,即使 MCP `readOnlyHint` 為 true:剪貼簿/歷史、本機文件/資料/SQL 與 dotenv 讀取、參照解析、認證資料產生、持久存放區讀取、對外檢查、麥克風擷取與外部 VLM 請求都需要 operator/admin。斷言容器的 spec 也可能讀取這些資源,因此同樣需要 operator。螢幕觀察與純輸入解析維持既有分類。`ac_realize_item`、`ac_idempotency_begin` 與 `ac_rate_limit` 會改變狀態,已從 `--read-only` 模式排除。 - -間隔/cron 排程、觸發器、熱鍵、watchdog 規則、webhook、e-mail 觸發器與 observer 回呼會保留註冊者身分。每次觸發重新檢查來源使用者檔與角色;已刪除的使用者、無法使用的來源檔與 viewer 不能執行背景工作。啟動 daemon 不會改變既有工作的擁有者。擁有者資訊不保存 RBAC bearer token;未帶 `store_path` 的明確 Python `AuthorizationContext` 保留角色快照,未在 RBAC 下註冊的工作會清除 worker 原有身分。observer/watchdog 回呼使用獨立變數範圍,watchdog 動作失敗不會算成成功排除彈窗。巢狀回呼會保留呼叫端的失敗計數;webhook 擁有者被撤銷權限時回應 HTTP 403 與 `fired: false`。 - -### 遠端桌面的線路協定 - -TCP host 在送出 `AUTH_FAIL` 前就釋放認證失敗的 client 名額。Viewer 即使因錯誤 token、錯誤握手訊息或拒絕核准而失敗,也能立即重試,不必等 socket 清理或日誌完成;待處理握手仍有獨立的資源上限。 - -把主機開出去之前值得先知道,而且這段在其他文件裡都沒有寫。預設傳輸是**裸 TCP -上的長度前綴分幀**(不需要額外相依),連線一開始就是 **HMAC-SHA256 的 -challenge/response 握手**:驗證沒過的觀看端在拿到任何一張畫面之前就會被斷掉。 -JPEG 影格依設定的 FPS 與品質編碼,再透過一個共用的**最新影格槽**發給已驗證的 -觀看端——所以慢的觀看端是**掉影格**,不會把其他人一起卡住。觀看端送來的輸入是 -JSON,會先比對**動作允許清單**才交給既有的輸入包裝層執行,觀看端無法自己發明 -新的操作。 - -```python -# 讓別人連進來——開一個主機,把 token 與 port 給對方 -from je_auto_control import RemoteDesktopHost -host = RemoteDesktopHost(token="hunter2", bind="127.0.0.1", - port=0, fps=10, quality=70) -host.start() -print("listening on", host.port, "viewers:", host.connected_clients) -``` - -```python -# 控制另一台機器——連上去並送輸入 -from je_auto_control import RemoteDesktopViewer -viewer = RemoteDesktopViewer(host="10.0.0.5", port=51234, token="hunter2", - on_frame=lambda jpeg: ...) -viewer.connect() -viewer.send_input({"action": "mouse_move", "x": 100, "y": 200}) -viewer.disconnect() -``` - -也可以用 IP 允許清單(CIDR 網段或個別位址)限制誰連得進來,清單外的對端在握手 -階段就會被拒絕: - -```python -RemoteDesktopHost(token="tok", ip_allowlist=["10.0.0.0/8", "192.168.1.100"]) -``` - ---- - -## 平台支援 - -| 平台 | 後端 | 輸入 | 螢幕擷取 | 錄製 | 視窗管理 | -|---|---|:---:|:---:|:---:|:---:| -| Windows 10 / 11 | Win32 ctypes(可選 Interception 驅動) | ✅ | ✅ | ✅ | ✅ | -| macOS 10.15+ | pyobjc / Quartz | ✅ | ✅ | ✅¹ | ✅ | -| Linux X11 | python-Xlib(可選 `uinput`) | ✅ | ✅ | ✅ | ✅ | -| Linux Wayland | 經桌面 portal 的 libei,或 ydotool/wtype + 擷取工具 | ✅ | ✅ | ❌ | ❌ | -| FreeBSD/OpenBSD/NetBSD | python-Xlib,與 Linux 同一套 X11 後端 | ✅² | ⚠️² | ✅² | ✅² | -| Android | adb + uiautomator2 | ✅ | ✅ | — | — | -| iOS | WebDriverAgent / facebook-wda | ✅ | ✅ | — | — | - -¹ macOS 的錄製走 Quartz event tap,需要**輔助使用**權限 -(系統設定 → 隱私權與安全性 → 輔助使用)。沒有授權時會直接拋出並指名 -缺的是哪個權限,而不是安靜地錄到一個空的 session。 - -² BSD 直接跑同一套 X11 後端——同一個 X server、同一個 `python-Xlib`,而輸入、 -錄製與視窗管理就只相依這一個套件。`freebsd` CI job 在真的 FreeBSD 14 上驅動真的 -輸入,再從 X server 讀回來;OpenBSD 與 NetBSD 走同一條程式路徑,只是沒有 CI -runner。唯一的例外是螢幕擷取,而卡的是打包不是平台:它走 Pillow/mss 與 OpenCV, -而 `opencv-python`、`pillow`、`cryptography` 都沒有發 FreeBSD wheel。從 ports -建起來之後,擷取、影像比對、OCR 與動作加密也都能用——`import je_auto_control` -本身已經不需要它們任何一個。 - -Wayland 的按鍵、按鈕與指標輸入在 `auto` 模式下,僅於選用原生後端缺席時改用 CLI。 -portal 請求開始後,拒絕、逾時、握手失敗、裝置暫停或權限撤銷都會停止輸入, -不會自動切換提供者;重複呼叫保留不含原生資源的失敗狀態,不重開同意對話框。 -`JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND=libei` 強制原生輸入,`=cli` 明確選擇 CLI。 -解決權限問題後,可明確呼叫 `je_auto_control.linux_wayland.libei.reset_default_backend()` -以允許重新請求。原生組合鍵中斷時會在同一後端嘗試釋放所有已按下的按鍵,並保留原始取消。 -此行為不改變明確的 wtype 文字輸入路徑或螢幕擷取選擇。 - -`ydotool` 退路需要 -**ydotool 1.0 以上**。AutoControl 送的每一個參數都是那一版才有的;0.1.x -(Debian bookworm 與目前所有 Ubuntu 仍以這個名字提供,Debian trixie 則根本沒有) -對同一批參數回傳 0 卻不送出任何事件。AutoControl 會偵測並直接拒絕, -而不是為根本沒送出的輸入回報成功。Arch、Fedora 與 Debian unstable 提供的是 1.0。 - -這條退路要能**準確定位**,還有一個前提:合成器的指標加速度必須是關的。 -`ydotool mousemove --absolute` 並不送任何絕對事件——它先把游標推到合成器夾取的 -那個角落,再送相對位移,所以這段位移會被合成器加速。對真的 wlroots session 量到的是: -libinput 的預設 profile 讓游標走的距離正好是要求的兩倍。ydotool 自己的 `--help` -也是這樣寫的;AutoControl 每個行程會記一次警告,而不是安靜地把點擊放到錯的地方。 -請對 ydotoold 的裝置關掉加速度(sway:`input type:pointer accel_profile flat` -加上 `pointer_accel 0`),或是裝上 `liboeffis`,改走協定層本來就是絕對座標的 libei。 - -倍率是合成器自己的設定,用戶端讀不回來,所以只有你知道它關了沒有: -`JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL=flat` 表示已經關掉,移動就不再出聲; -`=strict` 則寧可拒絕這次移動,也不讓點擊落在別的地方;不設定就維持 -「警告一次後照樣移動」的預設。 - -Wayland 的螢幕擷取需要合成器對應的工具,因為沒有單一工具能涵蓋全部:wlroots 系 -(sway、Hyprland、river)用 `grim`,GNOME 用 `gnome-screenshot`,KDE 用 `spectacle`。 -裝好其中一個之後,所有擷取路徑——截圖、影像與錨點定位、OCR、螢幕錄影、遠端桌面——都會 -經由它。三個都沒裝時,內建 D-Bus client 會透過 session bus 嘗試 `xdg-desktop-portal`,第一次可能會跳 -同意對話框。再不行,擷取會帶著安裝提示明確失敗,而不是回傳空白的 XWayland root; -`je_auto_control.api.run_diagnostics()`(以及 GUI 的 Diagnostics 分頁)的 `screen_capture` -檢查會回報目前使用哪一層。 - -原生 Wayland 指標座標在原始座標與版面原點換算後仍不屬於任何授權 EIS 區域時, -會以 `state="failed"` 的 `LibeiUnavailable` 拒絕,停止自動 CLI 備援, -不送出移動、frame 或後續點擊。有效座標、未提供區域的裝置、同一 sender 的後續有效請求, -以及明確選擇 CLI 的既有行為維持不變。 - -**輸入/擷取能力**提供 `je_auto_control.api`(亦由套件根目錄匯出)的 -`BackendContext`、`CapabilityStatus`、`CapabilitySnapshot` 與 `probe_capabilities`。 -呼叫 `probe_capabilities(BackendContext.current()).to_dict()`、無參數的 -`AC_probe_capabilities`/唯讀 `ac_probe_capabilities`,或選擇 -**Diagnostics → Actions → 檢視輸入與擷取能力**;Builder 提供相同無參數指令。 -`python -m examples.capabilities` 顯示本機前置條件與確定性的 XWayland 範圍範例,不操作桌面。 - -輸入項描述按鍵/指標事件;既有 wtype 文字路徑獨立。探測只讀環境、PATH 與不等待鎖的既有原生狀態, -不載入選用原生函式庫、不連線、不讀取事件、不擷取或要求授權。找到工具或 bus 位址只代表 -`unverified`,不等於可用。快取 libei 須完成握手,且鍵盤、絕對指標、按鈕與滾輪事件種類都在運作才回報可用; -部分授權維持未驗證,事件種類暫停或必要裝置移除則回報暫停/撤銷。八種狀態為 `available`、`unverified`、`needs_permission`、 -`needs_dependency`、`unsupported`、`paused`、`revoked`、`failed`。 -`available` 僅是最近的本機觀測,可能過時;實際操作仍重驗權限。XWayland 一律 -`desktop_wide=False`,無法涵蓋原生 Wayland 視窗;其他範圍旗標仍受授權區域限制,不代表已驗證每個螢幕。 - -Context 會複製環境/工具資料,可由擁有者提供無原生物件的輸入/擷取觀測,但不授予權限。 -預設本機結果不含環境值、命令參數、執行檔路徑或原生錯誤文字;AC/MCP 不接受外部提供觀測。 -明確選擇 CLI 與觀測到選用原生依賴缺失後的自動備援分開;拒絕、暫停、撤銷與失敗不表示改走 CLI。 -擷取工具/portal 選擇獨立診斷,重繪與切換語系只使用既有快照。原生 portal 恢復、compositor 重啟、 -擷取結果與 context 的接合,以及原生 session 的重試/取消/停止控制仍列於 `Progress.md`。 - -GUI 工作基礎提供 `gui.task_controller.TaskController`: -`submit(work, owner=widget)` 回傳呼叫者持有的 `TaskHandle`,透過 -`TaskOutcome`/`TaskProgress` 傳遞終態與進度。工作取得不依賴 Qt 的 -`CancellationToken`,提供 checkpoint、有界且可被取消喚醒的等待與進度回報。 -提交時捕捉 context,執行前重讀 store 使用者;工作須持有資料、不引用 widget,並驗證自身操作所需的 capability。 -既有 `DeferredAuthorization.scope()` 維持輸入權限要求,`context_scope()` 僅更新與綁定身分。 - -擁有者、handle 或 controller 銷毀時會要求協作式停止並丟棄延遲結果;每項工作有獨立 ID/token, -回呼在 GUI 執行緒執行。不強制中斷不合作的呼叫,也不把已成功提交的結果改標為取消。 -錯誤與進度使用捕捉的秘密遮罩 scope,終態不保留例外 traceback;執行緒啟動失敗會回復兩層登記並保留原失敗。 -Diagnostics 已接入此共用控制器;其餘面板/backend 遷移與原生 session 操作仍列於 `Progress.md`。 - -主動 **Diagnostics → Actions → 執行診斷** 以共用控制器在 GUI 執行緒外執行。 -**停止診斷** 要求協作式停止;四語狀態區分執行中、清理中、已取消與失敗,並顯示已完成檢查數。 -重複執行不另開工作,關閉後丟棄延遲進度/結果,明確重試會建立新的擁有者工作。 -GUI 以不保留例外 traceback 的 typed outcome 呈現取消;核心/SDK/CLI 與 MCP handler -維持原始直接/包裝取消物件。普通檢查錯誤仍列入報告並繼續其餘項目。 - -兩個 SDK namespace 匯出 `CancellationToken`、`TaskProgress`、`cancellation_scope`。 -使用 `with cancellation_scope(token): report = run_diagnostics()`,擁有者可由另一執行緒呼叫 -`token.cancel()`;既有無參數診斷簽章不變。Scope 不授予權限,`cancellation_scope(None)` -只在有時限的自有資源清理期間暫停取消。`AC_diagnose` 與新增的唯讀 `ac_diagnose` 共用報告; -MCP 不接受參數,使用請求取消/進度,與明確 GUI 操作同樣需要 `read_screen`,拒絕外部 token/授權資料。 -這些是主動檢查,擷取可能要求同意;`ac_probe_capabilities` 維持獨立的被動選項。 - -Scoped Wayland D-Bus 的連線/讀取/部分寫入,以至多 0.1 秒的區間輪詢,維持原本總時限。 -取消時在原 bus 以獨立 0.25 秒預算嘗試 Request.Close,再釋放連線;取消的已回傳圖片會刪除。 -Scoped CLI 擷取會停止並回收自己建立的 helper/process group,清理有時限,pipe close 失敗也不蓋掉原取消, -已回收的數字 PID 不再作為訊號目標。liboeffis 取得 session 時會觀察停止並釋放自身 context。 -不強制中斷不合作或原生呼叫,清理期間 GUI 仍可操作;restore/重啟、原生 session 控制、 -擷取擁有者 metadata 與其餘面板/backend 遷移保留於 `Progress.md`。 - -`python -m examples.cancellable_diagnostics` 預設只做受控取消示範,不呼叫 provider。 -`--active --cancel-after 2` 才明確執行診斷並在兩秒後要求停止;真機/裝置/API 驗收另外列管。 - -開啟 Diagnostics 只顯示已翻譯的「尚未執行」狀態,不執行檢查。 -選擇 **Actions → 執行診斷** 才會啟動既有主動檢查,可能擷取螢幕或需要 portal 同意; -切換語系不啟動檢查。明確的 `run_diagnostics`、`AC_diagnose` 與 MCP 診斷呼叫維持主動行為; -無副作用的能力檢視使用下方獨立操作。 - -未完成的 screenshot portal 請求會在斷開原始 bus 前嘗試 `Request.Close`, -使用獨立的 0.25 秒 D-Bus I/O 預算。伺服器回傳替代 handle 時會跟隨該 handle; -方法回覆不確定時則使用預測 handle,已完成的 Response 不重複關閉。 -一般清理錯誤不覆蓋主要擷取失敗;原始取消與強制中斷物件會穿過包裝及清理繼續傳播。 -D-Bus 寫入與回覆共用呼叫預算,連線建立有明確時限,connect/驗證/Hello 中斷時, -即使 `__enter__` 失敗也會釋放自己擁有的描述元。實際合成器/對話框取消仍待平台驗收。 - -有一件只在 Wayland 出現、需要事先規劃的事:**擷取回來的圖裡可能有滑鼠游標。** -這裡沒有任何一條擷取要求游標,但只要 backend 沒有游標平面(包含任何以 -`WLR_NO_HARDWARE_CURSORS=1` 執行的 session),wlroots 就會畫**軟體游標**並把它 -合成進輸出緩衝區,而擷取交回來的正是那一份。Windows 與 X11 都不含游標,所以 -「定位器、樣板比對或 OCR 在目標中間看到一個游標形狀的洞」只會在這裡發生。 -Wayland 不讓用戶端讀游標位置,所以沒有東西可以可靠地遮或閃避:請在擷取之前 -把指標移離要拍的區域。`screen_capture` 檢查會以 `cursor_may_be_captured` 回報這件事。 - -如果以上都不適用你的環境,可以直接指定自己的指令——它優先於所有偵測,`{output}` 會被 -換成暫存 PNG 路徑: - -```bash -export JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND="mycapture --png {output}" -``` - -Wayland 禁止非特權用戶端進行全域輸入錄製——若要錄製,請設定 -`JE_AUTOCONTROL_LINUX_DISPLAY_SERVER=x11` 並在 X11 session 下執行。視窗管理支援 -Windows、macOS(pyobjc)與 X11(含 XWayland);純 Wayland session 的協定不讓用戶端看到別的程式的視窗, -所以 `list_windows()` 回傳空清單,其餘視窗操作一律拋出帶原因的 `AutoControlUnsupportedOperationException`。對於會忽略合成輸入的應用程式, -可選用驅動層後端(`JE_AUTOCONTROL_WIN32_BACKEND=interception`、 -`JE_AUTOCONTROL_LINUX_BACKEND=uinput`、ViGEm 虛擬手把);驅動未安裝時會自動退回原本行為。 - ---- - -## 設定 - -AutoControl 讀取的每一個環境變數。這裡沒有任何一項是必填的:完全不設定時,AutoControl 會自行選擇平台後端,伺服器只綁定 `127.0.0.1`,所有需要主動開啟的功能(簽章強制、RBAC、USB 直通、工具路徑限制)都是關閉的。[設定參考](https://autocontrol.readthedocs.io/en/latest/Zh/doc/configuration/configuration_doc.html)([原始檔](../docs/source/Zh/doc/configuration/configuration_doc.rst))列出完整的可接受值,並把每個變數連到說明該功能的頁面;CI 會拿它以及下面的表格和程式碼比對。 - -### 平台後端 - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_WIN32_BACKEND` | `sendinput` | 設成 `interception` 時鍵盤與滑鼠改走 Interception 驅動程式;找不到驅動或 DLL 時會警告並退回 `SendInput`。 | -| `JE_AUTOCONTROL_LINUX_BACKEND` | `x11` | 設成 `uinput` 時直接寫入核心輸入事件;`/dev/uinput` 無法寫入時會警告並退回 XTest。 | -| `JE_AUTOCONTROL_LINUX_DISPLAY_SERVER` | `auto` | 決定載入哪一個 Linux 後端:`auto` 讀取 `XDG_SESSION_TYPE` 與 `WAYLAND_DISPLAY`;`wayland` 或 `x11` 則強制指定(在 Wayland 工作階段設成 `x11` 只能操作 XWayland 視窗)。 | - -### Windows Interception 驅動程式 - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_INTERCEPTION_DLL` | 未設定:先找 `PATH`,再找套件旁邊 | `interception.dll` 的完整路徑。 | -| `JE_AUTOCONTROL_INTERCEPTION_KEYBOARD` | `1` | 鍵盤事件要送往的 Interception 裝置編號(`1`–`10`)。 | -| `JE_AUTOCONTROL_INTERCEPTION_MOUSE` | `11` | 滑鼠事件要送往的 Interception 裝置編號(`11`–`20`)。 | - -### Wayland - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND` | `auto` | 設成 `cli` 時透過 `ydotool` 送出輸入,完全不向桌面 portal 提出要求。這是啟動前就做好的選擇:使用者拒絕授權後,AutoControl 不會自行切換過去。 | -| `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL` | `warn` | 只影響 `ydotool` 路徑的絕對移動(那其實是會被合成器加速的相對位移):`warn` 警告一次後照樣移動,`flat` 表示加速已關閉、不再警告,`strict` 直接拒絕移動。 | -| `JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND` | 未設定 | 自訂的截圖指令列,以 `{output}` 表示 PNG 的輸出路徑。優先於 `grim`、`gnome-screenshot`、`spectacle` 與 portal。 | -| `JE_AUTOCONTROL_WAYLAND_RECORD_DEVICES` | 未設定:一個都不讀 | `PhysicalRecorder` 可以讀取的 `/dev/input/event*` 裝置(以逗號分隔);實體輸入錄製必須逐一指定裝置才會啟用。 | - -### MCP 伺服器 - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_MCP_READONLY` | 未設定 | 設成 `1` 時只提供、也只能呼叫標示為唯讀的工具。 | -| `JE_AUTOCONTROL_MCP_TOOL_PROFILE` | 未設定 | `static` 模式的工具清單:以逗號分隔的工具名稱與 `category:<名稱>`。 | -| `JE_AUTOCONTROL_MCP_ALIASES` | `1` | 設成 `0` 時不註冊 `ac_*` 工具之外的簡短別名(`click`、`screenshot` …)。 | -| `JE_AUTOCONTROL_MCP_TOKEN` | 未設定 | HTTP 傳輸的 Bearer 權杖。啟用 RBAC 之後不再接受。 | -| `JE_AUTOCONTROL_MCP_ALLOWED_ORIGINS` | 未設定:只接受本機來源 | HTTP 傳輸額外接受的瀏覽器來源(以逗號分隔,須完全相符,例如 `https://example.test:8443`)。 | -| `JE_AUTOCONTROL_MCP_CONFIRM_DESTRUCTIVE` | 未設定 | 設成 `1` 時具破壞性的工具在執行前先向用戶端要求確認(MCP elicitation)。 | -| `JE_AUTOCONTROL_MCP_PATH_ROOTS` | 未設定:不限制 | 工具的每一個檔案參數都必須落在這些目錄內(以作業系統的路徑分隔字元分隔)。 | -| `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` | 未設定 | 設成 `1` 時同時接受 MCP 用戶端透過 `roots/list` 回報的根目錄。 | -| `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` | 未設定:不限制 | `ac_resolve_ref` 可以讀取的環境變數名稱(以逗號分隔,可用 `fnmatch` 樣式);設了卻沒有指名任何變數時,一個都不允許。 | -| `JE_AUTOCONTROL_MCP_AUDIT` | 未設定 | JSON-lines 檔案的路徑,每一次 `tools/call` 寫入一筆記錄。 | -| `JE_AUTOCONTROL_MCP_ERROR_SHOTS` | 未設定 | 工具每次失敗時存放截圖的目錄。 | -| `JE_AUTOCONTROL_FAKE_BACKEND` | 未設定 | 設成 `1` 時 MCP 伺服器只在記憶體中記錄滑鼠、鍵盤與剪貼簿呼叫而不實際執行,供沒有顯示器的 CI 使用。 | - -### REST/RBAC 與 chat-ops - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_RBAC_USERS` | 未設定:沿用共用權杖 | 使用者檔案的路徑。設定它就等於為 REST API 與 MCP HTTP 傳輸啟用角色。 | -| `JE_AUTOCONTROL_CHATOPS_SCRIPT_ROOT` | 未設定:`run` 會被拒絕 | chat-ops 的 `run` 指令唯一可以載入動作檔的目錄。 | - -### 執行與簽署動作檔 - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_ALLOWED_PACKAGES` | 未設定:一個都不允許 | `AC_add_package_to_executor` 可以載入的套件(以逗號分隔,含子模組),對所有進入點生效。只在行程啟動時讀取一次。 | -| `JE_AUTOCONTROL_REQUIRE_SIGNED_ACTIONS` | 未設定 | 設成 `1` 時所有會執行動作檔的路徑,都拒絕沒有有效簽章檔的動作檔。 | -| `JE_AUTOCONTROL_ACTION_SIGNING_PRIVATE_KEY` | 未設定 | Ed25519 私鑰(PEM)的路徑。只在負責簽署的機器上設定;設定後簽署會寫出第 2 版的簽章檔。 | -| `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` | 未設定 | 對應公鑰的路徑。在每一台執行端設定:它只能驗證,不能簽署。 | -| `JE_AUTOCONTROL_ACTION_SIGNING_PASSPHRASE` | 未設定 | 私鑰建立時若有設定通行碼,在這裡提供。 | -| `JE_AUTOCONTROL_ACCEPT_LEGACY_ACTION_SIGNATURES` | 未設定 | 設成 `1` 是遷移模式:設定公鑰之後,第 2 版之前寫出的 HMAC 簽章檔會被拒絕,除非設定了這個變數。所有檔案重新簽署後請再關掉。 | - -### 遠端桌面與信令 - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR` | `~/Downloads/AutoControl` | 遠端桌面檢視端存放主機傳來檔案的目錄。收到的路徑一律限制在這個目錄內。 | -| `JE_AUTOCONTROL_USB_PASSTHROUGH` | 未設定 | 設成 `1` 時在遠端桌面通道上啟用 USB 直通指令。 | -| `AC_SIGNALING_SECRET` | 未設定 | 信令/設定同步伺服器的共用密鑰(`X-Signaling-Secret`)。伺服器在沒有 `--shared-secret` 時讀取它。 | - -### GUI - -| 變數 | 預設 | 作用 | -|---|---|---| - -### 記錄檔、資料與測試 - -| 變數 | 預設 | 作用 | -|---|---|---| -| `JE_AUTOCONTROL_LOG_FILE` | `~/.je_auto_control/logs/AutoControlGUI.log` | 記錄檔寫入的位置。指定空裝置(`/dev/null`、`NUL`)即可關閉檔案輸出。在寫入第一筆記錄時才讀取,而不是在 import 時。 | -| `JE_AUTOCONTROL_ENV` | `default` | 資產庫目前使用的環境(`active_environment()`),讓同一份腳本在 `dev` 與 `prod` 讀到不同的值。 | -| `JE_AUTOCONTROL_REDACTION` | `off` | 截圖遮蔽的預設政策:`off`、`moderate` 或 `strict`。未知的名稱會報錯,不會被當成 `off`。 | -| `JE_AUTOCONTROL_PYTEST_ARTIFACTS` | `./autocontrol_screenshots` | 測試沒有使用 `autocontrol_screenshot_dir` fixture 時,pytest 外掛寫入失敗截圖的目錄。 | - ---- - -## 文件與範例 - -| 資源 | 內容 | -|---|---| -| [`examples/`](../examples/) | 45 個自足腳本:截圖點擊、OCR、排程器、遠端桌面、agent loop、可觀測性、錄製、變數、熱鍵、觸發器、報表、MCP、REST、機密、外掛、computer use、Wayland、跨主機 DAG、chat-ops、pytest/BDD、錨點定位、動作日誌、因果 peer 控制。 | -| [Read the Docs](https://autocontrol.readthedocs.io/en/latest/) | 完整 API 參考,含英文與中文。 | -| [architecture_explore.md](../architecture_explore.md) | 逐層記錄每個模組的職責。 | -| [docs/CAPABILITY_MATRIX.md](../docs/CAPABILITY_MATRIX.md) | 能力 × 平台對照矩陣。 | -| [docs/API_LIFECYCLE.md](../docs/API_LIFECYCLE.md) | 穩定 API 與棄用政策。 | -| [docs/updates/](../docs/updates/README.md) | 更新紀錄:各版本說明與完成的工作,每月一個檔(原 `WHATS_NEW.md`)。 | -| [CHANGELOG.md](../CHANGELOG.md) | 相容性變更記錄。 | -| [SECURITY.md](../SECURITY.md) | 安全政策與回報方式。 | - ---- - -## 開發 - -```bash -git clone https://github.com/Integration-Automation/AutoControlGUI.git -cd AutoControl -pip install -r dev_requirements.txt -uv sync # 或:以已提交的 uv.lock 做可重現安裝 -``` - -```bash -python -m pytest test/unit_test/headless # 無頭單元測試 -python -m pytest test/integrated_test/ # 跨模組流程測試 - -ruff check je_auto_control/ -pylint je_auto_control/ -bandit -c pyproject.toml -r je_auto_control/ - -python test/verify/typing_contract_verify.py # mypy,整個套件,三個目標平台 -python test/verify/typing_contract_verify.py --extras # 同一項檢查,改用真正的 PySide6/aiortc 型別 -python -m sphinx -b html -W docs/source docs/_build/html # 文件,警告視為錯誤 -``` - -dev/main 的無頭工作會保留七天的 `native--` artifact,內含合併行程輸出、 -套件/執行環境版本與退出碼。Linux 經 GDB 保留各執行緒原生堆疊;其他平台保留 Python -faulthandler 輸出,測試失敗仍會使工作失敗。可在 repo 執行單一指令 -`python scripts/ci_native_diagnostics.py --artifact-dir test-artifacts -- python -m pytest -v --tb=short --timeout=120`; -Linux 安裝 GDB 後,可在 `--` 前加入 `--native`。 -含空白/引號的 argv 仍是原始參數,已處理的 `SIGINT` 會傳給子行程。 -Linux 先在完整套件的 debugger 外驗證診斷工具;前置檢查紀錄也收在同一 artifact。 - -選定的 dev 推送由 `.github/workflows/ei-lifecycle.yml` 在隔離 libei/libeis -容器執行,將版本及兩份原生紀錄保留於 `ei-lifecycle--` artifact 十四天。 -半開與 live 釋放子行程分別有十/六十秒時限與 faulthandler;其他子行程失敗使 CI 失敗, -釋放成功必須有 begin/end 標記。半開探測另須有相同整數 fd 數量,live 清理先釋放擁有的 -device refs。run 39507190704 在 libei/libeis 1.3.901-1 通過 9/9 與 20/20 檢查, -包含座標越界拒絕且不轉用 CLI。半開 `ei_unref` 仍會 SIGSEGV,因此保留 runtime 保護, -helper 隔離仍待完成。裝置暫停與序號回讀仍未驗證;受控 socket peer 不代表合成器授權、 -真機或多螢幕驗收。 - -歡迎貢獻——請見 [CONTRIBUTING.md](../CONTRIBUTING.md) 與 -[CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md)。CI 會強制兩條規則:`import je_auto_control` -絕不能載入 PySide6;每個功能都必須同時具備無頭 API 與 GUI 介面。 - ---- - -## 授權 - -[MIT License](../LICENSE) © JE-Chen。 -內含與選用第三方元件的授權請見 [Third_Party_License.md](../Third_Party_License.md)。 - -- **首頁**:https://github.com/Integration-Automation/AutoControlGUI -- **PyPI**:https://pypi.org/project/je_auto_control/ -- **文件**:https://autocontrol.readthedocs.io/en/latest/ - -舊式 MCP 動作包裝、平行分支及本機 DAG worker 也會保留相同的來源限制。 - -受管指標動作可指定該次觀察的元素索引或縮圖座標,由主機檢查目前畫面並換算原生座標,包含縮放與負螢幕原點。收據保存幾何依據,不保存影像位元組。`AgentObservationStale` 表示分派前已拒絕動作;本機 agent 只在 adapter 確認沒有按住或待處理輸入時,於重試預算內重新觀察。 - -緊急停止先回傳帶有 metadata.details_deferred 的精簡狀態,完整產物連結可由個別任務查詢。 - -受管滑鼠按下前會正規化按鈕擁有權並確認實際游標位置。Windows 指標檢查會拒絕其他視窗遮擋。影像只將指定視窗繪製至清空的私有 GDI 記憶體,幾何變動會拒絕該畫面;繪製或讀取失敗亦會釋放資源。不改用桌面擷取。這些路徑已用模擬原生 API 測試,實際原生驗收仍未驗證。 - -Agent 任務介面將任務範圍、工作流程設定、觸發器、技能及恢復分頁。觀察頁顯示唯讀元素和已驗證、嚴格遮罩的 JPEG,每個邏輯畫面像素對應一個呈現像素。選取元素或影像座標只會編輯該次觀察的動作請求;由 Actions 的「執行觀察動作」透過共用任務 API 送出。切換任務會清除預覽,遲到回覆不能替換目前任務;新畫面必須重新選取,舊索引不能直接重用。關閉介面只解除請求訂閱。 - -受管工作流程可用 workflow_wait/AC_workflow_wait 等待指定控制項的精確值或狀態,只重複讀取;可取消且受動作預算限制,預設五秒、上限六十秒,不重送寫入或提交。固定技能每一步都驗證已完成收據與固定順序,恢復亦不能跳過讀回失敗的步驟;模型自主迴圈仍保留停滯偵測。新表單/跨應用範本會在提交前拒絕原本已匹配的確認值,提交後等待新的狀態轉換。批次可設定 new_record_selector 逐筆重設;確認只證明設定的介面轉換,有交易識別值時應使用它。歸檔範本完成時會重讀指定清單及檔案摘要,清單上限一 MB,總驗證資料上限六十四 MiB。 - -AgentHumanReview 表示未儲存內容或未知對話框需人工審閱;包含外部觀察請求都會記錄 waiting_user 並釋放輸入控制權,明確恢復後仍會重新檢查。Windows 依原生對話框/停用擁有者及英中日已知未儲存文字判定。Workspace 也會拒絕標題首尾帶星號的文件,並可在視窗設定加入 unsaved_selector 與 unsaved_value,於改變排列前檢查應用特有指示;不宣稱能推斷所有程式的未儲存狀態。標準檔案對話框沿用 AC_handle_file_dialog 執行器,受管 driver 只接受唯一精確標題、相同 PID、已確認前景,以及授權根目錄內的絕對路徑。UIA 控制項須屬於實際指定的根視窗,同 PID 的其他視窗也會拒絕。模擬原生與本機 HTTP 測試已有覆蓋,實際平台驗收仍未驗證。 - -主機目標以 AgentTargetProfile 與 manage_agent_target(AC_agent_target,register/get/disable/enable/probe)設定。名稱及設定固定不可替換,目前提供 desktop/files/browser adapter,未實作類型會被拒絕;瀏覽器可使用主機審閱的 helper_python。任務固定主機設定摘要,不能擴大工具、應用、根目錄或網路來源。啟停狀態會跨重啟保存並於分派時檢查;停用會要求暫停及清理,重新啟用仍須明確恢復任務。list_agent_targets/AC_agent_target_list/CLI agent-task targets 只提供被動資訊,readiness=not_probed、native_evidence=not_recorded;完整設定需要 manage_hosts。CLI agent-task target 及 GUI「主機目標」頁使用同一服務。匿名有效 MCP 工具 session 的直接及舊式包裝呼叫都以 operator 權限執行;MCP 主機管理需要已驗證的管理員,可信任的直接 Python 呼叫維持原行為。瀏覽器自動化統一由 WebRunner(je_web_runner)提供,本機開發來源為 D:/Codes/WebRunner;browser profile 使用受管 je_web_runner SDK 契約,依賴診斷不代表原生可用。 - -既有瀏覽器自動化(包含 open_path(URL) 與 AC_open_path)統一交由 WebRunner,Python 套件名稱為 je_web_runner。URL 計畫的 backend 現為 je_web_runner,原本比較 webbrowser 描述值的呼叫端需改用新值;函式介面與本機檔案開啟維持相容。實際 URL 執行需要設定的 WebRunner 專案,缺少時傳出 WebRunnerBridgeError,不改用 OS 瀏覽器。本機開發來源為 D:/Codes/WebRunner;純計畫及注入 opener 測試不需要該套件。協定支援由 WebRunner 與其選用的瀏覽器決定。既有瀏覽器 GUI/MCP/AC 及錄製的 WR_* 動作都使用同一橋接。 - -## Local DAG 完成證據的明確移交 - -其他 caller 持有的既有復原子任務,可透過明確且可撤銷的移交,向原 local DAG 提供完成證據。 -以 `manage_agent_recovery` 的 `review_handoff` 提供最終 `task_id`、`batch_id`、`node_id`, -有權管理者再用相同 ID、將返回的 `handoff_review` 填入 `review`,並附非空 `note` 執行 -`create_handoff`。接收者由服務依真實原始 admission 決定。在 `review_continuation` 的 successor -決策中,除 `node_id`、`action`、`task_id` 外明列 `handoff_id`,再審閱並批准整份 continuation。 -最多支援十六層真實復原鏈,包含經私有 admission 的永久唯讀最終驗證者;一般任務歸屬維持原樣。 - -`get_handoff`/`revoke_handoff` 使用 `handoff_id`;`list_handoffs` 使用 `batch_id`、`node_id`。 -建立與採認時重查實際 owner、建立審閱者、簽發 session 的來源根限制、當前接收端限制、固定 scope、 -效果快照、獨立完成及資源退役。批准、開始及後續相依驗證都重查同意;撤銷或證據遺失會阻止採認。 -期限不超過最早終止見證既有的三十天保留期限。公開回應只含有限 ID、摘要與狀態,不含私有參數、 -capture 或 principal 資料庫路徑;不授予一般任務讀取/輸入權、不移轉歸屬或重播。 -跨主機及非 DAG 的移交契約仍列於 `Progress.md`。 - -Agent Tasks 的成果移交頁提供操作選單與 JSON 編輯器;Actions 只準備審閱、建立、撤銷請求, -不自動派送。五個可編輯的 `agent_handoff_*.json` 範例涵蓋 review/create/get/list/revoke。 -Python、AC、CLI、具名 MCP、REST、Builder 共用這些 recovery 操作。本次證據涵蓋契約及自有檔案 -流程;暫緩的原生桌面、瀏覽器、裝置及二十四小時驗收仍須各自提供證據。 - -## 明確續授權唯讀完成驗證 - -原來源的 origin 參照過期或不可用時,明確呼叫 -`manage_agent_recovery("review_completion_authorization", {"task_id": ""})`。 -審閱服務產生的 `verification_spec`、保留/替換/當前 origin 限制,再以相同 `task_id`、返回的 -`snapshot`、`authorization_review` 及非空 `note` 呼叫 `create_authorized_completion`。 -可選 `owner_policy="source_owner"` 在建立時另須返回的 `ownership_review`;不能自行提供新驗證 -規格。仍有效的舊限制保留,新根目錄與原上限、前一讀者上限及當前 session 取交集。 -已重新授權的讀者不能改用一般完成審閱來移除這些限制。 - -子任務永久唯讀,依真實已確認的原效果獨立檢查當前條件,不輸入、不重播、不恢復 capture, -也不修改舊見證。來源/效果快照、實際 owner/reviewer 及原 DAG admission 都會重查。 -建立任務與最終完成各自在自己的 SQLite writer 內寫入後重驗,變更時共同回滾。 -最多支援十六層真實復原鏈;已退役且成功的讀者可再次明確續授權,但保留前次較窄上限及所有仍有效 -的繼承限制。來源/效果證據已改變時仍拒絕,不能藉由 scope 續授權默默修復舊證據。 - -歷史 `get` 保留 succeeded 狀態;新授權失效時,當前 `completion_contract` 為零、 -`completion_authorization` 為 unavailable,DAG 採認與後續相依驗證會拒絕這份證據。 -新的唯讀標記損壞/遺失時,在 helper 啟動前拒絕。以 `completion_task_id` 錄製時沿用原語義動作及 -已審閱的限縮 scope,但草稿仍須自己的新驗證試跑。此流程不發布過期候選,也不續授權已發布技能; -既有技能重新授權流程維持分開。 - -Python、AC、CLI、具名 MCP、REST、Builder 共用兩個操作;Recovery 頁的兩個明確 Actions -沿用所選任務、owner policy 與請求編輯器。可編輯範例為 `agent_completion_authorization_review.json` -與 `agent_completion_authorization_create.json`。remote 唯讀來源、跨主機移交、 -實際應用狀態重建,以及暫緩的原生/裝置/瀏覽器/二十四小時驗收仍列於 `Progress.md`。 - -## 明確移交已續授權讀者的完成證據 - -既有 `review_handoff`/`create_handoff` 現在可明確將已重新授權、永久唯讀讀者的完成 -證據交給實際原 local DAG。指定該讀者的 task ID 與原 batch/node,由服務推導證明;不能自行提供 -policy、擁有者覆寫或授權 bundle。一般成果移交沿用既有規則。 - -預覽的 `evidence.completion_authorization` 顯示完成任務/審閱、固定的審閱摘要、根目錄數量及 -替換/保留/當前 origin ID,不含私人 principal 路徑、動作參數或 capture。建立時以最上層返回的 `handoff_review` -作為請求的 `review`,並提供非空 `note`。每個真實任務都保留已審閱的上限與所有仍有效的歷史限制;不可用的 -參照須明確審閱替換,發出移交當下額外的 session 限制也持續有效。移交沿用讀者已實際驗證的相同 -根目錄;交集改變時須重新審閱及執行唯讀完成驗證,接收者的 session/profile 限制也會持續套用。 - -最多十六層真實復原鏈可混合先前已審閱的可執行子任務及私人讀者。成功的中間讀者必須具備實際 -私人歷史 scope 與退役證明,一般已成功來源沒有這個例外。發出或採認移交時不啟動 helper、不重播 -輸入;舊來源狀態、見證、收據及所有任務擁有者維持原樣。原擁有者只取得有限完成投影,不能因此 -一般讀取其他 caller 的任務。撤銷或授權失效會阻止採認及後續相依驗證。 - -原 accepted-request hash、原始提交見證、私人 admission、graph、owner/reviewer、整條來源/子任務 -快照與最後讀者的續授權都固定在證明內。讀取與寫入後重驗使用同一個 SQLite writer,包含尚未提交 -的變更;發現變動即回滾任務/移交建立。繼承的 `dag_batch` 選項不等於 admission,必須沿有界真實 -復原鏈找到原請求及實際授權身分,不補造 admission。舊的一般完成 binding hash 保持相容;各歷史 -任務各自審閱限制,不能藉由合併歷史繞過正常十六個有效 origin 上限或原根目錄界線。 - -相同有效重試沿用原 note 與 ID,已撤銷 ID 不會重新啟用;重啟與採認保留最早終止見證的三十日期限。 -origin 失效後仍可查 get/list 歷史與 revoke,但歷史不代表可用完成證據或輸入授權。Python、AC、 -CLI、具名 MCP、REST、Builder 共用五個既有操作,Handoffs Actions 與 JSON 編輯器/結果區可顯示 -明確續授權審閱,不自動派送同意。跨主機移交、remote 讀者、實際應用/裝置 -來源及暫緩的原生/瀏覽器/真機/二十四小時驗收仍列於 `Progress.md`。 - -## 明確移交任務來源的完成證據 - -既有五個移交操作也接受真實非 DAG 來源任務: - -- `review_handoff` 提供 `source_task` 與實際最後證據的 `task_id`。 -- `create_handoff` 再以最上層返回的 `handoff_review` 作為 `review`,並填寫非空 `note`。 -- `list_handoffs` 提供 `source_task`;`get_handoff`/`revoke_handoff` 仍使用 `handoff_id`。 +## 可以做什麼 -任務來源與 DAG batch/node 欄位互斥,服務依實際保存的 grant 判定儲存類別。真實 DAG 祖先仍須走 -原 batch/node 路徑,不能藉由已移除 `dag_batch` 的唯讀讀者繞過,也不補造 DAG 節點或 admission。 -一般任務不必虛構提交見證或 idempotency key;實際存在的原請求須固定並在同一 SQLite writer 重驗。 +- 操作滑鼠、鍵盤與視窗。 +- 用圖片比對、OCR、無障礙 API 或選配的視覺模型尋找控制項。 +- 將重複工作儲存為 JSON 動作檔。 +- 透過 MCP 連接 AI 用戶端,或透過 REST 與 Python 整合。 +- 在選配 GUI 中使用錄製、排程與遠端桌面工具。 -既有技能操作明確選擇 `handoff_id`。`record` 以 `completion_task_id` 採認獨立讀者,建立的 draft -仍須自己的新驗證 trial;`accept` 使用完成讀者時,仍保留原 candidate 的真正驗證任務。 -`review_execution` 與對應 `accept` 可選實際 `execution_task_id`;最後證據是獨立讀者時,再提供 -`completion_task_id`。服務核對原本完整語義動作計畫、真實執行 ID 及獨立完成條件,不能把讀者 -當執行任務或替代驗證 trial。 +Windows、macOS、X11 與 Wayland 使用不同後端,實際功能取決於系統權限與選配依賴。Windows ARM64 另有限制,部署前請先閱讀安裝文件。 -grant 只提供私人有限證據視圖,原擁有者、來源狀態與收據維持原樣,一般 get/list/observe/act/ -resume 權限不擴大。發出或採認時不啟動 helper、不重播輸入。真實快照、可選原請求、實際 owner/ -reviewer、退役輸入與有效歷史 origin 均持續核對;新錄製的 draft 保留發出與接收 session 上限。 -失效限制須經真實私人完成續授權,不能靠相同 hash 或自填 scope flag 替代;唯讀採認也不會續授權 -已發布技能原本的輸入權限。 +受管理的 Agent 任務與跨主機傳輸包含實驗性功能;採用前請查看實作紀錄與專案進度中的驗收狀態。 -來源祖先與後續移交鏈合計最多十六條真實復原連結。期限沿用最早終止證據的三十日,改錨定較新的 -讀者不會延長舊祖先。DAG 與任務 grant 的 INSERT 後及相同重試都重驗撤銷墓碑;來源/請求/角色/ -origin/撤銷變動會回滾 grant、draft 或發布。已撤銷 ID 不重啟,origin 失效後的 get/list/revoke -歷史只顯示有限 ID/hash,不代表持續有效的完成證據或輸入授權。 +## 文件 -Handoffs 頁可明確選原本機 DAG 或原任務來準備 JSON;三個技能 Actions 準備帶 grant 佔位符的錄製、 -發布與執行審閱,不自動同意或發布。Python、AC、CLI、具名 REST/MCP 與 Builder 共用相同操作及 -真實 caller。`examples/` 提供 `agent_task_handoff_review.json`、`agent_task_handoff_create.json`、 -`agent_skill_recording_handoff.json`、`agent_skill_completion_handoff.json`、 -`agent_skill_execution_handoff_review.json` 與 `agent_skill_execution_handoff_accept.json`。 +- [安裝、平台支援與設定](../docs/guides/zh-TW/setup.md) +- [Python、JSON 與命令列用法](../docs/guides/zh-TW/usage.md) +- [AI Agent、MCP 與伺服器整合](../docs/guides/zh-TW/integrations.md) +- [完成驗證與證據移交](../docs/guides/zh-TW/evidence.md) +- [開發與相關資源](../docs/guides/zh-TW/development.md) +- [實作紀錄](../docs/guides/zh-TW/implementation-notes.md) +- [Documentation index](../docs/README.md) +- [Examples](../examples/README.md) +- [Progress](../Progress.md) -跨主機移交、remote 讀者、實際應用/裝置來源、暫緩的原生與二十四小時驗收,以及未解的 -HTTP409/bootstrap 問題仍列於 `Progress.md`。 +## License -wheel 與原始碼發行套件包含 REST Dashboard 和 Swagger 的 HTML、CSS、JavaScript 資源。 -安裝後的套件沿用相同的本機 REST 路由與授權規則;提供靜態頁面不授予任務或桌面輸入權限。 +[MIT](../LICENSE) © JE-Chen. [Third-party licenses](../Third_Party_License.md). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..17d11f00d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,19 @@ +# AutoControl documentation + +Start with the [project README](../README.md) for installation and a first Python example. + +| Topic | English | 繁體中文 | 简体中文 | +|---|---|---|---| +| Installation and configuration | [en](guides/en/setup.md) | [zh-TW](guides/zh-TW/setup.md) | [zh-CN](guides/zh-CN/setup.md) | +| Automation usage | [en](guides/en/usage.md) | [zh-TW](guides/zh-TW/usage.md) | [zh-CN](guides/zh-CN/usage.md) | +| Agents and integrations | [en](guides/en/integrations.md) | [zh-TW](guides/zh-TW/integrations.md) | [zh-CN](guides/zh-CN/integrations.md) | +| Completion evidence | [en](guides/en/evidence.md) | [zh-TW](guides/zh-TW/evidence.md) | [zh-CN](guides/zh-CN/evidence.md) | +| Development | [en](guides/en/development.md) | [zh-TW](guides/zh-TW/development.md) | [zh-CN](guides/zh-CN/development.md) | +| Historical implementation notes | [en](guides/en/implementation-notes.md) | [zh-TW](guides/zh-TW/implementation-notes.md) | [zh-CN](guides/zh-CN/implementation-notes.md) | + +## Further reading + +- [API and user manual source](source/index.rst) +- [Examples](../examples/README.md) +- [Development updates](updates/README.md) +- [Current progress](../Progress.md) diff --git a/docs/guides/en/development.md b/docs/guides/en/development.md new file mode 100644 index 000000000..5cc093594 --- /dev/null +++ b/docs/guides/en/development.md @@ -0,0 +1,98 @@ +# Development and resources + +[README](../../../README.md) · [Documentation](../../README.md) + +## Documentation and examples + +| Resource | What's in it | +|---|---| +| [`examples/`](../../../examples) | 45 self-contained scripts: screenshot + click, OCR, scheduler, remote desktop, agent loop, observability, recording, variables, hotkeys, triggers, reports, MCP, REST, secrets, plugins, computer use, Wayland, cross-host DAGs, chat-ops, pytest/BDD, anchor locators, action journals. | +| [Read the Docs](https://autocontrol.readthedocs.io/en/latest/) | Full API reference, English and 中文. | +| [architecture_explore.md](../../../architecture_explore.md) | Every module's responsibility, layer by layer. | +| [docs/CAPABILITY_MATRIX.md](../../CAPABILITY_MATRIX.md) | Capability × platform matrix. | +| [docs/API_LIFECYCLE.md](../../API_LIFECYCLE.md) | Stable-API and deprecation policy. | +| [docs/updates/](../../updates/README.md) | Update log: release notes and finished work, one file per month (formerly `WHATS_NEW.md`). | +| [CHANGELOG.md](../../../CHANGELOG.md) | Compatibility changelog. | +| [SECURITY.md](../../../SECURITY.md) | Security policy and reporting. | + +--- + +## Development + +```bash +git clone https://github.com/Integration-Automation/AutoControlGUI.git +cd AutoControl +pip install -r dev_requirements.txt +uv sync # or: reproducible install from the committed uv.lock +``` + +```bash +python -m pytest test/unit_test/headless # headless unit tests +python -m pytest test/integrated_test/ # cross-module workflows + +ruff check je_auto_control/ +pylint je_auto_control/ +bandit -c pyproject.toml -r je_auto_control/ + +python test/verify/typing_contract_verify.py # mypy, whole package, three target platforms +python test/verify/typing_contract_verify.py --extras # the same against the real PySide6 / aiortc types +python -m sphinx -b html -W docs/source docs/_build/html # the docs, warnings as errors +``` + +The dev/main headless jobs retain `native--` artifacts for seven +days: merged process output, package/runtime versions and exit status. Linux +runs under GDB to retain all-thread native backtraces; other platforms retain +Python faulthandler output. Test failures remain failures. From a repository +checkout, reproduce collection with `python scripts/ci_native_diagnostics.py +--artifact-dir test-artifacts -- python -m pytest -v --tb=short --timeout=120` +(one command); add `--native` before `--` on Linux with GDB installed. +Literal argv (including whitespace/quotes) and handled `SIGINT` reach the +child unchanged. Linux first verifies the runner outside the suite's debugger; +its preflight logs are included in the same artifact. + +Selected dev pushes run `.github/workflows/ei-lifecycle.yml` in an isolated +libei/libeis container, retaining versions and both native logs for 14 days in +`ei-lifecycle--` artifacts. Half-open and live cleanup children +have 10/60-second deadlines and faulthandler. Unrelated child failures fail CI; +successful cleanup requires begin/end markers. The half-open probe also requires +equal integer descriptor counts; live cleanup releases owned device refs first. +Run 39507190704 on libei/libeis 1.3.901-1 passes 9/9 and 20/20 checks, including +native out-of-region refusal without CLI fallback. Half-open `ei_unref` still +segfaults, so runtime protection remains and helper isolation is pending. +Device pause and sequence readback remain unverified. These controlled socket +peers do not establish compositor consent, physical or multi-monitor acceptance. + +Contributions are welcome — see [CONTRIBUTING.md](../../../CONTRIBUTING.md) and +[CODE_OF_CONDUCT.md](../../../CODE_OF_CONDUCT.md). Two rules the CI enforces: `import +je_auto_control` must never pull in PySide6, and every feature needs both a headless +API and a GUI surface. + +--- + +## License + +[MIT License](../../../LICENSE) © JE-Chen. +See [Third_Party_License.md](../../../Third_Party_License.md) for the licenses of bundled and +optional third-party components. + +- **Homepage**: https://github.com/Integration-Automation/AutoControlGUI +- **PyPI**: https://pypi.org/project/je_auto_control/ +- **Documentation**: https://autocontrol.readthedocs.io/en/latest/ + +Legacy MCP action wrappers, parallel branches and local DAG workers retain the same origin ceilings. + +Managed point actions accept observation-local element indices or thumbnail image points. The host checks the current frame and resolves native coordinates, including scaling and negative monitor origins. Receipts retain geometry provenance without image bytes. `AgentObservationStale` identifies rejection before dispatch; local agents reobserve only within their retry budget when the adapter confirms no held or pending input. + +Emergency stop returns compact snapshots with metadata.details_deferred; fetch individual task details for full artifact links. + +Managed mouse presses normalize button ownership and confirm the actual cursor before input. Windows pointer checks reject foreign overlays. Vision renders the exact scoped window into cleared private GDI storage, rejects geometry changes and releases resources even on rendering/read failure. There is no desktop-crop fallback. Fake-native tests cover these paths; native acceptance remains unverified. + +The Agent tasks view groups task scope, workflow settings, triggers, skills and recovery into separate pages. Its observation page lists read-only elements and shows a validated, strictly masked JPEG at one rendered pixel per logical widget pixel. Selecting a row or image point only edits a frame-bound action request; Actions -> Perform observed action sends it through the shared task API. Switching tasks clears the preview, and late replies cannot replace the selected task. A new frame requires reselection before an old reference can be sent. Closing the view only detaches its requests. + +Managed workflow waits (workflow_wait / AC_workflow_wait) poll only exact scoped control values or states, with cancellation and a deadline capped by the action budget (default five seconds, maximum sixty). They never replay a write or submit. Fixed skills require all previous receipts to match the pinned sequence before continuing, including after resume; autonomous model loops retain stuck detection. New form/transfer drafts refuse an already-matching confirmation before submit and wait for a fresh transition afterward. Batch configurations may provide new_record_selector to reset each record; confirmations prove the configured UI transition, and transaction-specific receipt values should be used when available. Archive drafts also re-read the exact reviewed manifest and current file digests at finish (one-megabyte manifest and sixty-four-megabyte total evidence limit). + +AgentHumanReview identifies an unsaved-content or unknown-dialog gate. It persists waiting_user and retires input ownership, including for external observe requests; explicit resume still rechecks the gate. Windows detection uses native dialog/disabled-owner evidence and known English/Chinese/Japanese unsaved labels. Workspace tasks also pause for leading/trailing asterisks in document titles; a window entry may supply unsaved_selector and unsaved_value for an application-specific indicator before layout changes. These checks do not infer every application's dirty state. Recognized standard file pickers use a context-local driver on the existing AC_handle_file_dialog executor: exact unique title, same PID, confirmed foreground and canonical rooted absolute paths. UIA control patterns must belong to the actual owned root window, even when another window shares its PID. All behavior has fake-native/loopback coverage; actual platform acceptance remains unverified. + +Host-reviewed targets use AgentTargetProfile and manage_agent_target (AC_agent_target; register/get/disable/enable/probe). Names and configuration are immutable; desktop/file/browser adapters are currently supported; unimplemented kinds are rejected and optional browser helper_python is host-reviewed. Tasks pin the host profile digest and cannot expand its tools, applications, roots or network origins. Availability persists across restart and is checked at dispatch; disabling requests pause/cleanup, while enabling requires explicit task resume. list_agent_targets / AC_agent_target_list / CLI agent-task targets expose passive metadata with readiness=not_probed and native_evidence=not_recorded. Full configuration requires manage_hosts; CLI agent-task target and the GUI Host targets page use the same service. Live anonymous MCP tool sessions have operator authority across direct and legacy wrapper calls; MCP host management requires an authenticated administrator. Trusted direct Python callers remain unchanged. Browser automation belongs to WebRunner (je_web_runner), with D:/Codes/WebRunner as the development source; browser profiles use the managed je_web_runner SDK contract, and dependency probes do not establish native readiness. + +Existing browser automation, including open_path(URL) and AC_open_path, delegates to WebRunner (Python package je_web_runner). URL plans now report backend=je_web_runner; callers inspecting the previous webbrowser descriptor should use the new value. Signatures and local-file opening stay compatible. URL execution requires the configured WebRunner project and propagates WebRunnerBridgeError when unavailable, without opening an OS browser as a fallback. The development source is D:/Codes/WebRunner. Planning and injected-opener tests remain usable without that package; browser protocol support is determined by WebRunner and its selected browser. Existing dedicated browser GUI/MCP/AC paths and recorded WR_* actions share the same bridge. diff --git a/docs/guides/en/evidence.md b/docs/guides/en/evidence.md new file mode 100644 index 000000000..0a8a2e588 --- /dev/null +++ b/docs/guides/en/evidence.md @@ -0,0 +1,151 @@ +# Completion evidence and handoffs + +[README](../../../README.md) · [Documentation](../../README.md) + +## Explicit local DAG evidence handoffs + +Existing recovery children held by another caller can provide completion evidence to their +original local DAG through an explicit revocable handoff. In `manage_agent_recovery`, use +`review_handoff` with the final `task_id`, `batch_id` and `node_id`; an authorized manager then calls +`create_handoff` with the same IDs, returned `handoff_review` as `review`, and a nonempty `note`. +The service derives the recipient from the real original admission. In a `review_continuation` +successor decision, explicitly include `handoff_id` alongside `node_id`, `action` and `task_id`, then +review and approve the whole continuation. At most sixteen real recovery links are supported, +including a privately admitted permanent read-only final verifier. Ordinary task ownership remains. + +`get_handoff` and `revoke_handoff` take `handoff_id`; `list_handoffs` takes `batch_id` and `node_id`. +Issuance and consumption refresh actual owners, admitting reviewers, issuing-session root witnesses, +current consumer ceilings, fixed scope, effect snapshots, independent completion and retirement. +Approval, start and late dependency validation recheck consent; revocation or evidence loss blocks +adoption. Grants expire no later than the earliest retained terminal witness's existing thirty-day +deadline. Returned data contains bounded IDs, hashes and status, without private task arguments, +captures or principal-store paths. No ordinary task-read/input access, ownership transfer or replay is +granted. Cross-host and non-DAG handoff contracts remain outstanding in `Progress.md`. + +The Agent Tasks Handoffs page has an operation selector and JSON editor; Actions prepare review, +create and revoke requests without dispatching them. Five editable `agent_handoff_*.json` examples +cover review/create/get/list/revoke. Python, AC, CLI, authenticated MCP, REST and Builder use the +same recovery operations. These checks establish contract and owned-file behavior; deferred native +desktop, browser, device and 24-hour acceptance still require their own evidence. + +## Explicit read-only completion authorization renewal + +When original origin references are expired or unavailable, explicitly call +`manage_agent_recovery("review_completion_authorization", {"task_id": ""})`. +Review the server-derived `verification_spec` and retained/replaced/current origin context, then call +`create_authorized_completion` with the same `task_id`, returned `snapshot`, `authorization_review` +and a nonempty `note`. Optional `owner_policy="source_owner"` requires the returned `ownership_review` +at creation. Callers cannot supply a replacement verification spec. Existing live constraints stay; +new roots intersect the original ceiling, prior reader ceiling and current session. Ordinary +completion review does not replace this explicit consent for an already renewed reader. + +The child is permanently read-only. It independently checks current conditions against the actual +confirmed original effects, without input, replay, restoring captures or modifying old witnesses. +Source/effect snapshots, real owners/reviewers and original DAG admission are rechecked. Task admission +and final completion each revalidate inside their own SQLite writer after SQL; changes roll back. +At most sixteen actual recovery links are supported. A retired successful reader may be explicitly +renewed again, retaining its previous narrower ceiling and all still-valid inherited restrictions. +Changed source/effect evidence remains refused and must not be silently repaired by scope renewal. + +Historical `get` preserves succeeded state; loss of renewed authority makes its current +`completion_contract` zero and `completion_authorization` unavailable. DAG adoption and late dependency +validation then refuse that evidence. Malformed/missing renewed read-only markers fail before helper +startup. Recording with `completion_task_id` uses the approved restricted scope and original semantic +actions, but the draft still needs its own fresh validation trial. Renewal does not publish an expired +candidate or renew a published skill grant. Existing skill reauthorization remains separate. + +Python, AC, CLI, authenticated MCP, REST and Builder share both operations. The Recovery page exposes +two explicit Actions using its selected task, owner policy and request editor. Editable examples are +`agent_completion_authorization_review.json` and `agent_completion_authorization_create.json`. +Remote read-only providers, cross-host handoffs, actual application +state restoration and deferred native/device/browser/24-hour acceptance remain in `Progress.md`. + +## Explicit renewed-reader completion handoffs + +Existing `review_handoff` / `create_handoff` can explicitly transfer completion evidence from +a privately renewed, permanently read-only reader to its real original local DAG. Select that reader's +task ID and the actual original batch/node. The service derives the proof; callers cannot supply a +policy, ownership override or authorization bundle. Ordinary handoffs keep their existing rules. + +The preview's `evidence.completion_authorization` contains the completion task/review, a bound review +digest, approved-root count and replaced/retained/current origin IDs. It omits private principal paths, +action arguments and captures. Set creation's `review` to the returned top-level `handoff_review`, then +provide a nonempty `note`. Every actual task keeps its reviewed ceiling; all live historical restrictions stay, unavailable +references are explicitly reviewed, and the issuing session's additional constraints remain live. +The grant uses the exact already-verified reader roots. A different intersection requires another +real completion review and verification. The consuming session/profile still applies its own limits. + +At most sixteen actual recovery links may mix previously reviewed executable successors and private +readers. A succeeded intermediate reader needs actual private historical scope and retirement proof; +an ordinary succeeded source does not gain that exemption. No helper is launched or input replayed +while granting or adopting evidence. Old source state, witnesses, receipts and all task owners stay. +The original owner receives only the bounded completion projection, without ordinary access to the +other caller's task. Revocation or lost authority blocks adoption and late dependency validation. + +Original accepted-request hashes, raw submission witnesses, private admission, graph, owners/reviewers, +all real source/child snapshots and the leaf renewal remain bound. Reads and post-write checks use +the same SQLite writer, including uncommitted changes; mutation rolls back admission/grant creation. +An inherited `dag_batch` option is not admission: a bounded real recovery chain must resolve the actual +original request and admitting identity without creating a replacement admission row. Earlier ordinary +completion binding hashes remain compatible. Each historical task retains its own policy review; +combining history cannot bypass the normal sixteen-live-origin limit or any original root ceiling. + +Exact active retries retain their note and ID; revoked IDs never reactivate. Restart and adoption +preserve the earliest retained terminal witness's thirty-day deadline. Historical get/list/revoke stay +available after an origin expires, while that history supplies no usable completion or input grant. +Python, AC, CLI, authenticated MCP, REST and Builder share the five existing operations. Existing +Handoffs Actions and its JSON editor/result view show the explicit renewed review without dispatching +consent automatically. Cross-host handoff, remote readers, actual application/device +providers and deferred native/browser/device/24-hour acceptance remain in `Progress.md`. + +## Explicit task-source completion evidence handoffs + +The five existing handoff operations also accept a real non-DAG source task: + +- `review_handoff`: supply `source_task` and the actual final evidence `task_id`. +- `create_handoff`: add the returned top-level `handoff_review` as `review`, plus a nonempty `note`. +- `list_handoffs`: supply `source_task`; `get_handoff` and `revoke_handoff` still use `handoff_id`. + +Task-source fields and DAG batch/node fields are mutually exclusive. The service resolves persisted +grant IDs to their actual storage family. Original DAG ancestry must use its real batch/node route, +even if a later read-only reader dropped its `dag_batch` option. No synthetic DAG node or admission +is created. Ordinary standalone tasks need no invented submission witness or idempotency key; +any actual accepted request is bound and rechecked on the same SQLite writer. + +Select `handoff_id` explicitly in existing skill operations. `record` uses a separate verified reader +through `completion_task_id` and creates a draft which still needs its own new validation trial. +`accept` with `completion_task_id` keeps the actual original candidate's validation task. +`review_execution` and its matching `accept` may select an actual `execution_task_id`; add +`completion_task_id` when the final granted evidence is a separate reader. The service verifies +the exact complete original semantic action plan, real execution IDs and independent final criteria. +A reader never becomes an execution task or a substitute validation trial. + +The grant yields only a private bounded evidence view. Original task owners, source state and +receipts remain; ordinary get/list/observe/act/resume access never expands. Granting or adopting +launches no helper and replays no input. Real source/child snapshots, original optional requests, +actual owners/reviewers, retired input and every live historical origin remain checked. New recorded +drafts retain both issuing and consuming session ceilings. Unavailable restrictions require actual +private completion renewal; matching hashes or caller-authored scope flags cannot replace it. +Read-only evidence adoption does not renew a published skill's original input authorization. + +At most sixteen real recovery links include source ancestry and the forward granted chain. Earliest +retained terminal evidence expires after thirty days; anchoring at a later reader cannot extend an +older ancestor. Same-writer post-insert and exact-retry checks honor revocation tombstones for both +DAG and task grants. Source/request/role/origin/revocation changes roll back grant creation, draft +recording or publication. Revoked IDs never reactivate. Historical get/list/revoke after an origin +expires expose bounded IDs and hashes, not continued completion or input authority. + +The Handoffs page explicitly selects original local DAG or original task when preparing JSON. +Three skill Actions prepare recording, publication or execution review with a handoff placeholder; +they do not issue consent or publish automatically. Python, AC, CLI, authenticated REST/MCP and +Builder share the same operations and actual caller identities. Editable requests are +`agent_task_handoff_review.json`, `agent_task_handoff_create.json`, `agent_skill_recording_handoff.json`, +`agent_skill_completion_handoff.json`, `agent_skill_execution_handoff_review.json` and +`agent_skill_execution_handoff_accept.json` under `examples/`. + +Cross-host handoffs, remote readers, actual application/device providers, deferred native +and twenty-four-hour acceptance, and unresolved HTTP409/bootstrap issues remain in `Progress.md`. + +Installed wheel and source distributions include the REST Dashboard and Swagger HTML, CSS and +JavaScript resources. The same localhost REST routes and authentication rules apply to an +installed package; serving static pages grants no task or desktop input authority. diff --git a/docs/guides/en/implementation-notes.md b/docs/guides/en/implementation-notes.md new file mode 100644 index 000000000..7f92512cf --- /dev/null +++ b/docs/guides/en/implementation-notes.md @@ -0,0 +1,658 @@ +# Implementation notes migrated from README + +Historical implementation notes preserved during the README reorganization on 2026-11-10. These entries describe different development stages and are not a current acceptance checklist. See [Progress](../../../Progress.md) and [updates](../../updates/README.md) for tracked status. + + +Transfer management now shares `manage_agent_transfer(operation, request)`, `AC_agent_transfer`, +`ac_agent_transfer`, authenticated `POST /agent/transfer`, and Script Builder metadata. The CLI uses +`agent-task transfer --operation review_export --request request.json`. Review returns an approval +token; creation requires that token, the original request key and an explicit note. Export/import +management and portable evidence management support registered hosts, with source-local authority checks. +The Transfers page exposes these operations through explicit Actions, editable JSON and four locales. +Review never sends approval; preparing approval preserves the original host, review token and request +key with an empty note. Changed selections and closed views reject late replies; accepted imports +remain service-owned. Routed evidence consent is persisted before forwarding; exact retries after lost +replies or a coordinator +restart reuse the same grant. Passive diagnostics describe only the local contract, not a live grant +or verified remote/native capability. Read-only completion grants revalidate their retained private +consent at creation and resolution, without reviving original input authority. +Implementation verification is recorded in docs/updates/README.md; remaining delivery and acceptance +are tracked in Progress.md. +Editable request templates are provided in examples/agent_transfer_export_review.json, +agent_transfer_import_review.json and agent_transfer_evidence_review.json, with separate create templates. + +Experimental source-host skill operations may select a portable grant with the existing +`handoff_id` and explicit completion/execution task. The source rechecks its actual consent, +recipient and private proof in the skill transaction, including after candidate/publication writes. +Original actions, the candidate's own validation trial and explicit version approval remain required. +New skill trials receive a fresh service-generated request key; legacy unkeyed trials are not backfilled. +Selected evidence retains the source host's actual actions, trials and versions under current authority. +Remaining cross-host acceptance and production delivery are tracked in Progress.md. +Runtime ownership is retained throughout the selected-evidence skill operation and released afterward. + +Destination import remains experimental. An explicitly started service accepts +`review_import` / `create_import` / `get_import` / `run_import` / `cancel_import` / `list_imports` +through its runtime transfer controller and authenticated `/agent/transfer` route. A coordinator can +route these finite operations through its own opaque consent token. The destination resolves the +source using its own registry and account; coordinator principals, origins and source credentials +are not forwarded. Approval commits before dispatch, and exact lost-ACK retries retain one import. +Startup resumes accepted never-claimed work and fences unsettled claims for review. Explicit +`run_import` rechecks the original recipient, profile, live origins and source grant under a new +queue generation. Verified private chunks can be reused; an owned complete generation is inspected +and hashed without downloading or publishing again. Additional attempt origins remain restrictive. +An explicitly queued, never-claimed inspection survives another restart; current bytes, profile +and retained attempt origins are rechecked before accepting its result. +Before accepting a published import receipt, the destination rechecks the complete file list +and content digests after its final source response. Changed, missing or extra files leave +the import in requires_review, preserving user edits and the original publication for review. +Changed ownership, bytes or authority cannot confirm publication. Cancellation fences the producer; +unaccepted publication remains requires_review, and confirmed published files remain user output. +Cancelled or expired private chunk accounts are cleaned only after their exact producer retires; +failed cleanup retains capacity until a confirmed retry. Receipts keep their original fixed expiry. +Staging directories and preallocated files are journaled by filesystem identity before bytes +are copied. Expiry retries their exact cleanup after the producer retires, including after restart; +replaced or unrecognized objects retain capacity for review and are never recursively deleted. +Source maintenance retires expired or revoked private export accounts, including after restart +or issuer removal. Failed cleanup retains its reservation. Runtime ownership remains held until +source or destination cleanup finishes; idle maintenance takes no runtime writer. +Create/run replies describe the committed receipt assembled before waking new delivery work; +a later get_import reads current progress. This avoids reading that receipt behind the new writer. +A later maintenance sweep prunes already-cleaned, revoked and expired source metadata to reclaim +its record quota, preserving consent/revocation tombstones and other record families. Cold runtime +maintenance discovers pending source records through a read-only probe; unused controllers stay lazy. +Final runtime owner release is serialized with lazy controller construction and rechecks any late +controller. Active construction or cleanup keeps ownership held for a later close attempt. +Redirected private cache paths are refused before storage opens; failed cleanup retains capacity. +Subsequent maintenance also prunes expired destination import/delivery metadata and its terminal queue +rows after confirmed private cleanup. Active, rebound or unknown queue work prevents pruning; original +consent/revocation tombstones and published user files remain. Cold maintenance performs this retirement +without a listener or producer. Cleanup scans held accounts independently of retained unexpired metadata. +Portable evidence retention and shared surfaces are implemented; remaining fault acceptance and delivery +are tracked in Progress.md. +Experimental source evidence now supports review_evidence/create_evidence/get_evidence/revoke_evidence/ +list_evidence through the owning runtime and authenticated local transfer route. Separate durable +consent reuses real recovery/completion proof, current accounts and original local DAG admission. +The registered peer evidence operation matches the actual accepted key/spec and optional DAG node; +it returns only IDs, hashes and finite verification, with evidence_only=true/input_authorized=false. +Review summaries omit the node request_digest; live resolution supplies it for the exact reviewed +accepted key. Source grants do not grant ordinary task reads or input. Selected source-owned skill evidence, routed management and shared public surfaces are implemented. +Remaining fault acceptance and production delivery are tracked in Progress.md. +Experimental coordinator continuation accepts a separately reviewed live remote recovery grant for +the exact original source/key/spec/graph/node and pinned host. Approval and start persist provisional +states, resolve again outside the coordinator writer, then recheck immutable local consent and claims +before activation. Stop cancels pending states; an interrupted provisional approval requires the same +explicit request. Runtime ownership remains held during confirmation without serializing peer readers. +Dependency checks repeat around claim/record and final remote adoption acceptance. A failed grant +fences scheduling and requests bounded pause only for independently matched accepted dependents; +unknown or lost acknowledgements retain claims and require review. Completed effects and unrelated +tasks remain intact. This does not certify native input retirement or complete the full fault matrix. +Legacy delivery-schema upgrade preserves the accepted origin and fixed expiry. Additional origins +remain cumulative across resumes. Stopping an attached REST observer leaves the same service-owned +delivery and runtime owner intact; reattachment reads its result without redispatch. +Actual two-host and separate-process three-host tests independently verify bytes and account scope. +Further restart/cancellation faults, further staging faults, full retention, portable evidence, +client/GUI surfaces and complete-stage verification remain in Progress.md. A receipt grants no +task-input authority or task-completion evidence. + +Registered source management now routes review/create/get/list/revoke through a coordinator-owned +opaque review. Consent binds the actual local caller, current host fingerprint, peer review, manifest +digest and original key. Approved intent commits before forwarding; lost replies and coordinator +restart retry the same source grant. Changed actor/host/token/note/key or a different reply manifest +is refused. Pending reviews and retained route records each cap at128; expiry removes only local +route metadata while preserving consent fences. Runtime closure discards unapproved cached reviews; +durable approvals remain recoverable. The source uses its own account, and local principal/ +origin headers stay local. Destination lifecycle, source-owned skill evidence and shared surfaces are implemented; remaining +acceptance and production delivery are tracked in Progress.md. + +Existing remote DAG calls now read the actual persisted host book when pinning a host and before +and after each retained connection call. Another process replacing/removing the endpoint or token, +damaged configuration or revoked captured local authority invalidates the operation. Reads neither +initialize nor quarantine the book; local service delegation and the closed remote routes stay compatible. + +Cross-host outcome handoff remains experimental and incomplete. The runtime-owned local source core reviews +selected completed file outcomes and commits consent-bound immutable blobs with actual issuer and +recipient checks. Authenticated source management and peer-read HTTP routes now expose those reviewed +manifests/chunks. Peer reads use the receiving server's ordinary bearer/RBAC gate and rate limits; +local principal/origin headers are refused before foreign principal/store lookup. The local service +client preserves real owner delegation for management only. Transfer requests are capped at1MiB before +server reads; the bounded client refuses oversized request dispatch and success/error reply decoding +without changing ordinary HTTP limits. Destination publication, live evidence adoption and shared public surfaces are implemented. +Remaining lifecycle acceptance and production delivery are tracked in Progress.md. A transfer receipt grants no task-input authority. + +Source export excludes actual runtime/transfer databases and sidecars, current source-owner and +issuer user stores, service-owned connection files and owned evidence directories before opening +selected bytes. The service registers its actual private files; ordinary same-named outputs remain +valid. Manifest checks apply to selected outputs. Peer reads and exact retries recheck current path +authority without rehashing historical user output, and path checks retain the operation deadline. +DAG artifacts follow at most sixteen real recovery links to the original submitted task, binding +actual accepted requests and local DAG admission. The admitting actor is reauthorized, and its actual +user store is private even when distinct from the source owner. Recovery children need no fabricated +submission row; genuine standalone sources need no DAG row. A private lineage digest is rechecked at +review, creation, exact retry and peer reads. Actual private recovery ownership/reviewer bindings +also join the digest and their user stores stay private. Source operations honor cooperative +cancellation around byte access and grant writes; a committed intent remains exactly recoverable +after a cancelled reply. Artifact expiry is its completed source updated+30days; retries/restarts do +not refresh it or substitute an older ancestor deadline. Real local renewed readers use their current +private completion authority while old input remains revoked. Cross-host commit races, automatic cleanup and destination lifecycle/evidence remain open. + +Runtime owns a TransferPeer through its actual batch host adapter. Registered transfer reads pin the +persisted endpoint/credential and reread the book before and after HTTP, with current local caller +checks. Source authentication uses the receiving host's own credential; local principal/origin headers +are absent. Actual configured credential-book paths stay private without initializing or reloading the +console. Closed manifests and canonical base64 chunks require matching export IDs/hashes, at most256KiB +per chunk and a fixed deadline. The1MiB transfer wire cap also applies behind URL path prefixes; +ordinary HTTP keeps its existing limit. Invalid numeric budgets, including oversized integers, fail +with typed errors before dispatch. Remaining cross-host fault acceptance and production delivery are tracked in Progress.md. + +Idle background workers check empty work queues without reserving a database writer, reducing +contention with task status and completion transactions. A nonempty hint still requires the original +transaction to recheck and claim the work. Claim generations, stale-work recovery and retry limits +remain enforced; task and transport deadlines are unchanged. + +Lease maintenance binds expiry/revocation stops to the actual input owner and generation in the +same stop transaction. A delayed watcher cannot rewrite retired recovery evidence or cancel a newer +lease. The accepted final state and cancellation token are set before the stop becomes visible; +current revocation and the original deadlines remain enforced. + +Stopped browser tasks with confirmed effects can now use the existing completion review and +skill workflow with their actual original WebRunner context. The owned worker permanently freezes +SDK input/network before its input journal and lease release; the runtime retains at most 16 +contexts for at most 300 absolute seconds, starting before detachment. Preview/new admission probe that exact effect task's live SDK view. +The verifier borrows it for fresh bounded DOM/value reads, without configure, input ACKs, transfers +or another browser/helper. Retirement, capability probes and cleanup deny nested tools and native input. +Same-profile tasks keep separate contexts. A saved context ID grants nothing. +Private completion authorization can explicitly renew the verification scope within the original +ceiling while the original input specification stays immutable. Expired input origins grant no reads; +bounded private custody alone is not authority. Removed owners, disabled targets, changed sources, +expiry and failed reads invalidate contexts. Confirmed process reaping is required to free ownership; +failed cleanup stays tracked. Restart cannot restore a page. Network-retired DOM is not new server data. +Existing Python/AC/MCP/REST/CLI/Builder and GUI Actions share the same review requests. Skill recording +keeps original actions; publication requires its own actual validation trial and selected completion. +See `examples/agent_browser_retained_completion.py`. Cold browser-prefix reconstruction, remote +readers, production deployment and deferred native/browser/device/24-hour acceptance remain open. + +Stopped tasks with confirmed effects can use `manage_agent_recovery("preview_completion", {"task_id": id})` +to review a separate verification task. Call `create_completion` with the exact task_id/snapshot and a +review note, then finish the returned task. A private atomic binding selects a permanently read-only +helper; source actions never replay and fresh independent criteria plus input retirement prove success. +Skill plans must be fully confirmed; dynamic tasks must have no dormant finite plan or unknown effects. +Observe may precede finish: identical helper configuration reruns readiness without replacing its authority. +Source/reviewer authority stays live, including after helper cleanup and across explicit retries/restarts. +Existing API/AC/MCP/REST/CLI/Builder and GUI Actions share the workflow. Remote readers and +production deployment remain in Progress.md; desktop capability still requires separate native evidence. + +Managed-only DAGs can register a durable whole-graph batch with +`manage_agent_dag("register", {"definition": graph, "max_parallel": 4})`, then explicitly call +`run_dag(graph, batch_id=batch["batch_id"])`. Registration performs no target operation. The stored +graph pins topology, node contracts, host configuration and parallelism; destination keys/spec tags +bind each node to that batch. A claim commits before possible delivery, and exact destination spec / +completion / input-retirement evidence gates dependants. Repeated begin is refused after success, +interruption or a lost submit reply. `get/list/inspect` retain coordination identity across restart. +Use API/AC/MCP/REST/CLI/Builder or the DAG Actions batch register/read controls and optional batch ID. +For a stopped batch, `review_continuation` returns a read-only whole-graph snapshot and explicit node +decisions. Pass its reviewed `snapshot`, `decisions` and a nonempty `note` through +`run_dag(graph, batch_id=id, recovery=request)` to approve and consume one continuation attempt. +Only independently completed originals or genuine completed recovery successors can be adopted; +dispatch requires a never-claimed pending node with no accepted destination request. Local authority +can be renewed within equal/narrower roots. Unknown claims are never replayed. DAG Actions exposes +fencing, review and explicit continuation; fencing stops new dispatch and leaves accepted tasks under +their own lifecycle. To delegate coordination to an explicitly started service, call +`manage_agent_dag("run_background", {"batch_id": id, "definition": graph, "max_parallel": 4})`. +Add `approval_id` for an explicitly approved continuation. DAG Actions exposes both background actions; +closing the view leaves accepted service work alive. `get.background` reports bounded queue state. +Restart fences old attempts and requires review, without replaying queued or unknown deliveries. +Both original owner and submitting actor remain live checks; local tasks use their owning runtime. +The existing `prune_agent_tasks()` and hourly maintenance also collect expired unused registrations +and settled successful batches (30 days by default). Unresolved batches retain task/recovery evidence +and admission gates. Results add `deleted_batches` and `deleted_dag_deliveries`; foreign queues and +user outputs remain untouched. Remote evidence retention still requires an explicit handoff contract. +Caller-coordinated bound runs pin the local service path, endpoint, credential fingerprint and generation. +All local node calls reuse that client; replaced metadata stops future calls and requires explicit review. +Server-side batch evidence reads its owning runtime directly. No bearer credential is cached by binding. +Ordinary non-batch clients retain adaptive discovery; bound batches require generation-bearing metadata. +Local batch nodes now use the source service's closed `local_task` transport after a durable claim. +The exact spec/key is admitted as the original owner, with the real caller recorded atomically. Runtime +checks refresh both identities and the live attempt before input; losing admin authority over another +owner's work also blocks execution. Existing requests without this trusted admission are never backfilled. +Task metadata exposes bounded `local_dag_admission` audit data; accepted input retains its cleanup contract. +For a reviewed recovery successor that must remain readable to its original owner, pass +`owner_policy="source_owner"` to recovery preview/review_authorization, then carry its +`ownership.review` as `ownership_review` into explicit create/create_authorized. The child retains the +source owner and records the real reviewer atomically; both identities remain live input checks. +The recovery GUI offers this owner selection. Omitted policy keeps caller ownership and ordinary read +isolation. DAGs can adopt an independently completed source-owned child through normal recovery evidence. +Existing caller-owned children are not automatically transferred or backfilled into this policy. +See [the continuation protocol](../../source/Eng/doc/ai_agents/agent_dag_batches_doc.rst). + +Triggers can explicitly use `manage_agent_trigger("review_authorization", {"trigger_id":"..."})`, +then `create_authorized` with `trigger_id`, `snapshot`, `authorization_review`, reviewed `spec` and `note`. +The new registration preserves its full template/config/pending limit within original/live/current +authority, retires the old binding atomically and enables future notifications. Shared lineage history +keeps accepted keys and outstanding tasks across renewal, removal and restart; inherited queued events +are never redispatched. Schedule windows restart in the future and file checkpoints remain. API/AC/MCP/ +REST/CLI/Builder and the GUI trigger selector share this explicit flow; ordinary enable cannot replace +expired authority. Review only prepares a request with a blank note. + +Published skills can use `manage_agent_skill("review_authorization", {"candidate_id":"..."})`, +then explicit `create_authorized` with `candidate_id`, `snapshot`, `authorization_review`, reviewed +`spec` and `note`. Renewal preserves the whole plan/parameter schema and source root ceiling, retaining +live restrictions and intersecting current authority. It creates an audited draft in the same skill +lineage; fresh validation and explicit next-version publication are required. Old versions remain +unchanged. Identical approval deduplicates; stale versions/context fail. API/AC/MCP/REST/CLI/Builder and +the GUI Skills operation selector share this flow. Trigger renewal uses the separate flow above. + +Stopped tasks with retired origin authority can explicitly use `review_authorization`, then +`create_authorized` with `task_id`, `snapshot`, reviewed `spec`, `note` and `authorization_review`. +The successor retains every live source restriction and intersects current authority with the original +root ceiling; roots may only stay equal or shrink. Other permissions, mode/model, budgets and completion +conditions stay fixed. Approval is audited atomically with the unique successor; the source and its +revoked witnesses stay unchanged. All recovery surfaces include these operations, with separate GUI +Actions for authorization review and creation. See the [recovery guide](../../source/Eng/doc/ai_agents/agent_recovery_doc.rst). +Task recovery does not clear input quarantine or restore application state; skills and triggers use their separate renewal flows above. + +Stopped tasks can use `manage_agent_recovery("preview", {"task_id": "..."})` to review source +receipts and a source snapshot without touching an application. Finite skills expose remaining actions +and row outcomes. External-agent and local-model tasks provide `review_template` with a blank goal; +operators must explicitly supply a remaining-work goal, with no copied action list. Explicit `create` approval +supplies the snapshot, reviewed spec and note, creating one linked successor with fresh observations +and receipts. Repeated approval returns that task. Execution mode, model/endpoint, scope, budgets and +completion conditions stay fixed, and unknown effects require reconciliation. Old captures, indexes, +coordinates and completed history are not transplanted. Use `AC_agent_task_recovery`, MCP/REST, +`agent-task recovery preview|create request.json` or Agent tasks → Actions → Review remaining work / +replan / Create reviewed successor task. Delegated sources cannot resume; continue from the successor. +Login and window-state restoration is declared, never inferred: a successor (or any task) may list +`resume_conditions` — `screen`, `browser` or `file_*` clauses only, since receipts are history — and its +first action is admitted only on a fresh observation that passes all of them. A failed or unknown +condition puts the task in `waiting_user` instead of acting; once any action receipt exists the gate is spent. + +Built-in Android/iOS managed profiles remain unavailable. Their internal remote-effect guard records +before/after acknowledgements against a physical-device identity and retains quarantine when a local +helper exits with an unconfirmed effect. Recovery requires a trusted device proof after writer retirement +and a later epoch invalidating old commands. No built-in SDK proof, device profile or native acceptance +is implied; remaining integration is in `Progress.md`. +The internal Android transport connects only to an explicit existing loopback ADB server, with no CLI, +daemon management, retry or legacy-shell fallback. Shell-v2 exit evidence has bounded framing/output; +it does not establish app completion, physical-device identity or input retirement. +Internal Android sessions now inspect an exact endpoint, validate physical serial/boot/default-display +focus and pin one boot atomically. Finite input proposals recheck identity and focus on the selected +command connection, with literal bounded text and fixed results. Proposals grant no input authority; +input-window, occlusion, lock/presence and owned-worker integration remain required. +Android checked proposals now bind current native input-window/queue and keyguard evidence. Pointer +checks cover entire half-open touch-region paths and foreign interception/overlays; hashes are rechecked +on the command connection. Old ANR/history cannot certify current state. Human presence and global-monitor +review still require trusted providers; built-in managed device execution remains unavailable. +Internal Android action protocol v2 distinguishes complete pre-input refusal from input failure, +post-input refusal and returned input. Missing/malformed phases or mismatched shell exits remain unknown; +even returned input does not certify remote input retirement or task completion. No retry is authorized. +The internal owned remote SDK worker now checks exact task/owner scope, refreshed authority and physical +takeover; parent monitoring starts before the trusted host factory. Calls require a durable begin ACK, +then matching device/epoch settlement before an end ACK. Missing proof keeps effects quarantined. +Trusted device-control providers, the WDA adapter and managed profile wiring remain required. +The command compiler reads the three native focus fields in one labeled extraction, accepting their +six possible orders while refusing missing/duplicate/empty fields. Pre/post identity and input-security +checks remain, and action deadlines are unchanged. Owned POSIX fixtures avoid extra Git Bash reader +processes without changing file bytes; bounded phase/timing diagnostics exclude commands and output. +Internal AndroidRemoteAdapter now connects checked sessions to this worker through explicit per-command +AndroidCommandLease grants. A fresh identity/routing/security observation is consumed per action; the SDK +recompiles the finite command before sending it once over ADB. Device fencing must suppress old writes +after physical takeover, cancellation or expiry. No default provider exists: standard ADB and killing +the local helper cannot supply that guarantee. Settlement additionally binds one random request ID and +boot to independent input/queue proof. An optional explicit host hierarchy_reader supplies bounded +app-only semantic elements and reviewed non-sensitive text; without it observations remain metadata-only. +XML cannot grant text access; editable/password values and protected descendants stay masked. Raw XML +and private freshness hashes are never published; random observation revisions change after actions and +source changes. Android element references require a current actionable semantic element. Fresh screen +readback can confirm a reviewed positive label; missing/partial/masked content cannot prove text absent. +No CLI/SDK startup or capture fallback is added. Real capture/control providers, protected field-value +verification, Unicode/IME and managed profile delivery remain open. + +Managed screen completion now treats built-in desktop and WebRunner previews as partial text evidence. +File targets and desktop window bootstrap supply no semantic screen evidence. Known safe labels can +confirm presence or contradict absence; masked and explicitly hidden labels cannot. Combined conditions +remain unknown if any required evidence is missing, or fail on a known contradiction. Use explicit +browser completion reads for exact DOM/value checks. Custom targets without coverage flags keep legacy behavior. + +`lookup_agent_task("key", reviewed_spec)` optionally compares the destination-normalized specification +with the immutable digest stored for the original owner's request. The response advertises +`spec_match_contract=1` and reports `spec_match=matches|differs|unverifiable|not_found` when a spec is supplied. +CLI lookup accepts `--spec reviewed.json`; AC/MCP/REST/Builder share the optional object. Inspection first +queries the key, then compares the reviewed node spec only when the destination advertises the exact +contract. Old destinations stay `unverified`; local origin witnesses are never sent to remote matching. +Changed request identity invalidates the earlier snapshot. Matched nodes also require the exact count, +kinds and passed status of independent criterion reports before confirming recorded completion. +`request_match` binds the node's task spec; +DAG topology/batch approval and continuation remain separate, with `resume_permitted=false`. + +`inspect_agent_dag(definition, timeout_seconds=30)` looks up existing local/registered-host requests +without submitting, pausing or resuming tasks. Use `AC_agent_dag_inspect`, MCP `ac_agent_dag_inspect`, +REST action execution, CLI `agent-task inspect-dag reviewed.json`, Script Builder or DAG Actions. +At most 100 nodes and a 300-second maximum budget bound inspection. Remote lookup needs host-management +authority; local principal/store/origin metadata stays local. Results omit remote paths and raw errors. +`recorded_completion` describes the found task only. Node-spec matching is optional; `resume_permitted=false` +explicitly leaves graph/batch approval and continuation unapproved. A missing record +does not prove rejection. GUI inspection is read-only and discards results after graph edits. + +Use `lookup_agent_task("original-key")` (`AC_agent_task_lookup`, MCP `ac_agent_task_lookup`, +`POST /agent/lookup`, CLI `agent-task lookup original-key`, or the task view's Actions menu) to inspect +a submission whose reply was lost. It reads only the original principal/store namespace and never +submits, resumes or acquires input. `found=false` is a current snapshot; a late request may still arrive. +GUI lookup results cannot replace a task/key selected while the request was pending. DAG inspection +shares this lookup; specification-bound recovery approval remains separate work. The query requires task access. + +Existing `run_dag` / `AC_run_dag` / MCP `ac_run_dag`, REST action execution, CLI action files, +Script Builder and the DAG Actions menu accept nodes with a `task` payload instead of actions: + +DAG types and functions are also exported from `je_auto_control.api` and `je_auto_control.api.core`. + +```python +run_dag({"nodes": [{"id": "collect", "host": "reviewed-host", "task": { + "spec": reviewed_spec, "idempotency_key": "batch-20261024-collect", "wait_seconds": 300}}]}) +``` + +`reviewed_spec` must use skill or an explicitly configured local-model mode, with tools, destination +roots and completion criteria. The host must already expose an authenticated agent runtime with +background dispatch; this does not deploy listeners. Omit `host` for the explicit local service. +The destination validates scope and coordinates resource ownership. Nodes submit once, poll bounded +status and advance only with matching passed criteria, durable completion contract 1 and confirmed input +retirement. Keys are required and must stay stable when recovering the same reviewed batch; rerunning +does not resume paused tasks or replay effects. Stop, timeout or transport/authority failure requests +bounded pause when the task ID is known. A lost acknowledgement stays uncertain; failed nodes retain +the task ID/key and block dependants. The GUI displays retained task IDs. Remote credentials come from +the administrator's registered host; local principal/store paths and origin witnesses stay local. +Production multi-host setup and native/device acceptance remain separately tracked. + +Managed HTTP pause/cancel/stop-all/shutdown requests have a separate per-IP reserve with the same +120-per-minute rate and 30-request burst as ordinary traffic, so polling cannot exhaust stop admission. +Authentication, live roles, task ownership, audit and bounded input retirement still apply. The shared +client also reserves transport capacity for DAG batch/node pauses; its control marker admits only closed +pause requests on `/agent/dag`. Other marked DAG operations fail before dispatch. Custom auth gates +retain their own admission contract. This does not guarantee priority over a saturated OS/network. + +Managed task success is published after input cleanup is confirmed. If cleanup fails or remains busy, +the task requires review and keeps its input lease; a crash before confirmation remains recoverable. +Completion uses conditional state transitions so concurrent cancellation retains priority. Status and +the existing GUI/API task results expose `metadata.input_released` and durable `completion_contract=1` +for newly confirmed success (legacy records retain zero); final artifacts reflect the settled +state. This supplies local retirement evidence for subsequent DAG coordination. + +DAG nodes retain the caller's authorization, cancellation and command ceilings on pool threads, +including custom runners. Each node refreshes store-backed users before execution; removed users fail +that node and dependent nodes are skipped. Individual operations check the refreshed role. Default +remote nodes require `manage_hosts` before opening the host address book or action files, because +registered host credentials may grant more access than local action permissions. Trusted local Python +and administrators retain remote dispatch. Managed task nodes add the closed lifecycle described above; +production multi-host deployment and native acceptance remain separate work. + +Browser host profiles can select a reviewed installed Python environment through optional +`settings.helper_python` (an absolute local interpreter path). Explicit helpers run with `-I`, using +installed packages rather than the caller's `PYTHONPATH` or working directory. Virtualenv executable +symlinks retain their environment identity. Task options cannot select the interpreter. +Host managers can call `manage_agent_target("probe", {"name":"reviewed-browser"})` or use +`AC_agent_target`, MCP/REST, `agent-task target probe request.json` and the GUI Host targets operation. +The probe uses a separate bounded owned helper, imports browser dependencies through `je_web_runner`, +then retires it without acquiring input ownership or starting a browser. Its result can say +`python_dependencies_ready`; `browser_launch=not_probed` and `native_evidence=not_recorded` stay explicit. +`last_probe` is an in-memory timestamped diagnostic snapshot; passive readiness and task permissions +are unchanged by probing. Disabled targets stay disabled. Desktop/device native probes remain open. +The prepared isolated environment installs wheels from both feature worktrees. Shared environments +and production checkouts remain untouched; production service configuration and real-browser acceptance +remain separate work. Browser automation still belongs entirely to WebRunner (`je_web_runner`). + +Desktop finite skills now use the same context-continuity fence as browser skills. Retiring a +desktop scope or its owned helper requires review before an old prefix can continue; paused form/window +state is not established by historical receipts. Live uninterrupted contexts continue normally. File +adapters retain their persistent-artifact recovery. Target checks run before helper replacement, and +existing resume/status/receipt interfaces expose the human-review result. Draft/authentication/window +state restoration and reviewed remaining-step reconstruction remain open; native acceptance stays paused. + +A finite browser skill's verified prefix now requires its original live browser/helper context. +After pause, cleanup, helper loss or runtime restart, retained action history cannot prove that the +form still contains its previous values. Continuation enters human review before launching a replacement +helper or sending the next action. Review the remaining steps and create a new task explicitly. +Pausing before any retained attempt and attempts reviewed as failed/not-applied permit a fresh start. +External owners can reobserve a new context and plan fresh scoped actions; ordinary uninterrupted skills +continue on their existing session. Restoring authenticated/draft browser state remains open work. + +Local runtime principal and live-root forwarding now requires an explicit local-service call. +Generic authenticated HTTP requests carry the supplied bearer token; local user/store/witness metadata +is attached only by the runtime client after validating the loopback service destination and route. +The versioned `je_auto_control.api` namespace exposes every advertised `api.core` name, including +managed browser commands, target recovery and skills. Executor typing stubs include all shipped commands; +unresolved postponed project types use the generator's existing `Any` fallback instead of invalid names. +Concurrent budget readers sample clocks inside the exclusive database transaction, preventing false +task timeouts when readers acquire locks in a different order. Actual clock rollback remains fail-closed. +GUI/MCP/REST/CLI share these repaired client and API contracts. Production checkouts and existing +native/browser/device/24-hour acceptance pauses remain unchanged. + +Managed browser file commands `browser_link`, `browser_download` and `browser_upload` (with matching +`AC_browser_*` commands) delegate to WebRunner transfer contract version 1. Download and upload grants +require explicit host/task roots. Downloads preserve scoped browser cookies inside the owned SDK/helper, +check complete length and optional SHA256, and publish without overwriting an existing file; reuse +requires its matching SHA256. Uploads read one regular file up to 4 MiB into a checked immutable snapshot, +verify optional SHA256 and SDK metadata, and never submit a form. Network operations remain in `je_web_runner`. +The browser `download_archive` preview accepts a query `url`, explicit `allowed_origins`, rooted `directory` +and `files` with a plain `name` and either `url` or link `selector`/optional `frame`; `page_url` can override +the query page per file. It captures fresh links, downloads at most 16 MiB per file and writes a manifest +whose names/sizes/hashes are independently verified. GUI Actions draft file target/workflow/upload examples +without starting resources. MCP/REST/CLI/Builder/model tools share these commands; link reads still require +drive-input authority. Deployment and real-browser acceptance remain open; existing acceptance pauses hold. + +Browser tasks accept pinned completion clauses such as +`{"kind":"browser","operation":"value","selector":"#field","value":"expected"}`. +Operations are exact `text`, `value`, `visible` (boolean), or `url` (no locator). They require an explicit +`AC_browser_read` grant and task origins; completion cannot add permissions. At finish, the same owned +helper checks a current allowed HTTP(S) page and independently reads the full SDK value through guarded +read commands. Receipts, bounded previews and model stop messages do not substitute for those reads. +Blank/unavailable/out-of-scope pages, refused readbacks and invalid verifier replies remain unknown; +failed comparisons remain failed. Cancellation, authority revocation and human-review errors propagate. +GUI Actions can draft an inert browser completion example; API/MCP/REST/CLI finish share the verifier. +SPA URL fragments remain intact while origin checks exclude only the fragment. Browser/native +application acceptance and reviewed transfers remain open. + +Managed browser startup now requires the exact WebRunner `ManagedBrowserSession.contract_version == 1` +contract before constructing its policy or opening a proxy/browser. Missing, boolean, string, older or +unknown markers fail with an actionable readiness reason. SDK source `575e5d2` provides complete text/value +readback: at most 8,000 UTF-16 code units, with over-limit/invalid Unicode refusal instead of truncation. +AutoControl applies matching Unicode bounds to browser arguments and workflow preview data before effects. +The consumer/SDK source contract is tested through the real owned helper with fake Chromium; deployment +and real-browser/native acceptance remain separate from that evidence. + + +`draft_agent_workflow("batch_form", config)` and `transfer` accept `backend: browser` with +explicit `allowed_origins` and a reviewed browser target. CSV/XLSX sources stay rooted; browser drafts +emit only `AC_browser_*` actions and never fall back to desktop input. Forms take `url`, CSS `fields`, +optional frame selectors/new-record control, and submit plus confirmation selectors. Each fill has an +independent exact value readback. Optional `confirmation_column` supplies a per-row expected marker. +Transfers take `source_url`/`destination_url`, capture text/value fields, apply an allowlisted transform, +fill and read back destination fields, then verify saving. A stale confirmation is refused before submit. +`AC_browser_wait` / `browser_wait` polls text/value reads only, including a newly visible element; +`wait_seconds` defaults to 5, is capped by the action budget, and late matching replies are refused. +It never repeats a fill or click. Python/core, catalog/model schemas, MCP, CLI/REST task operations, +Builder and GUI workflow preview use the shared compiler. Browser readback can serve as independent +skill evidence. Actual application acceptance and production upload/download configuration remain open. +Managed browser startup requires WebRunner contract version 1 with complete bounded readback. + +Managed browser profiles (`kind: browser`) now delegate to the owned `je_web_runner` SDK from +WebRunner (`D:\Codes\WebRunner`; integration source on its isolated managed-session branch). +Profiles require exact `settings.allowed_origins`, browser-only tools and no desktop apps; every task +also declares a narrower nonempty `options.allowed_origins`. Profile/task grants are checked again on +activation. Registration stays inert. Install the reviewed managed-session SDK and its Chromium runtime +in the helper environment explicitly; absent dependencies fail readiness and nothing is installed automatically. +`AC_browser_navigate`, `AC_browser_click`, `AC_browser_fill`, `AC_browser_select`, `AC_browser_check` +and `AC_browser_read` share Python/core, executor, MCP and Builder schemas. They operate inside the +managed helper; drive them through the existing task submit/observe/act lifecycle, not an ambient browser. +The read operation is `text`, `value` or `visible`; secret form controls are refused by WebRunner. +Observation-local DOM indexes resolve selectors and frames after the runtime's freshness check. +Failed effects remain uncertain and require reconciliation; pause/cancel retire owned resources. +GUI Actions can draft a browser target example for review, and DOM selection only edits the action request. +The dedicated helper preserves one fresh session across readiness checks. Ordinary cleanup acknowledges +browser cleanup and reaps its owned process tree; eligible completion sources instead transfer their +actual frozen context to the bounded runtime collection. Browser tasks acquire no desktop input ownership. +Controlled cross-source tests use the real SDK with fake Chromium and owned IPC/loopback. Browser/native +acceptance, production transfer configuration and additional browser workflow kinds remain tracked in `Progress.md`. + +MCP asynchronous calls preserve the accepting caller's role, session, exact root policy and +disclosure view; retired sessions and path policies reject late dispatch. Stateless async calls keep +their fixed profile. HTTP tool-list changes reach all live session streams for plugin updates, while +session enable/disable targets one owner and avoids duplicate delivery. Stream registration and HTTP +headers share one lock so an early notification cannot precede the response headers. +The metadata-only `benchmarks/mcp_discovery.py --repeats 20` benchmark records count, JSON bytes, +warm in-process handshake, search and enable latency. The captured Windows/Python 3.14.4 run has +732 permitted tools / 358,029 initial response bytes in full mode and 5 / 2,029 in progressive mode +(99.43% fewer response bytes). Handshake is 58.263 / 47.439 ms; search median is 16.243 / 19.718 ms. +Progressive enable median is 42.486 ms. These local timings exclude cold imports and native work. +See the dated JSON report under `docs/benchmarks/`; argument-policy coverage limits remain in `Progress.md`. + +MCP supports opt-in session disclosure: `je_auto_control_mcp --tool-mode progressive` starts +with five discovery controls; `ac_mcp_tools_enable` / `ac_mcp_tools_disable` change only that session. +`--tool-mode static --tool-profile ac_screen_size,ac_list_windows` supplies a fixed profile for clients +that do not refresh tool lists. The default `full` mode retains its unpaginated permitted list. +Progressive/static pages use opaque, single-use cursors bound to a snapshot and caller; changed tools, +roles, view configuration or expired cursors require restarting `tools/list`. Enable/disable notify +the owning connection. Session closure retires outstanding metadata callbacks and clears cursors. +Use `MCPServer.configure_tool_disclosure(...)` for HTTP/embedded servers, or host environment +`JE_AUTOCONTROL_MCP_DISCLOSURE` and comma-separated `JE_AUTOCONTROL_MCP_TOOL_PROFILE`. +`plan_mcp_tool_profile(...)` and Diagnostics Actions preview startup arguments without starting a server. +Stateless requests use a fixed, unpaginated initial profile; they do not retain session enablement. +Read-only ceilings cover later plugin registrations. Unauthenticated/shared-token peers see operator +tools, matching their existing invocation ceiling; host-management tools require authenticated authority. + +MCP tool discovery is available through `search_mcp_tools(query, limit=10)` and +`get_mcp_tool_schema(name)`, corresponding AC/MCP commands, and Diagnostics → Actions. +Search returns bounded summaries with category and required capability; full schemas require a +single-tool lookup. Both queries refresh role authority and respect the registry's read-only filter. +MCP queries use that server's live registry, including plugin changes. CLI inspection: +`je_auto_control_mcp --search-tools document --limit 5` or `--tool-schema ac_mcp_tool_search`. +Full mode remains the default; opt-in session disclosure is described alongside this metadata API. + +Agent tool calls use `executor.execute_one(name, arguments)`, returning the raw result through +the same authorization, variable interpolation, cancellation and journal boundaries as action scripts. +Private executor arguments are rejected. Managed task delivery is tracked in `Progress.md`. + +Crash-safe input ownership uses a durable resource witness before dispatch/input ACK. After host death, explicitly review and recover the target with `recover_agent_target(target, note)` (host management), after manually releasing held input; task receipts still require separate reconciliation. Workspace document handoff runs outside the disposable input helper, and approved focus steps wait for the scoped application window. + +Managed skills record verified semantic flows into immutable candidates. `manage_agent_skill` previews typed parameters, runs a separate validation task, and publishes a numbered version only after explicit review of that candidate's verified success. Repairs are new selector candidates with fresh validation; tasks pin their version and digest. AC/MCP/REST/CLI and the Agent Tasks Actions menu share these operations. + +For an interrupted validation trial whose actions are all confirmed, explicitly review/create and +finish a separate read-only completion task, then call `manage_agent_skill("accept", {...})` with the +original `task_id` and optional `completion_task_id`. Publication retains the exact candidate/trial +hash/pin, up to sixteen real read-only recovery links, fresh authority and independently verified +retirement. The original stays stopped; its actions are not replayed. The Actions menu can prepare +the request for review. Publication keeps historical completion IDs/hashes after transient reader +evidence expires; unpublished adoption still needs retained evidence. + +`manage_agent_skill("record", request)` also accepts `completion_task_id` for a stopped original +workflow. Keep `task_id` equal to that workflow: its confirmed semantic actions become a draft, +while the separate reader supplies private, independently verified completion evidence. Recording +does not replay actions or change the source state. Source/proof checks and draft insertion share +one transaction with live authority rechecks. Historical `provenance.completion_review` survives +reader retention without granting current authority. The draft, including added validation criteria, +still needs its own new exact validation trial before publication. The Actions menu prepares the +record request without executing it. + +For a partially executed validation trial, first call `manage_agent_skill("review_execution", request)` +with `candidate_id`, the original `task_id` and a separate final `execution_task_id`. Then explicitly +`accept` those same IDs with the returned `execution_review`, `expected_version` and a nonempty `note`. +At most sixteen actual executable recovery links must confirm the complete original semantic plan; +a successful different remainder is insufficient. Comparison includes JSON types, captured values, +expectations and grounding, without restoring captures or rebuilding historical UI state. Each task +retains its existing limits and separate approval. Current callers, all owners and actual admission +reviewers must remain authorized. Version, publication and historical `publication.execution_review` +commit atomically, with post-write evidence/authority checks. The original stays stopped and retains +`publication.task_id`; no recovery child becomes a fabricated validation trial. An optional +`completion_task_id` must verify the final executable effect and is nested in this execution audit. +Expired evidence cannot approve an unpublished candidate. Two Actions examples prepare review and +accept requests without executing them; `agent_skill_execution_review.json` and +`agent_skill_execution_accept.json` are editable request examples. + +Managed tasks retain live origin path ceilings: removing a source root blocks later actions, trigger fires and skill trials. MCP client roots are isolated per session; retiring that client authority revokes its ceilings. Static host policy remains valid until explicitly replaced. Worker shutdown cancels actual running work, including model initialization before input acquisition, while unstarted deliveries remain durable. + +Experimental [managed agent tasks](../../AGENT_TASKS.md) provide owner-scoped submit/observe/act/verify, +pause/resume/cancel, fenced target control, durable action receipts, WorkQueue delivery, local Ollama +inference and a background service shared by Python, AC, MCP, REST, CLI and the Agent Tasks view. +Start explicitly with `je_auto_control agent-task start`; new flows have no mandatory external service. +Four reviewable templates cover download/archive, CSV/XLSX forms, cross-app transfer and workspace +preparation. Use `agent-task draft` or Actions → Preview workflow before submitting. +Durable interval/cron/file/event bindings capture approved task scopes, reauthorize each fire and +deduplicate notifications. Submission keys prevent duplicate tasks across retries and restart. +Owner-scoped receipts and explicit uncertain-outcome review link to run history, journals and task +reports. Generated cache expires after 30 days; user outputs and external journals are preserved. +Evidence caches bind the complete database path and a persistent database identity under +`.agent-evidence-cache/`. Restored databases and legacy caches retain their original history references; +the next action or report starts a new owned journal segment without reading or moving historical files. +Task metadata reports `artifact_cache_state` as `owned` or `historical`. Retention removes only the current +database's recognized cache files; historical files remain, and retained private roots cannot be exported. + +On Linux, helper processes can run under the optional [owner service](../../../native/owner_service/README.md). +A root guardian runs each helper in its own cgroup v2 tree, which the helper's account cannot leave. +Closing the channel kills the whole tree, escaped descendants included, and a restarted guardian +recovers after a crash. A root-owned `/etc/je_auto_control/owner_service.json` binding routes +exactly listed helper argv through it. Helpers that drive your desktop or browser always run as +local processes, because a protected helper runs as its own ID with an empty environment and +cannot reach your display. Without that binding, helpers keep running as local +processes, and `agent-task status` reports the mode under `helper_containment`. The Python +package never builds, installs or starts the service, and its builds refuse protected launches +until a reviewed release opens the gate. + +`agent-task readiness` (`agent_runtime_readiness`, `AC_agent_runtime_readiness`, the MCP tool and the +Agent Tasks view's Actions menu) reports, for the desktop input and capture, the human-presence source, +Android and iOS control, the browser and the local model, one of `unsupported`, `missing_dependency`, +`unauthorized`, `not_probed`, `not_recorded` or `measured`. It reads only the environment, `PATH` and +installed packages: it contacts no device, launches no helper and asks for no permission, so it never +reports `measured` and every area carries `native_evidence: not_recorded`. An installed tool is +`not_probed`, not ready. + +Before deployment or rollback, compare exact source and artifact hashes; the unchanged version number alone does +not identify private-cache compatibility. A runtime without this private-root protection must not reuse the +newer database/cache. A reviewed restore must use matching pre-upgrade state at its recorded locations, retire +owned input first, and exclude retained newer private files from every legacy task root. Preserve uncertain +journals and avoid replay. Keep the compatible runtime if these conditions cannot be established. + +Windows USB enumeration emits and decodes UTF-8 explicitly and keeps its PowerShell process hidden. +Unicode device names and diagnostics are preserved in both Python UTF-8 modes; enumeration remains read-only. +Native calls use an owned helper with cancellation/deadlines, recorded input cleanup and per-session +exclusion across runtime databases. Windows shared-desktop tasks share a persistent session source across +runtime/task/helper lifetimes and wait for sixty seconds of fresh unlocked inactivity after monitoring starts. +Only an active supported local console can acquire input; remote, shadowed and unknown sessions fail closed. +Each helper freshly checks its fixed host lease before and after input ACK. Source/reader loss pauses input; +unconfirmed held-input cleanup stays fenced for explicit retry. Closing one runtime preserves another's source. +Target descriptions expose coarse `presence` metadata with `native_evidence=not_recorded` and start no probes. +`agent-task stop-all` stops visible tasks. Other shared desktops require a trusted activity adapter. +Native acceptance and the remaining workflows are in `Progress.md`. + +Linux's internal presence_peer_linux retains a noninheritable pidfd for the original connected +Unix stream or sequenced-packet peer. It checks account, birth, namespaces and liveness without +reopening a PID. This process identity does not establish desktop or input authority. + +The internal LinuxListener and LinuxChannel transport owns its protected Unix endpoint, socket +and peer. Each bounded JSON packet requires the live original writer's kernel credentials and +pidfd. Extra, missing, negative or truncated descriptor controls are refused; received descriptors +retire before delivery. Admission and I/O share one deadline. Cancellation revokes delivery, and +unfinished or failed cleanup stays unconfirmed. Unknown filesystem objects remain untouched. +Pathname permissions do not isolate hostile processes sharing a UID. Bounded userspace waits +do not promise hard realtime kernel syscall completion. + +Physical-activity sources now exist for X11 and macOS. X11 counts XInput2 raw events from real +devices, never from XTEST slaves, and reads `Active`/`LockedHint` from logind: without logind or +`XDG_SESSION_ID` the seat counts as locked. macOS uses a listen-only session event tap (it needs the +Accessibility permission). An event counts as injected only when a process posted it from a non-HID +source state, so a doubt keeps a task waiting rather than letting it take over. Wayland has no +trusted source. On Linux the presence broker, worker and server now run over this transport: the owned +worker binds a fresh private endpoint and reports it in its bootstrap reply, the broker adopts only that +endpoint, and connecting pins the listener to the process it names before the presence challenge. macOS has +no presence transport yet, and the runtime still refuses non-Windows shared desktop tasks until native +acceptance. This transport is not full Linux application or native input acceptance. + +[![PyPI](https://img.shields.io/pypi/v/je_auto_control)](https://pypi.org/project/je_auto_control/) +[![Python](https://img.shields.io/pypi/pyversions/je_auto_control)](https://pypi.org/project/je_auto_control/) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../../LICENSE) +[![Documentation](https://readthedocs.org/projects/autocontrol/badge/?version=latest)](https://autocontrol.readthedocs.io/en/latest/?badge=latest) + +**AutoControl** is an open-source, cross-platform **computer-use and GUI automation framework** for AI agents, Python applications, and automated testing. It drives the mouse and keyboard, finds UI targets through template matching, OCR, the OS accessibility tree, or a vision model, records and replays flows, and runs deterministic JSON actions across Windows, macOS, Linux (X11 and Wayland), the BSDs, Android, and iOS. + +Every capability ships three ways: a **Python API**, an **`AC_*` action command** usable +from JSON files / CLI / servers, and a **GUI tab**. Nothing is GUI-only. + +**[繁體中文](../../../README/README_zh-TW.md)** · **[简体中文](../../../README/README_zh-CN.md)** + +--- diff --git a/docs/guides/en/integrations.md b/docs/guides/en/integrations.md new file mode 100644 index 000000000..a41c30cec --- /dev/null +++ b/docs/guides/en/integrations.md @@ -0,0 +1,130 @@ +# Agents and integrations + +[README](../../../README.md) · [Documentation](../../README.md) + +## AI agents and computer use + +**AutoControl is an open-source, cross-platform computer-use and GUI automation framework for AI agents.** + +Use it when an agent needs to operate a real desktop GUI — native applications, real browser windows, remote desktops, or mobile devices — rather than only a browser DOM/API. + +### When an AI agent should choose AutoControl + +- Real mouse and keyboard input +- Screenshots and screen-coordinate interaction +- OCR and native accessibility-tree discovery +- Image/template matching +- Vision-language-model UI localization +- Anchor and self-healing locators +- Cross-platform desktop/mobile automation +- Deterministic JSON action files +- MCP-based computer use + +A robust agent loop is: + +**observe → identify → act → wait → verify → recover** + +The repository also has a dedicated [AI agent guide](../../../AI.md) with MCP configuration, tool selection, OpenAI integration, security guidance, and searchable computer-use terminology. + +### AI-friendly MCP + +Start the stdio server with: + +```bash +pip install je_auto_control +je_auto_control_mcp +``` + +The MCP server exposes the canonical `ac_*` surface plus short, model-friendly aliases such as `click`, `type`, `screenshot`, `find_text`, `click_text`, `drag`, `focus_window`, and `wait_image`. + +For inspection-only clients: + +```bash +je_auto_control_mcp --read-only +``` + +If a client needs only canonical `ac_*` names: + +```bash +JE_AUTOCONTROL_MCP_ALIASES=0 je_auto_control_mcp +``` + +For OpenAI agent integrations, expose a focused allow-list with `export_openai_tools(only=[...])` instead of passing the complete AutoControl command catalogue. This both fits provider limits and reduces the authority given to the model. + +### Project identity + +**Project:** AutoControl
+**Repository:** `Integration-Automation/AutoControlGUI`
+**Python package / PyPI:** `je_auto_control`
+**MCP command:** `je_auto_control_mcp` + + +--- + + +## Servers and integrations + +| Surface | Start it with | Notes | +|---|---|---| +| **MCP server** | `je_auto_control_mcp` (stdio) or `AC_start_mcp_http_server` | 820 tools for Claude Desktop / Claude Code / custom tool loops: the full `ac_*` surface plus short model-friendly aliases for common GUI actions. Speaks the stateless MCP 2026-07-28 beside the `initialize`-based revisions. Bearer auth, TLS, audit log, rate limit, plugin hot-reload, CI fake backend. | +| **REST API** | `je_auto_control start-rest` | Bearer token, per-IP rate limit + lockout, SQLite audit hook, `/metrics`, `/openapi.json`, `/docs` Swagger UI, `/dashboard`. | +| **TCP socket server** | `je_auto_control start-server` | Newline-framed JSON action lists. Binds `127.0.0.1` by default. | +| **pytest plugin** | installed automatically | Fixtures plus a Gherkin step library for pytest-bdd / behave. | +| **Language server** | `python -m autocontrol_lsp.server` | Completion and diagnostics for `AC_*` action JSON, generated from the live command table. | +| **Remote desktop** | `RemoteDesktopHost` / GUI | TCP, WebSocket, or WebRTC; TOTP, trust list, TURN config, file/clipboard/audio sync. | + +All servers bind to `127.0.0.1` unless you opt in explicitly. + +The MCP window-state tools `ac_window_minimize`, `ac_window_maximize` and `ac_window_restore` return the window handle on accepted requests and `isError: true` on backend refusal (including a stale handle or rejected activation). Raw Win32 `ShowWindow` previous visibility is normalized by the backend. + +**Package gate.** `AC_add_package_to_executor` and `AC_add_package_to_callback_executor` import a Python package and register its members as commands, so an action list arriving over any of these surfaces could load `os` or `subprocess`. No package loads unless it has been allowed: a package that is not on the allowlist is refused before it is imported, and that action fails with `AutoControlExecuteActionException`. Allow packages (submodules included) from Python with `executor.allow_packages("name", …)`, for every entry point — both CLIs, the socket / REST / MCP servers and the scheduler — with the `JE_AUTOCONTROL_ALLOWED_PACKAGES` environment variable (comma-separated names, read when the process starts), or for one CLI run with `je_auto_control run script.json --allow-package NAME` (repeatable). `executor.set_allow_arbitrary_packages(True)` opens the gate for every package, which is what earlier releases did by default (with a `DeprecationWarning`). None of these is an `AC_*` command, so an action list cannot open its own gate. + +**Opt-in hardening.** Each of these is off until configured, and a server without them behaves as before. `JE_AUTOCONTROL_RBAC_USERS=` makes the REST API and the MCP HTTP transport resolve the bearer token to a user and authorise each route, tool and privileged `AC_*` command by role (viewer / operator / admin); the shared token is then refused. `JE_AUTOCONTROL_MCP_PATH_ROOTS` (directories separated by the OS path separator) confines every MCP tool argument that is a file path to those directories, `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT=1` adds the client's `roots/list`, and `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` limits which `env://` names `ac_resolve_ref` may read. `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` makes an endpoint verify Ed25519-signed action files without being able to sign them (`create_signing_keypair`; the private key stays on the signing machine). A remote-desktop viewer writes files pushed by a host only below `~/Downloads/AutoControl` (`JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR`); that one is on by default. + +The REST GUI shows RBAC mode and disables the shared-token field while a user store is active. `rest_api_registry.status()` includes `rbac_enabled` and returns `token: null` in that mode; use an individual user token. Custom REST gates that only implement `check()` remain supported in shared-token mode; RBAC requires an authenticated user context and refuses an identityless success. + +RBAC viewers do not receive the named sensitive-read tools, even when their MCP `readOnlyHint` is true: clipboard/history, local document/data/SQL and dotenv reads, reference resolution, credential generation, persistent store readers, outbound checks, microphone capture and external VLM requests require operator/admin. Assertion containers also require operator because their specs can read those resources. Screen observation and pure input parsing keep their existing classification. `ac_realize_item`, `ac_idempotency_begin` and `ac_rate_limit` change state and are excluded from `--read-only` mode. + +Delayed interval/cron jobs, triggers, hotkeys, watchdog rules, webhooks, e-mail triggers and observer callbacks retain their registrant’s identity. Store-backed users and roles are checked again on dispatch; deleted users, unavailable stores and viewers cannot execute deferred work. Starting a daemon does not transfer its registrations to the starter. Ownership metadata retains no RBAC bearer token; explicit Python `AuthorizationContext` values without `store_path` keep their captured role, and work registered outside RBAC clears worker identity. Observer/watchdog callbacks get fresh variable scopes, and failed watchdog actions do not count as dismissed popups. Nested callbacks retain the caller’s failure count; a webhook with a revoked owner returns HTTP 403 and `fired: false`. + +### How the remote-desktop wire protocol works + +TCP hosts release a rejected authentication attempt’s client slot before sending `AUTH_FAIL`. A viewer can retry immediately, including after a bad token, wrong handshake message or denied approval, while socket cleanup/logging finishes. Pending handshakes retain their independent resource bound. + +Worth knowing before you expose a host, and described nowhere else in the +docs. The default transport is length-prefixed framing over raw TCP — no extra +dependencies — and it opens with an **HMAC-SHA256 challenge/response +handshake**: a viewer that fails auth is dropped before it is sent a single +frame. JPEG frames are encoded at the configured FPS and quality and handed to +authenticated viewers through a shared *latest-frame slot*, so a slow viewer +drops frames instead of stalling the rest. Viewer input arrives as JSON and is +**validated against an allow-list** of actions before being applied through the +ordinary input wrappers, so a viewer cannot invent new operations. + +```python +# Be remoted — start a host and hand the token + port to whoever views you +from je_auto_control import RemoteDesktopHost +host = RemoteDesktopHost(token="hunter2", bind="127.0.0.1", + port=0, fps=10, quality=70) +host.start() +print("listening on", host.port, "viewers:", host.connected_clients) +``` + +```python +# Control another machine — connect a viewer and send input +from je_auto_control import RemoteDesktopViewer +viewer = RemoteDesktopViewer(host="10.0.0.5", port=51234, token="hunter2", + on_frame=lambda jpeg: ...) +viewer.connect() +viewer.send_input({"action": "mouse_move", "x": 100, "y": 200}) +viewer.disconnect() +``` + +Narrow who may connect at all with an IP allow-list (CIDR ranges or exact +addresses); peers outside it are rejected during the handshake: + +```python +RemoteDesktopHost(token="tok", ip_allowlist=["10.0.0.0/8", "192.168.1.100"]) +``` + +--- diff --git a/docs/guides/en/setup.md b/docs/guides/en/setup.md new file mode 100644 index 000000000..334ab0130 --- /dev/null +++ b/docs/guides/en/setup.md @@ -0,0 +1,355 @@ +# Installation and configuration + +[README](../../../README.md) · [Documentation](../../README.md) + +## Installation + +```bash +pip install je_auto_control # core +pip install je_auto_control[gui] # + PySide6 desktop app +``` + +Optional extras, installed only when you need them: + +| Extra | Enables | +|---|---| +| `gui` | PySide6 desktop application (51 tabs): a searchable navigation panel (`Ctrl+K`) lists every feature by category, tabs are built the first time they are opened, and **View → Theme** switches dark / light. Pages scroll in narrow windows; theme, text size, navigation visibility (`Ctrl+B`) and width are saved in `~/.je_auto_control/gui.ini` on close. Themes use Qt directly; `qt-material` is not required. | +| `webrtc` | WebRTC remote desktop, USB passthrough (`aiortc`, `av`) | +| `signaling` | Standalone signaling / rendezvous server (`fastapi`, `uvicorn`) | +| `discovery` | mDNS / Zeroconf LAN host discovery | +| `pdf` / `office` | PDF and Excel / Word / PowerPoint reading | +| `fuzzy` / `locale` | `rapidfuzz` matching, `babel` locale parsing | +| `s3` / `audio` | S3 artifact store, system volume control | + +Closing a factory-built feature with the tab cross releases its widget, subscriptions and timers on the next Qt event-loop turn; reopening starts a new panel. **View → Tabs** and the embedding `hide_tab` API only hide it and preserve state. `tab_registry.open/close` and `close_tab` expose explicit lifecycle operations. Legacy owner-built forms and Remote Desktop remain reusable on close while their lifecycle migration is pending. + +**Windows on arm64** installs and runs, minus what upstream cannot ship +there: neither `opencv-python` nor `cryptography` publishes a `win_arm64` +wheel. So `find_image*`, `screenshot()` (the OpenCV/BGR one — the Pillow +capture still works), the secret vault, action-file encryption, ACME/TLS +and encrypted recording each raise a message naming the missing wheel +instead of failing obscurely. Mouse, keyboard, screen size, window +management, the accessibility tree, the action executor, the MCP/REST/TCP +servers and the GUI all work — measured, not assumed. Every other platform +is unaffected. + +**Requirements:** Python ≥ 3.11. On Linux, install build +prerequisites first: + +```bash +sudo apt-get install cmake libssl-dev +``` + +OCR, VLM, and LLM backends (`pytesseract`, `easyocr`, `paddleocr`, `anthropic`, +`openai`) are loaded on demand — install whichever you actually use. For Tesseract, +`find_tesseract_cmd()` locates the executable (`$TESSERACT_CMD`, then `PATH`, then the +installers' default folders), `set_tessdata_dir()` points it at a language-data folder, +and `ocr_status()` / `ocr_languages()` say what is missing before the first OCR call. + +**Log file:** the library logs to `~/.je_auto_control/logs/AutoControlGUI.log`, +created on the first record (importing alone writes nothing) and shared by every +process on the account (appended to, one process id per line, moved to `.1` +past 10 MB). Set `JE_AUTOCONTROL_LOG_FILE` to write elsewhere, or to +`os.devnull` to turn the file off. + +--- + +## Platform support + +| Platform | Backend | Input | Screen capture | Recording | Window management | +|---|---|:---:|:---:|:---:|:---:| +| Windows 10 / 11 | Win32 ctypes (+ optional Interception driver) | ✅ | ✅ | ✅ | ✅ | +| macOS 10.15+ | pyobjc / Quartz | ✅ | ✅ | ✅¹ | ✅ | +| Linux X11 | python-Xlib (+ optional `uinput`) | ✅ | ✅ | ✅ | ✅ | +| Linux Wayland | libei via the desktop portal, or ydotool / wtype + a capture tool | ✅ | ✅ | ❌ | ❌ | +| FreeBSD / OpenBSD / NetBSD | python-Xlib, the same X11 backend as Linux | ✅² | ⚠️² | ✅² | ✅² | +| Android | adb + uiautomator2 | ✅ | ✅ | — | — | +| iOS | WebDriverAgent / facebook-wda | ✅ | ✅ | — | — | + +¹ macOS recording captures through a Quartz event tap and needs +**Accessibility** permission (System Settings → Privacy & Security → +Accessibility). Without it recording raises and names the permission +rather than returning an empty session. + +² The BSDs run the X11 backend unchanged — the same X server, the same +`python-Xlib`, which is the only dependency input, recording and window +management have. A `freebsd` CI job drives real input on a real FreeBSD 14 and +reads it back off the X server; OpenBSD and NetBSD take the same code path but +have no CI runner. Screen capture is the exception, and the reason is +packaging rather than the platform: it goes through Pillow/mss and OpenCV, and +`opencv-python`, `pillow` and `cryptography` publish no FreeBSD wheels. Build +those from ports and capture, image matching, OCR and action encryption work +too — `import je_auto_control` no longer requires any of them. + +Wayland key/button/pointer input in `auto` mode uses CLI when the optional native +backend is absent. Once a portal request starts, refusal, timeout, handshake +failure, device pause or revocation stops input; it never silently switches +providers. Repeated refused calls retain inert failure state without reopening +consent. `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND=libei` requires native input; +`=cli` explicitly selects CLI. After resolving permission, an explicit +`je_auto_control.linux_wayland.libei.reset_default_backend()` allows a fresh +request. Interrupted native chords attempt all owned key releases on the same +backend and preserve the original cancellation. This does not change the +explicit wtype text path or screen-capture selection. + +The `ydotool` fallback needs **ydotool 1.0 or newer**. Every argument +AutoControl builds arrived in that release; 0.1.x — which is what Debian +bookworm and every current Ubuntu still ship under that name, and Debian +trixie ships not at all — answers the same arguments with exit code 0 and no +events. AutoControl detects it and refuses rather than reporting success for +input it never sent. Arch, Fedora and Debian unstable package 1.0. + +That fallback also positions the pointer accurately **only where the +compositor's pointer acceleration is off**. `ydotool mousemove --absolute` +sends no absolute event: it drives the cursor into the corner the compositor +clamps to and then moves relative to it, so the compositor accelerates the +move — measured against a real wlroots session, libinput's default profile +travels exactly twice the distance asked for. ydotool's own `--help` says the +same; AutoControl logs it once per process rather than mispositioning in +silence. Turn acceleration off for the ydotoold device (sway: `input +type:pointer accel_profile flat` and `pointer_accel 0`), or install +`liboeffis` so the libei path — absolute at the protocol level — is used. + +The factor is the compositor's own setting and no client can read it back, so +only you know whether it is off. `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL=flat` +says it is, and moves silently; `=strict` refuses the move rather than let a +click land somewhere else; leaving it unset keeps the warn-and-move default. + +Wayland screen capture needs the tool your compositor supports, because no +single one covers them all: `grim` on wlroots compositors (sway, Hyprland, +river), `gnome-screenshot` on GNOME, `spectacle` on KDE. Install one and every +capture path — screenshots, image and anchor locators, OCR, screen recording, +remote desktop — goes through it. With none installed, a session bus is +enough: the built-in D-Bus client tries `xdg-desktop-portal` last, though it may ask for consent the +first time. Failing that, capture fails loudly with an install hint rather than +returning the blank XWayland root. The `screen_capture` check in +`je_auto_control.api.run_diagnostics()` (and the GUI Diagnostics tab) reports +which tier is in use. + +A native Wayland pointer coordinate outside every granted EIS region, after +raw-coordinate and layout-origin mapping, raises `LibeiUnavailable` with +`state="failed"` and disables automatic CLI fallback. A rejected move emits +no motion/frame or subsequent click. Valid coordinates, devices without +regions, later valid requests on the same sender and explicit CLI selection +retain their existing behavior. + +Passive **input/capture capabilities** use `BackendContext`, `CapabilityStatus`, +`CapabilitySnapshot` and `probe_capabilities` from `je_auto_control.api` (also +exported at the package root). Call +`probe_capabilities(BackendContext.current()).to_dict()`, use no-argument +`AC_probe_capabilities` / read-only `ac_probe_capabilities`, or choose +**Diagnostics → Actions → Inspect input and capture capabilities**. Builder +provides the same no-argument command. `python -m examples.capabilities` prints +live prerequisites and a deterministic XWayland scope example without desktop operations. + +Input describes key/pointer events; the existing wtype text path is separate. +The probe reads environment/PATH and nonblocking cached native state; it never +loads optional native libraries, connects, polls events, captures or requests +permission. Installed tools or a bus address mean `unverified`, not readiness. +Cached libei readiness requires a completed handshake and active keyboard, +absolute pointer, button and scroll families. A partial grant remains +unverified; paused families and removed required devices report paused/revoked. +The eight states are `available`, `unverified`, `needs_permission`, +`needs_dependency`, `unsupported`, `paused`, `revoked` and `failed`. +`available` is only the last local observation and may be stale; every real +operation rechecks authority. XWayland always has `desktop_wide=False` and cannot +cover native Wayland windows. Other scope flags remain subject to granted +regions/permissions and do not verify every monitor. + +Contexts detach environment/executable facts and may carry an owner's inert +input/capture observations. They grant no authority. Default live results omit +environment values, command arguments, executable paths and native error text; +AC/MCP accept no supplied observations. Explicit CLI configuration remains +distinct from automatic fallback after observed optional native absence; +permission/pause/revocation/failure metadata cannot imply CLI fallback. +Capture helper and portal selection are diagnosed independently. Rendering and +language changes reuse the snapshot without probing. Native portal restore, +compositor restart, capture-result/context integration and native session +controls remain in `Progress.md`. + +The GUI task infrastructure provides `gui.task_controller.TaskController`: +`submit(work, owner=widget)` returns a caller-owned `TaskHandle` with +typed `TaskOutcome` and `TaskProgress` observations. Work receives a +Qt-free `CancellationToken` with checkpoints, bounded interruptible waits +and progress reporting. Submission captures context; dispatch refreshes +store-backed identity. Work must receive plain data, avoid widget references +and authorize its own operation. Existing +`DeferredAuthorization.scope()` still requires input privilege, while +`context_scope()` only refreshes/binds identity for independently authorized work. + +Owner/handle/controller destruction requests cooperative stop and drops +late delivery. Each task has a separate ID/token; callbacks run on the GUI +thread. Cancellation does not forcibly interrupt an uncooperative call +or relabel a successful committed return. Errors/progress use the captured +secret scope; terminal errors retain no exception traceback. Failed thread +starts roll back both registries and preserve the original failure. +Diagnostics now adopts this controller. Remaining panel/backend migrations +and native session operations stay in `Progress.md`. + +Active **Diagnostics → Actions → Run diagnostics** uses the shared task +controller off the GUI thread. **Stop diagnostics** requests cooperative stop; +the view distinguishes running, stopping, canceled and failed states in four +languages. Progress counts completed checks. Duplicate runs are ignored, close +abandons late progress/results, and a deliberate retry starts a new owned run. +GUI cancellation is a typed outcome without retained exception tracebacks; +headless core/SDK/CLI and the MCP handler preserve original direct/wrapped controls. +Ordinary probe failures still become report rows and allow remaining checks. + +`CancellationToken`, `TaskProgress` and `cancellation_scope` are exported by both +SDK namespaces. Bind `with cancellation_scope(token): report = run_diagnostics()`; +the owning caller can call `token.cancel()` from another thread. The existing +no-argument diagnostics signature remains. Scope binding grants no authority; +`cancellation_scope(None)` only suspends cancellation for bounded owned cleanup. +`AC_diagnose` and the new read-only `ac_diagnose` share the report. The MCP tool +accepts no arguments, uses request cancellation/progress and requires +`read_screen`, as does the explicit GUI action. Caller-supplied tokens or +authority metadata are rejected. These are active checks: capture may request +consent. `ac_probe_capabilities` remains the separate passive alternative. + +Scoped Wayland D-Bus connect/read/partial-write waits poll at intervals capped +at 0.1s within the original total deadline. Cancellation attempts Request.Close +on the originating bus with its separate 0.25s budget, then releases that +connection; a canceled returned image is discarded. Scoped CLI captures stop +and reap their newly owned helper/process group with bounded cleanup, preserving +the original control even if pipe close fails; reaped numeric PIDs are never +signaled. liboeffis acquisition observes scoped stop and releases its own context. +Uncooperative/native calls are not forcibly preempted; the GUI remains responsive +while cleanup completes. Restore/restart, native session controls, capture-owner +metadata and remaining panel/backend migrations stay in `Progress.md`. + +`python -m examples.cancellable_diagnostics` runs a controlled cancellation demo +without providers. `--active --cancel-after 2` explicitly runs diagnostics and +requests stop after two seconds; native/device/API acceptance remains separate. + +Opening Diagnostics displays a localized not-run state and performs no checks. +Choose **Actions → Run diagnostics** to start the existing active checks, which +can capture the screen or require portal consent. Changing the display language +does not start checks. The explicit `run_diagnostics`, `AC_diagnose` and MCP +diagnostic calls retain their active behavior. Passive capability inspection is a separate action below. + +Abandoned screenshot portal requests attempt `Request.Close` on the originating +bus before disconnect, using a separate 0.25-second D-Bus I/O budget. A returned +alternate handle is followed; after an uncertain method reply, the predicted +handle is used. Completed responses are not closed again. Ordinary cleanup +errors do not replace the primary capture failure; original cancellation and +hard-control objects survive wrappers and cleanup. D-Bus writes and reply waits +share the call budget, connection setup has an explicit timeout, and interrupted +connect/authentication/Hello releases its owned descriptor even when `__enter__` +fails. Actual compositor/dialog cancellation remains platform acceptance work. + +One Wayland-only difference to plan around: **a capture may contain the mouse +cursor.** Nothing here asks for it, but wlroots composites a *software* cursor +into the output buffer whenever the backend has no cursor plane — which +includes any session run with `WLR_NO_HARDWARE_CURSORS=1` — and that buffer is +what screen capture hands back. Windows and X11 never include the pointer, so a +locator, a template match or an OCR read can find a pointer-shaped hole in the +middle of its target here and nowhere else. Wayland does not let a client read +the cursor position, so there is nothing to reliably mask or move around it: +park the pointer away from what you are about to capture. The `screen_capture` +check reports this as `cursor_may_be_captured`. + +For a setup none of that fits, name your own command — it wins over every +detected tool, and `{output}` is replaced with a temporary PNG path: + +```bash +export JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND="mycapture --png {output}" +``` + +Wayland forbids global input recording for unprivileged clients — set +`JE_AUTOCONTROL_LINUX_DISPLAY_SERVER=x11` to record on an X11 session. Window +management works on Windows, macOS (pyobjc) and X11, including XWayland; on a pure +Wayland session, whose protocol hides other clients' windows, `list_windows()` returns +an empty list and every window action raises `AutoControlUnsupportedOperationException` +saying why. Opt-in driver-level backends (`JE_AUTOCONTROL_WIN32_BACKEND=interception`, +`JE_AUTOCONTROL_LINUX_BACKEND=uinput`, ViGEm virtual gamepad) exist for apps that +ignore synthetic input, and fall back silently when the driver is absent. + +--- + +## Configuration + +Every environment variable AutoControl reads. Nothing here is required: with no variable set, AutoControl picks the platform backend by itself, servers bind `127.0.0.1`, and every opt-in feature (signature enforcement, RBAC, USB passthrough, tool-path roots) is off. The [configuration reference](https://autocontrol.readthedocs.io/en/latest/Eng/doc/configuration/configuration_doc.html) ([source](../../source/Eng/doc/configuration/configuration_doc.rst)) has the accepted values in full and links each variable to the page that explains the feature; CI compares it, and the tables below, with the code. + +### Platform backends + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_WIN32_BACKEND` | `sendinput` | `interception` sends keyboard and mouse through the Interception driver; falls back to `SendInput` with a warning when the driver or DLL is missing. | +| `JE_AUTOCONTROL_LINUX_BACKEND` | `x11` | `uinput` writes kernel input events; falls back to XTest with a warning when `/dev/uinput` is not writable. | +| `JE_AUTOCONTROL_LINUX_DISPLAY_SERVER` | `auto` | Which Linux backend loads: `auto` reads `XDG_SESSION_TYPE` and `WAYLAND_DISPLAY`; `wayland` or `x11` forces one (`x11` on a Wayland session drives XWayland windows only). | + +### Windows Interception driver + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_INTERCEPTION_DLL` | unset: `PATH`, then next to the package | Full path of `interception.dll`. | +| `JE_AUTOCONTROL_INTERCEPTION_KEYBOARD` | `1` | Interception device id (`1`–`10`) keyboard events are sent to. | +| `JE_AUTOCONTROL_INTERCEPTION_MOUSE` | `11` | Interception device id (`11`–`20`) mouse events are sent to. | + +### Wayland + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND` | `auto` | `cli` sends input through `ydotool` and never asks the desktop portal. Chosen before starting: after a refused consent AutoControl does not switch to it by itself. | +| `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL` | `warn` | Absolute moves on the `ydotool` path only (relative motion the compositor accelerates): `warn` warns once and moves, `flat` declares acceleration off and moves silently, `strict` refuses the move. | +| `JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND` | unset | Your own screenshot command line, with `{output}` where the PNG path goes. Takes precedence over `grim`, `gnome-screenshot`, `spectacle` and the portal. | +| `JE_AUTOCONTROL_WAYLAND_RECORD_DEVICES` | unset: none | Comma-separated `/dev/input/event*` devices `PhysicalRecorder` may read; physical recording is opt-in per device. | + +### MCP server + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_MCP_READONLY` | unset | `1`: only tools marked read-only are offered and callable. | +| `JE_AUTOCONTROL_MCP_TOOL_PROFILE` | unset | Comma-separated tool names and `category:` entries of the `static` profile. | +| `JE_AUTOCONTROL_MCP_ALIASES` | `1` | `0` leaves out the short aliases (`click`, `screenshot`, …) registered beside the `ac_*` tools. | +| `JE_AUTOCONTROL_MCP_TOKEN` | unset | Bearer token of the HTTP transport. Not accepted once RBAC is on. | +| `JE_AUTOCONTROL_MCP_ALLOWED_ORIGINS` | unset: loopback origins only | Comma-separated extra browser origins (exact, e.g. `https://example.test:8443`) the HTTP transport accepts. | +| `JE_AUTOCONTROL_MCP_CONFIRM_DESTRUCTIVE` | unset | `1`: destructive tools ask the client for confirmation (MCP elicitation) before they run. | +| `JE_AUTOCONTROL_MCP_PATH_ROOTS` | unset: no confinement | Directories (separated by the OS path separator) every file argument of a tool must stay inside. | +| `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` | unset | `1`: also accept the roots the MCP client reports through `roots/list`. | +| `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` | unset: no restriction | Comma-separated environment variable names (`fnmatch` patterns allowed) `ac_resolve_ref` may read; a value that names nothing allows none. | +| `JE_AUTOCONTROL_MCP_AUDIT` | unset | Path of a JSON-lines file that receives one record per `tools/call`. | +| `JE_AUTOCONTROL_MCP_ERROR_SHOTS` | unset | Directory a screenshot is saved to each time a tool fails. | +| `JE_AUTOCONTROL_FAKE_BACKEND` | unset | `1`: the MCP server records mouse, keyboard and clipboard calls in memory instead of performing them, for CI without a display. | + +### REST / RBAC and chat-ops + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_RBAC_USERS` | unset: shared token | Path of the user store file. Setting it is what switches roles on for the REST API and the MCP HTTP transport. | +| `JE_AUTOCONTROL_CHATOPS_SCRIPT_ROOT` | unset: `run` is refused | The only directory the chat-ops `run` command may load action files from. | + +### Executing and signing action files + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_ALLOWED_PACKAGES` | unset: none | Comma-separated packages `AC_add_package_to_executor` may load (submodules included), for every entry point. Read once, when the process starts. | +| `JE_AUTOCONTROL_REQUIRE_SIGNED_ACTIONS` | unset | `1`: every path that runs an action file refuses one without a valid signature sidecar. | +| `JE_AUTOCONTROL_ACTION_SIGNING_PRIVATE_KEY` | unset | Path of the Ed25519 private key (PEM). Set it on the signing machine only; signing then writes a version-2 sidecar. | +| `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` | unset | Path of the matching public key. Set it on every machine that executes: it verifies and cannot sign. | +| `JE_AUTOCONTROL_ACTION_SIGNING_PASSPHRASE` | unset | Passphrase of the private key, when it was created with one. | +| `JE_AUTOCONTROL_ACCEPT_LEGACY_ACTION_SIGNATURES` | unset | `1` is migration mode: once a public key is configured, HMAC sidecars written before version 2 are refused unless this is set. Switch it off again when every file has been re-signed. | + +### Remote desktop and signaling + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR` | `~/Downloads/AutoControl` | Directory a remote-desktop viewer stores files its host sends in. A received path is confined to it. | +| `JE_AUTOCONTROL_USB_PASSTHROUGH` | unset | `1` enables USB passthrough opcodes on the remote-desktop channel. | +| `AC_SIGNALING_SECRET` | unset | Shared secret of the signaling / config-sync server (`X-Signaling-Secret`). Read by the server when `--shared-secret` is not given. | + +### GUI + +| Variable | Default | Effect | +|---|---|---| + +### Logging, data and testing + +| Variable | Default | Effect | +|---|---|---| +| `JE_AUTOCONTROL_LOG_FILE` | `~/.je_auto_control/logs/AutoControlGUI.log` | Where the log file is written. The null device (`/dev/null`, `NUL`) switches the file off. Read when the first record is written, not at import. | +| `JE_AUTOCONTROL_ENV` | `default` | The active environment of the asset store (`active_environment()`), so one script reads different values in `dev` and `prod`. | +| `JE_AUTOCONTROL_REDACTION` | `off` | Default screenshot redaction policy: `off`, `moderate` or `strict`. An unknown name is an error, not `off`. | +| `JE_AUTOCONTROL_PYTEST_ARTIFACTS` | `./autocontrol_screenshots` | Directory the pytest plugin writes failure screenshots to when a test did not request the `autocontrol_screenshot_dir` fixture. | + +--- diff --git a/docs/guides/en/usage.md b/docs/guides/en/usage.md new file mode 100644 index 000000000..850906a88 --- /dev/null +++ b/docs/guides/en/usage.md @@ -0,0 +1,216 @@ +# Automation usage + +[README](../../../README.md) · [Documentation](../../README.md) + +## Why AutoControl + +- **One API, seven platforms.** `wrapper/platform_wrapper.py` picks the backend at import + time; your script does not change between Windows, macOS, X11, and Wayland. +- **Scriptable without Python.** 911 `AC_*` commands cover the whole feature set, so a + JSON file can do anything the library can — including loops, branches, try/catch, + macros, and variables. +- **Headless by default.** `import je_auto_control` never loads Qt. The GUI is an + optional extra that wraps the same headless core. + Public exports load their source modules when requested. `__all__` and `dir()` list names + without loading every feature; wildcard import requests them all. Unresolved names are absent + from `vars(je_auto_control)`. + On X11, plain package import opens no display or input device and starts no keyboard listener. + Desktop operations acquire resources when called. Reading `keyboard_keys_table` or calling + `get_keyboard_keys_table()` resolves actual server keycodes and requires an X connection. +- **Locate things four ways.** Template matching, OCR, the accessibility tree, and a + vision-language model — composable through anchor locators and self-healing fallbacks. +- **Light dependency floor.** The REST server, JSON Schema validator, JWT, TOTP, + WebSocket framing, ACME client, USB/IP protocol, and Prometheus metrics are all + standard-library implementations. Heavy things are opt-in extras. + + +## Choosing the right automation layer + +AutoControl is not intended to replace every automation tool. Use the smallest layer that matches the interface: + +| Need | Good fit | +|---|---| +| Stable browser DOM/API automation | Playwright / Selenium | +| Simple Python mouse and keyboard scripting | PyAutoGUI or AutoControl | +| Native desktop application automation | **AutoControl** | +| Accessibility-tree GUI automation | **AutoControl** | +| OCR-driven GUI automation | **AutoControl** | +| Screenshot / vision-model GUI localization | **AutoControl** | +| Self-healing cross-platform GUI locators | **AutoControl** | +| AI agent controlling a real desktop | **AutoControl + MCP** | +| Deterministic JSON GUI workflows | **AutoControl** | + +The differentiator is the combination of **real computer input + semantic/visual discovery + self-healing + agent/MCP integration** behind one cross-platform automation surface. + + +## 60-second quick start + +**1. As a Python library** + +```python +import je_auto_control as ac + +ac.set_mouse_position(500, 300) +ac.click_mouse("mouse_left") +ac.write("Hello World") +ac.hotkey(["ctrl_l", "s"]) + +x, y = ac.locate_image_center("save_button.png", detect_threshold=0.9) +ac.click_text("Submit") # OCR +ac.click_accessibility_element(name="OK") # accessibility tree +ac.click_by_description("the green Submit button") # vision model +ac.screenshot("shot.png", screen_region=[0, 0, 800, 600]) +``` + +**2. As a JSON action file** — `flow.json` + +```json +[ + ["AC_set_var", {"name": "user", "value": "alice"}], + ["AC_locate_and_click", {"image": "login.png", "mouse_keycode": "mouse_left"}], + ["AC_write", {"write_string": "${user}"}], + ["AC_retry", {"max_attempts": 3, "body": [ + ["AC_wait_text", {"target": "Welcome", "timeout": 10}] + ]}], + ["AC_assert_text", {"text": "Welcome"}], + ["AC_generate_html_report", {"html_name": "report"}] +] +``` + +```bash +je_auto_control run flow.json --var user=bob +je_auto_control run flow.json --dry-run # list the steps without touching the mouse +``` + +**3. As a desktop app** + +```bash +pip install je_auto_control[gui] +python -c "import je_auto_control; je_auto_control.start_autocontrol_gui()" +``` + +Record a flow, edit it in the visual Script Builder, and save it as the same JSON +format the CLI runs. (`python -m je_auto_control` is the legacy action-file runner — `-e`, `-d`, +`-c`, `--execute_str` — not the GUI.) + +--- + +## Capability overview + +Every row works headlessly. "GUI tab" is where the same feature surfaces in the +desktop app; tab commands live in the window's **Actions** menu. + +| Capability | Python API | `AC_*` command | GUI tab | +|---|---|---|---| +| Mouse | `click_mouse` (`clicks=2` double-clicks), `set_mouse_position`, `mouse_scroll`, `tween_drag` / `drag_path` (paced by `step_delay_s`, `settle_s`) | `AC_click_mouse`, `AC_tween_drag`, `AC_drag_path` | Auto Click | +| Keyboard | `write`, `write_secret`, `hotkey`, `type_keyboard`, `keyboard_key_name` (code → canonical name; Windows also takes aliases such as `ctrl`, `esc`, `enter`) | `AC_write`, `AC_write_secret`, `AC_hotkey` | Auto Click | +| Screen & pixels | `screenshot`, `screen_size`, `get_pixel` | `AC_screenshot` | Screenshot | +| Image matching | `locate_image_center`, `locate_and_click` | `AC_locate_and_click` | Image Detect | +| OCR text | `click_text`, `wait_for_text`, `read_text_in_region`, `ocr_status` | `AC_click_text`, `AC_wait_text`, `AC_ocr_status` | OCR Reader | +| Accessibility tree | `find_accessibility_element`, `click_accessibility_element` | `AC_a11y_find`, `AC_a11y_click` | Accessibility | +| Vision-model locator | `locate_by_description`, `click_by_description` | `AC_vlm_locate`, `AC_vlm_click` | VLM | +| Anchor locator | — | `AC_anchor_click`, `AC_anchor_locate` | — | +| Self-healing locators | `self_heal_run`, `self_heal_locate`, `self_heal_click` | `AC_self_heal_click` | Self-Healing | +| Natural-language planner | `plan_actions`, `run_from_description` | `AC_llm_plan` | LLM Planner | +| Computer-use agent | `AgentLoop`, `run_agent` | `AC_run_agent` | Computer Use | +| Record & replay | `record`, `stop_record` | `AC_record`, `AC_stop_record` | Record | +| JSON scripting | `execute_action`, `execute_files` | all 911 commands | Script, Script Builder | +| Variables & flow control | `execute_action_with_vars` | `AC_set_var`, `AC_loop`, `AC_for_each`, `AC_try`, `AC_retry` | Variables | +| Data-driven runs | — | `AC_for_each_row` (CSV / JSON / SQLite / Excel) | Data Sources | +| Assertions | `assert_text`, `assert_image` | `AC_assert_text` + 20 more | Assertions | +| Test suites | `run_suite` | `AC_run_suite` | Test Suites | +| Scheduler (interval + cron) | `default_scheduler` | — | Scheduler | +| Global hotkeys | `default_hotkey_daemon` | — | Hotkeys | +| Event triggers | `default_trigger_engine` | `AC_email_trigger_add` | Triggers, Webhooks, Email | +| Window management *(Windows, macOS, X11)* | `list_windows`, `focus_window` | `AC_focus_window`, `AC_snap_window` | Window Manager | +| Clipboard (text + image) | `get_clipboard`, `set_clipboard`, `get_clipboard_image`, `set_clipboard_image` | `AC_clipboard_get`, `AC_clipboard_set`, `AC_clipboard_get_image`, `AC_clipboard_set_image` | — | +| Remote desktop | `RemoteDesktopHost`, `RemoteDesktopViewer` | `AC_start_remote_host`, `AC_remote_connect` | Remote Desktop | +| USB enumeration & passthrough | `list_usb_devices`, `enable_usb_passthrough` | `AC_usb_*` (16 commands) | USB Devices, USB Share | +| Secrets vault | `default_secret_manager` | `AC_secret_set` + `${secrets.NAME}` | Secrets | +| Reports (HTML / JSON / XML) | `generate_html_report` | `AC_generate_html_report` | Report | +| Run history | `HistoryStore`, `manual_history_scope` | `AC_history_list`, `AC_history_capture` | Run History, Script Executor, Script Builder | +| Action journals | `execute_journal_run`, `inspect_journal` | `AC_journal_capture`, `AC_journal_read` | Run History, Script Builder | +| Metrics & tracing | `default_metric_registry`, `render_metrics_text` | — | — | +| Diagnostics | `run_diagnostics` | `AC_diagnose` | Diagnostics | +| Test-code generation | `generate_code` | — | — | + +Self-healing propagates cancellation before fallback or clicking. Its audit log masks secrets already resolved in the current run before writing or returning records; returned locator outcomes retain their original values. Legacy log files are not rewritten. + +Live image/VLM self-healing now shares one lazy logical capture, including its actual clipped origin. `screen_region` is `[left, top, right, bottom]` for both strategies. Schema-v2 audit records add run/step identity, content/configuration version, frame hash, strategy/capture timing and resolved backend/model; old records still load. Click dispatch without a verifier is recorded as issued or failed, with verification left unknown. The GUI exposes region input and selected-record evidence; Script Builder keeps region JSON structured. Historical `healed`/`heal_rate` count located candidates; separate operation metrics require explicit verification. + +Experimental `self_heal_run(SelfHealRequest(...))` defaults to locating. Choose `operation="click"` and `VerificationRequest(verifier=...)` (a Python bool callback) or `VerificationRequest(description=...)` (a configured VLM) to check the post-condition after input dispatch. VLM verification obtains a fresh logical frame and may incur API cost. `verified` is true, false or unknown; `found` and `issued` alone do not verify the operation. Exceptions and cancellation propagate without retrying the click. `AC_self_heal_run` and MCP `ac_self_heal_run` accept a nested `request`; explicit false verification fails the command/CLI or returns MCP `isError` with the structured result. GUI **Self-Healing** offers an optional post-condition field, and Script Builder edits the JSON request. Standalone VLM capture now uses the same logical origin/Retina normalization in memory. Framework assertions stop lookup recovery. + +Captured self-healing rows now include an optional `journal_path` alongside run/step IDs. Experimental `inspect_heal_source(path, run_id, step_id)`, `AC_self_heal_source` and MCP `ac_self_heal_source` read only the original step’s sanitized lifecycle snapshots. In **Self-Healing**, select a row and choose **Actions → Inspect original step** to open the background reader. Switching targets waits for the older reader to stop and retains the requester’s context; closing cancels pending work. Run History’s reader also accepts an optional step ID. Run/step filtering precedes the output limit, the whole file is validated, current path roots are rechecked around progress callbacks, and cancellation returns no partial result. Legacy or uncaptured rows have no original-source link; inspection never replays a command. + +Experimental causal synchronization provides `CausalBucket`, `CausalConfigStore`, `SyncActor`, conflict-preserving entry versions and a durable local `SyncOutbox`. The dedicated authenticated `GET/PUT /config/{user_id}/causal` protocol (version 3) validates peer registration, acknowledgements, retirement/full-sync epochs and collection in the same CAS transaction as retry receipts. Collected deletions retain permanent minimal fences; legacy writers cannot overwrite upgraded accounts. Private `AC_config_store_get` / `AC_config_store_commit` and matching MCP/Builder commands read and commit causal JSON with an explicit `_actor`. Pure merge/peer commands and private outbox commands remain available. The explicit `CausalSyncClient` and `AC_config_causal_fetch`, `AC_config_causal_commit`, `AC_sync_outbox_flush` (matching MCP/Builder commands) now deliver v3 HTTP requests: uncertain sends reuse the frozen request; only definite stale-base errors rebase within a bounded budget. `CausalReceipt` confirms the original receipt and latest complete snapshot atomically in the outbox. Command credentials use a live `options.secret_env` reference. `CausalSyncClient.control` and private `AC_sync_peer_control` / `ac_sync_peer_control` / Builder Data commands durably register, acknowledge, collect, retire and perform full resync. `SyncControlRequest(operation_id=...)` makes completed RPC retries idempotent; full resync requires explicit `discard_pending=True` before atomically adopting a new generation and archiving pending old edits. Local `status` reads no credential or network. Run `python -m examples.causal_peer_control` for the temporary loopback workflow; explicit local asset generations are available through `AssetManifest`, `DirectoryAssetTransport`, `build_asset_manifest`, `sync_assets` and private `AC_sync_asset_manifest` / `AC_sync_assets` (MCP/Builder). All assets stage and pass SHA-256/size checks before one directory publication; damaged caches are refused and scripts stay inert. `python -m examples.sync_assets` uses temporary directories only. Seven experimental adapters now capture selected scripts, locators, hotkeys, triggers, address-book entries, JSON settings and saved native GUI preferences into durable causal profiles. `SyncBindings` replaces explicit secrets and machine values with named references; `materialize_sync_profile` publishes a complete inert native-format generation. Private `AC_sync_adapter_snapshot`, `AC_sync_adapter_apply`, `AC_sync_adapter_resolve`, `AC_sync_profile_materialize` and matching MCP/Builder commands share the workflow. `python -m examples.sync_adapters` uses temporary files only. Private absolute path bindings accept high-entropy directory names while recognized credential formats remain refused. Native numeric definitions reject out-of-range values, including extreme JSON integers, with typed errors before storage. `WorkspaceSettingsSyncAdapter` captures only theme, font size, navigation visibility/width from native GUI INI files and publishes an inert `workspace.ini`; explicitly copy it to a separate working file before opening a new GUI. `python -m examples.sync_workspace` stays Qt-free. `SyncWorkspace` now coordinates selected sources, durable offline capture, causal HTTP, exact conflict review and full-resync source baselines. Private `AC_sync_workspace` / `ac_sync_workspace` / Builder Data share status/capture/sync/review/resolve/preferences/materialize and explicit peer controls; all require DRIVE. Runtime network credentials use `options.secret_env`. `python -m examples.sync_workspace_http` demonstrates two temporary sources over loopback, conflict resolution, restart and no replay of retired edits. Received definitions remain inert. Referenced asset transport is described below; explicit native working-copy loading is described below; `ConfigSyncClient` retains its timestamp merge. See the [causal/outbox guide](../../source/Eng/doc/causal_sync/causal_sync_doc.rst) and `python -m examples.causal_sync`. + +The lazy **Workspace Sync** tab exposes local status/capture, network synchronization and peer controls, exact causal review/resolution, and complete inert publication through **Actions**. Paste an explicit private workspace descriptor; credentials are environment variable names. Sync never applies received preferences automatically. Select `workspace`, review its current heads, then choose **Apply reviewed GUI preferences** to update theme, font and navigation in the running window. `SyncWorkspace.preferences(observed=change_ids)` and the existing AC/MCP/Builder `preferences` operation return four canonical values only when the exact reviewed heads remain conflict-free; missing/deleted values use safe defaults. Workers preserve caller context, refresh DRIVE authority, support cancellation and discard stale results on close. The view shows revision/pending/conflict/reference counts and the last successful sync revision; no connection starts when opened. + +Explicit native loading uses `load_sync_profile(directory, target_root, expected_digest=...)` and `LoadedSyncProfile`, with private `AC_sync_profile_load` / `ac_sync_profile_load` / Builder Data equivalents. The published `files` directory and exact reviewed manifest digest create a fresh editable workspace. Full verified bytes, canonical native files and sealed heads must agree before atomic publication. Loaded hotkeys and every trigger node are disabled native objects; locator and address-book handles use the working files. Typed asset references and native hotkey/trigger paths resolve against that working root, while literal script strings keep their meaning and secrets stay placeholders. In **Workspace Sync**, materialization fills the directory/digest fields; choose a working-copy container and **Load reviewed native profile**. Separate Actions inspect the selected native kind, open a loaded script snapshot in Builder, or apply its preference snapshot. These actions recheck both the current caller and captured owner; opening a script keeps Run explicit. Builder renders imported command names and positional data as literal text. `python -m examples.sync_profile_load` uses seven temporary domains and a real PNG with no network or device calls. + +Folder mirroring now compares SHA-256 content instead of increasing modification times: metadata-only touches do not resend, while same-time/older-time edits do. FolderSyncEngine retains pending/offline edits across restarts, checks stop between files, and owns a blocked sender until it exits. Transport owners can explicitly call record_received(path) after publication to prevent echoing received bytes. Native GUI frozen-receipt handling is described below. + +File sends now wait for each DataChannel callback, bound buffered data to 1 MiB and propagate channel failures to the caller. Optional `cancelled` predicates stop queued writes; announced byte counts detect source truncation/growth. Native folder jobs capture their authorization, engine, viewer and peer connection, and stop when ownership changes. Inbox downloads run outside the event loop through a per-channel queue capped at 32 requests. Default manual-mode channel acceptance is not publication acknowledgement; confirmed mode is described below. GUI reconnect handoff is described below. + +Native file receivers now discard unfinished bytes on shutdown, files/control channel close, terminal connection state, replacement channel or revoked file permission. Closed receivers reject late frames; current peer/channel and authentication checks protect replacement transfers, including viewer receives before authentication. State cleanup precedes user callbacks so callback-driven reconnection survives an old failure. File/audit/state callbacks preserve original cancellation and hard-interruption objects. Filesystem cleanup failures are logged after both close and unlink are attempted. Existing Remote Desktop controls use this lifecycle automatically; completed targets and the legacy wire format remain available. + +Local `FileReceiveReceipt(path, sha256, size)` metadata now freezes the original received bytes after atomic publication. `FileTransferReceiver.handle_message(on_receipt=...)` and native host/viewer `set_file_receipt_callback()` expose it without rereading the published file. `FolderSyncEngine.record_receipt()` prevents echo while retaining later local edits; legacy `record_received(path)` explicitly snapshots current content. The GUI folder toggle captures its engine and viewer for receipt delivery and refreshes its original authorization before touching the watch. Relative inbox/watch paths bind to their creation working directory; existing path notices use absolute paths. These local receipts feed the confirmed native mode below; GUI reconnect handoff is described below. + +Native `FileTransferSender.send`, viewer `send_file` and host `push_file` now accept keyword-only `require_commit=True`. Confirmed mode probes an authenticated native peer before source metadata/content reads, sends version-2 begin/end metadata and verifies the matching transfer ID, unpredictable end nonce, SHA-256 and byte size after atomic publication. Relative source paths bind before the exchange. Each file rechecks peer support/permission; waits are bounded and cancellation, channel/loop replacement or permission loss retain failure. GUI folder sends always require this mode, so accepted-but-dropped bytes do not advance delivery state and uncertain sends retry on the same engine. Legacy manual mode remains the default and sends its original envelopes. Both peers need confirmed-transfer support for GUI folder delivery; unsupported peers fail before file content is sent. Explicit GUI reconnect/resume is described below. + +GUI reconnect retains one in-memory folder baseline per panel. After reconnecting, press Start sync again: the same authenticated host fingerprint, absolute watch path and local principal resume failed/offline edits through a new authorised sender. A missing/changed host fingerprint, different root or principal starts a fresh baseline; a still-running old worker blocks handoff until it exits. Explicitly disabling folder sync resets the baseline, while stopping/reconnecting the viewer retains it. Closing the application clears it. The fingerprint follows the existing authenticated host-metadata trust model, not a new cryptographic identity guarantee. SDK callers can stop a FolderSyncEngine, export checkpoint() after actual worker retirement and pass that immutable FolderSyncCheckpoint to a replacement engine with the same path/recursion mode and an explicitly authorised sender. The baseline includes initially ignored files and received bytes; it is not a list of remote acknowledgements. + +TCP/WebSocket clipboard transfers use the existing explicit SDK methods and GUI Push clipboard button. Received text/images do not automatically send or broadcast onward; deliberate repeated sends of identical content remain valid. Buffered viewer/host reads recheck the original connection, authentication and full-control permission before applying clipboard data. Viewer sends pin the original channel before encoding and refuse replacement. Queued GUI deliveries retain their concrete viewer and connecting user; permissions and ownership are refreshed before native clipboard writes, before explicit clipboard reads and again before sending. Stale/revoked work is discarded or reports its permission error. Ordinary provider/callback errors stay contained; original cancellation and hard-control objects propagate. Text/image JSON envelopes and existing APIs remain unchanged. Callback registration binds the original viewer weakly once, so a disconnected viewer does not keep itself and its Qt panel alive until cyclic GC. Actual queued deliveries still retain the original peer and authority until consumed or discarded. Controlled local protocol, loopback and offscreen tests replace native clipboard providers; real-device and paid-API acceptance remain deferred. + +Experimental referenced assets use `SyncAssetBlob`, `SyncAssetReference`, `SyncAssetStore` and `SyncAssetHTTPClient`. Explicit `SyncBindings.assets` aliases freeze selected files into immutable SHA-256 references; asset-only changes create new causal versions. `SyncWorkspace` uploads verified chunks before preparing new definition requests, resumes interrupted transfers and downloads referenced bytes before complete inert publication. Existing private AC/MCP/Builder workspace/profile commands share these fields. `asset_cache_path` selects the client cache; signaling `--asset-store` / `AUTOCONTROL_SYNC_ASSET_STORE` select the separate server database. Authenticated version-one asset routes use 256-KiB chunks, a 64-MiB per-file bound and default per-account limits of 256 MiB, 8,192 chunks and 4,096 blob receipts. Quota exhaustion fails explicitly; immutable history has no automatic garbage collection. Paths in native output are relative to the generation root. `python -m examples.sync_referenced_assets` sends a real PNG and script through temporary loopback HTTP with no execution or active workspace change. + +Experimental persistent configuration uses `ConfigStore.commit(..., base_revision=..., operation_id=...)` and a version-two signaling PUT envelope. SQLite transactions preserve buckets and retry receipts across restart; stale revisions or changed operation identities conflict. `ConfigSyncClient` defaults to conditional writes; blind legacy writes require explicit client/server opt-in. `--config-store` selects the lazy database. Private `AC_config_store_get` / `AC_config_store_commit` and matching MCP tools share explicit Script Builder Data commands. This stores data without running scripts or enabling triggers; causal merge and offline outbox remain separate. See the [persistent config guide](../../source/Eng/doc/config_store/config_store_doc.rst) and `python -m examples.config_store`. + +Experimental journal-to-code candidates use `generate_candidate_from_log(path, run_id=...)`, `AC_generate_candidate_from_log`, and MCP `ac_generate_candidate_from_log`. They reconcile lifecycle snapshots, retain recorded control sources and retry evidence, and mark partial reconstructions as observed paths. Failed/incomplete invocations and unknown or redacted inputs remain explicit exclusions; parallel order is never invented. Generated Python/pytest/Robot source passes static, command and non-dispatching dry-run checks. `codegen --from-log run.jsonl --run-id selected` prints a JSON review bundle; `-o review.zip` or `write_candidate_archive` atomically exports code, actions and provenance together. **Actions → Review journal candidate** in Recording Editor or Script Builder opens source/diff/manifest/warnings; Builder import is separate and refuses intervening editor changes. Neither generation nor import runs the candidate. See the [journal candidate guide](../../source/Eng/doc/journal_candidates/journal_candidates_doc.rst) and `python -m examples.journal_candidates`. + +Experimental template-candidate revisions use `create_template_candidate`, `preview_template_candidate`, `verify_template_candidate`, `accept_template_candidate` and `revert_template_candidate`, with matching `AC_template_candidate_*` / `ac_template_candidate_*` operations. A new immutable JSON bundle retains original bytes and the candidate encoded in the target’s PNG/JPEG/BMP format. Preview returns bounded thumbnails. Verification compares both frozen versions on a local sample manifest; acceptance requires a labelled hit, an expected miss and every labelled case correct, plus the reviewed bundle SHA-256. Acceptance rechecks the dataset and atomically replaces only matching original bytes; revert restores exact original bytes and refuses later edits. Unknowns and native-operation success remain separate. The recorded threshold applies to verification; activating image bytes does not edit script thresholds. **Self-Healing → Template candidates** offers all five Actions, background work, cancellation and JSON evidence. Run `python -m examples.template_candidates` for a temporary-file-only example. + +Experimental fixed-frame comparisons use `evaluate_locators` or `evaluate_healing_manifest`, `AC_self_heal_evaluate`, MCP `ac_self_heal_evaluate`, and **Self-Healing → Version comparison**. Reports separate labelled accuracy, wrong predictions, unknowns and verified recovery, include p50/p95 and provenance, and export JSON/HTML through `write_healing_report` or GUI Actions. The local manifest operation never captures, clicks or selects a network backend. See the [dataset, populations and limits](../../../benchmarks/self_healing/README.md). + +Beyond this table, `utils/` holds 311 headless packages covering assertions, resilience, +data quality, i18n auditing, redaction, governance, observability, and more. The full +per-module map is in **[architecture_explore.md](../../../architecture_explore.md)**. + +--- + +Experimental structured journal capture is exported from `je_auto_control` (also available in `utils.action_journal`): `journal_scope` captures existing executor calls, and `execute_action_with_journal` isolates one run. Local loop/parallel/DAG steps retain parent IDs; failures, cancellation and dry-runs are distinct. Existing history owners automatically link explicit captures, including captures opened by local parallel/DAG workers; `HistoryStore.journals_for_run` returns the non-owning links. Clearing/pruning history leaves journal files intact. The CLI supports `run script.json --journal run.jsonl [--journal-run-id ID]` and `journal run.jsonl [--run-id ID] [--limit 100]`. Journal reads show sanitized lifecycle snapshots in append order; output defaults to 100 snapshots (maximum 10,000). `AC_journal_capture` accepts named parameters and runs a nested `body` on the owning executor without replacing its variables; `AC_journal_read` shares sanitized, bounded inspection with the CLI and public `inspect_journal`. Both commands are editable in Script Builder. Capture rejects identifiers or destinations containing secrets known to the run before history linking, file creation or action effects. MCP `ac_journal_capture` and `ac_journal_read` provide structured results, progress and cooperative cancellation. Captured journal roots and observers survive nested captures and local workers; reads can cancel between validated records. `JournalRunOptions` and `execute_journal_run` expose the same controls in Python. + +Manual runs can opt into history with `manual_history_scope`, `AC_history_capture`, CLI `run --history [--history-db PATH]`, or **Record in Run History** in Script Executor / Script Builder. An optional GUI journal path also works independently of history. GUI/CLI result JSON and existing variable scopes are preserved; the command returns `history_id`, `record` and `failed_actions`. Existing and nested captures link to the new manual row. CLI previews use the `cli.preview` source label; ordinary runs use `cli.run`. + +Run History includes a read-only journal browser. Use **Actions → Use Journals from Selected Run** to select a provenance link, or **Choose Journal** for an external file. Set a run ID and snapshot limit, then **Read Journal**; start/completion snapshots stay separate and their full sanitized data appears on selection. **Cancel Journal Read** and closing the view request cancellation between records. File parsing runs in a background worker; selecting a link opens no file. + +Values resolved from `${secrets.NAME}` are masked in application diagnostics during executor runs, including nested actions and local parallel/DAG workers. CLI/REST/MCP requests and scheduled, trigger, hotkey and email runs retain the mask through error handling and audit/history writes; report records capture redacted snapshots. DAG calls retain the owner mask through complete node diagnostics, including standalone calls and custom local runners. Watchdog, observer and callback-executor calls also retain it through final diagnostics; independent rules have separate masks. CLI stderr is masked, while API outcomes, raised exceptions and CLI result payloads retain their original values. Masks are discarded when the owning request or run exits. Interrupted history runs are recorded as `error`, while journal steps remain `cancelled`; no error screenshot is taken. Cancellation propagates through non-strict execution, recovery/retry, callbacks and local workers. Hard exits retain their original signal even if history completion fails. + +## Command-line interface + +Each `je_auto_control run` invocation, including `--dry-run` and runs without `--var`, gets a fresh variable scope. Top-level `run_from_description` and `StateMachine.run()` also isolate variables while sharing them across their own actions and states; nested calls reuse an existing execution scope. A caller-owned `Executor()` keeps its own variables. + +```bash +je_auto_control run script.json [--var name=value] [--dry-run] [--allow-package NAME] +je_auto_control validate script.json # alias: lint +je_auto_control fmt script.json [--check] +je_auto_control list-commands [--filter mouse] [--json] +je_auto_control record out.json [--duration 5] +je_auto_control codegen script.json --target pytest -o test_flow.py +je_auto_control failure-bundle failure.zip --error "login timed out" +je_auto_control list-jobs +je_auto_control start-server --port 9938 # TCP socket server +je_auto_control start-rest --port 9939 # REST API +je_auto_control version +``` + +`--var name=value` is parsed as JSON when possible (`count=10` becomes an int), +otherwise kept as a string. `run` exits 1 when any action failed (the run +still goes on to the end), so a CI step fails with it. The legacy +`python -m je_auto_control -e file.json` entry point still works, and its +`-e`, `-d` and `--execute_str` flags exit 1 the same way. Under +[TestPioneer](https://github.com/Integration-Automation/TestPioneer), which +sets `TEST_PIONEER_ARTIFACT_DIR`, the HTML, JSON and XML reports asked for +under a relative name are written below that directory. + +--- diff --git a/docs/guides/zh-CN/development.md b/docs/guides/zh-CN/development.md new file mode 100644 index 000000000..8349d53a7 --- /dev/null +++ b/docs/guides/zh-CN/development.md @@ -0,0 +1,90 @@ +# Development and resources + +[README](../../../README/README_zh-CN.md) · [Documentation](../../README.md) + +## 文档与示例 + +| 资源 | 内容 | +|---|---| +| [`examples/`](../../../examples) | 45 个自包含脚本:截图点击、OCR、调度器、远程桌面、agent loop、可观测性、录制、变量、热键、触发器、报表、MCP、REST、密钥、插件、computer use、Wayland、跨主机 DAG、chat-ops、pytest/BDD、锚点定位、动作日志。 | +| [Read the Docs](https://autocontrol.readthedocs.io/en/latest/) | 完整 API 参考,含英文与中文。 | +| [architecture_explore.md](../../../architecture_explore.md) | 逐层记录每个模块的职责。 | +| [docs/CAPABILITY_MATRIX.md](../../CAPABILITY_MATRIX.md) | 能力 × 平台对照矩阵。 | +| [docs/API_LIFECYCLE.md](../../API_LIFECYCLE.md) | 稳定 API 与弃用策略。 | +| [docs/updates/](../../updates/README.md) | 更新记录:各版本说明与完成的工作,每月一个文件(原 `WHATS_NEW.md`)。 | +| [CHANGELOG.md](../../../CHANGELOG.md) | 兼容性变更记录。 | +| [SECURITY.md](../../../SECURITY.md) | 安全策略与报告方式。 | + +--- + +## 开发 + +```bash +git clone https://github.com/Integration-Automation/AutoControlGUI.git +cd AutoControl +pip install -r dev_requirements.txt +uv sync # 或:以已提交的 uv.lock 做可重现安装 +``` + +```bash +python -m pytest test/unit_test/headless # 无头单元测试 +python -m pytest test/integrated_test/ # 跨模块流程测试 + +ruff check je_auto_control/ +pylint je_auto_control/ +bandit -c pyproject.toml -r je_auto_control/ + +python test/verify/typing_contract_verify.py # mypy,整个包,三个目标平台 +python test/verify/typing_contract_verify.py --extras # 同一项检查,改用真正的 PySide6/aiortc 类型 +python -m sphinx -b html -W docs/source docs/_build/html # 文档,警告视为错误 +``` + +dev/main 的无头任务会保留七天的 `native--` artifact,内含合并进程输出、 +包/运行环境版本与退出码。Linux 经 GDB 保留各线程原生堆栈;其他平台保留 Python +faulthandler 输出,测试失败仍会使任务失败。可在 repo 执行单一命令 +`python scripts/ci_native_diagnostics.py --artifact-dir test-artifacts -- python -m pytest -v --tb=short --timeout=120`; +Linux 安装 GDB 后,可在 `--` 前加入 `--native`。 +含空格/引号的 argv 仍是原始参数,已处理的 `SIGINT` 会传给子进程。 +Linux 先在完整套件的 debugger 外验证诊断工具;前置检查记录也收在同一 artifact。 + +选定的 dev 推送由 `.github/workflows/ei-lifecycle.yml` 在隔离 libei/libeis +容器执行,将版本及两份原生记录保留于 `ei-lifecycle--` artifact 十四天。 +半开与 live 释放子进程分别有十/六十秒时限与 faulthandler;其他子进程失败使 CI 失败, +释放成功必须有 begin/end 标记。半开探测另须有相同整数 fd 数量,live 清理先释放拥有的 +device refs。run 39507190704 在 libei/libeis 1.3.901-1 通过 9/9 与 20/20 检查, +包含坐标越界拒绝且不转用 CLI。半开 `ei_unref` 仍会 SIGSEGV,因此保留 runtime 保护, +helper 隔离仍待完成。设备暂停与序号回读仍未验证;受控 socket peer 不代表合成器授权、 +真机或多屏幕验收。 + +欢迎贡献——请见 [CONTRIBUTING.md](../../../CONTRIBUTING.md) 与 +[CODE_OF_CONDUCT.md](../../../CODE_OF_CONDUCT.md)。CI 会强制两条规则:`import je_auto_control` +绝不能加载 PySide6;每个功能都必须同时具备无头 API 与 GUI 界面。 + +--- + +## 许可 + +[MIT License](../../../LICENSE) © JE-Chen。 +内含与可选第三方组件的许可请见 [Third_Party_License.md](../../../Third_Party_License.md)。 + +- **主页**:https://github.com/Integration-Automation/AutoControlGUI +- **PyPI**:https://pypi.org/project/je_auto_control/ +- **文档**:https://autocontrol.readthedocs.io/en/latest/ + +旧式 MCP 动作包装、并行分支及本机 DAG worker 也会保留相同的来源限制。 + +受管指针动作可指定该次观察的元素索引或缩略图坐标,由主机检查当前画面并换算原生坐标,包括缩放与负屏幕原点。收据保存几何依据,不保存图像字节。`AgentObservationStale` 表示分派前已拒绝动作;本机 agent 只在 adapter 确认没有按住或待处理输入时,在重试预算内重新观察。 + +紧急停止先返回带有 metadata.details_deferred 的精简状态,完整产物链接可由单个任务查询。 + +托管鼠标按下前会规范按钮所有权并确认实际光标位置。Windows 指针检查会拒绝其他窗口遮挡。影像仅将指定窗口绘制到清空的私有 GDI 内存,几何变化会拒绝该画面;绘制或读取失败也会释放资源。不改用桌面捕获。这些路径已用模拟原生 API 测试,实际原生验收仍未验证。 + +Agent 任务界面将任务范围、工作流程设置、触发器、技能及恢复分页。观察页显示只读元素和已验证、严格遮罩的 JPEG,每个逻辑画面像素对应一个呈现像素。选择元素或影像坐标只会编辑该次观察的动作请求;由 Actions 的「执行观察动作」通过共用任务 API 发送。切换任务会清除预览,迟到回复不能替换当前任务;新画面必须重新选择,旧索引不能直接复用。关闭界面仅解除请求订阅。 + +托管工作流程可用 workflow_wait/AC_workflow_wait 等待指定控件的精确值或状态,只重复读取;可取消且受动作预算限制,默认五秒、上限六十秒,不重发写入或提交。固定技能每一步都验证已有收据与固定顺序,恢复也不能跳过读回失败的步骤;模型自主循环仍保留停滞检测。新表单/跨应用模板会在提交前拒绝原本已匹配的确认值,提交后等待新的状态转换。批次可设置 new_record_selector 逐条重置;确认仅证明配置的界面转换,有交易标识值时应使用它。归档模板完成时会重读指定清单及文件摘要,清单上限一 MB,总验证数据上限六十四 MiB。 + +AgentHumanReview 表示未保存内容或未知对话框需人工审核;包括外部观察请求都会记录 waiting_user 并释放输入控制权,明确恢复后仍会重新检查。Windows 依据原生对话框/禁用所有者及英中日已知未保存文字判断。Workspace 也会拒绝标题首尾带星号的文档,并可在窗口设置中加入 unsaved_selector 与 unsaved_value,在改变排列前检查应用特有指示;不声称能推断所有程序的未保存状态。标准文件对话框沿用 AC_handle_file_dialog 执行器,托管 driver 只接受唯一精确标题、相同 PID、已确认前景,以及授权根目录内的绝对路径。UIA 控件须属于实际指定的根窗口,同 PID 的其他窗口也会拒绝。模拟原生与本机 HTTP 测试已有覆盖,实际平台验收仍未验证。 + +主机目标通过 AgentTargetProfile 与 manage_agent_target(AC_agent_target,register/get/disable/enable/probe)设置。名称及设置固定不可替换,目前提供 desktop/files/browser adapter,未实现类型会被拒绝;浏览器可使用主机审阅的 helper_python。任务固定主机设置摘要,不能扩大工具、应用、根目录或网络来源。启停状态会跨重启保存并在分派时检查;禁用会请求暂停及清理,重新启用仍须明确恢复任务。list_agent_targets/AC_agent_target_list/CLI agent-task targets 仅提供被动信息,readiness=not_probed、native_evidence=not_recorded;完整设置需要 manage_hosts。CLI agent-task target 及 GUI「主机目标」页使用同一服务。匿名有效 MCP 工具 session 的直接及旧式包装调用都以 operator 权限执行;MCP 主机管理需要已验证的管理员,可信任的直接 Python 调用维持原行为。浏览器自动化统一由 WebRunner(je_web_runner)提供,本机开发来源为 D:/Codes/WebRunner;browser profile 使用受管 je_web_runner SDK 契约,依赖诊断不代表原生可用。 + +既有浏览器自动化(包括 open_path(URL) 与 AC_open_path)统一交由 WebRunner,Python 包名为 je_web_runner。URL 计划的 backend 现为 je_web_runner,原本比较 webbrowser 描述值的调用端需改用新值;函数接口与本机文件打开维持兼容。实际 URL 执行需要配置的 WebRunner 项目,缺少时传出 WebRunnerBridgeError,不改用 OS 浏览器。本机开发来源为 D:/Codes/WebRunner;纯计划及注入 opener 测试不需要该包。协议支持由 WebRunner 与所选浏览器决定。既有浏览器 GUI/MCP/AC 及录制的 WR_* 动作都使用同一桥接。 diff --git a/docs/guides/zh-CN/evidence.md b/docs/guides/zh-CN/evidence.md new file mode 100644 index 000000000..51c021aba --- /dev/null +++ b/docs/guides/zh-CN/evidence.md @@ -0,0 +1,121 @@ +# Completion evidence and handoffs + +[README](../../../README/README_zh-CN.md) · [Documentation](../../README.md) + +## Local DAG 完成证据的明确移交 + +其他 caller 持有的既有恢复子任务,可通过明确且可撤销的移交,向原 local DAG 提供完成证据。 +以 `manage_agent_recovery` 的 `review_handoff` 提供最终 `task_id`、`batch_id`、`node_id`, +有权管理者再用相同 ID、将返回的 `handoff_review` 填入 `review`,并附非空 `note` 执行 +`create_handoff`。接收者由服务依真实原始 admission 决定。在 `review_continuation` 的 successor +决策中,除 `node_id`、`action`、`task_id` 外明列 `handoff_id`,再审核并批准整份 continuation。 +最多支持十六层真实恢复链,包含经私有 admission 的永久只读最终验证者;一般任务归属保持原样。 + +`get_handoff`/`revoke_handoff` 使用 `handoff_id`;`list_handoffs` 使用 `batch_id`、`node_id`。 +创建与采纳时重查实际 owner、创建审核者、签发 session 的来源根限制、当前接收端限制、固定 scope、 +效果快照、独立完成及资源退役。批准、开始及后续依赖验证都重查同意;撤销或证据丢失会阻止采纳。 +期限不超过最早终止见证既有的三十天保留期限。公开响应只含有限 ID、摘要与状态,不含私有参数、 +capture 或 principal 数据库路径;不授予一般任务读取/输入权、不转移归属或重放。 +跨主机及非 DAG 的移交契约仍列于 `Progress.md`。 + +Agent Tasks 的成果移交页提供操作菜单与 JSON 编辑器;Actions 只准备审核、创建、撤销请求, +不自动派发。五个可编辑的 `agent_handoff_*.json` 示例涵盖 review/create/get/list/revoke。 +Python、AC、CLI、具名 MCP、REST、Builder 共用这些 recovery 操作。本次证据涵盖契约及自有文件 +流程;暂缓的原生桌面、浏览器、设备及二十四小时验收仍须各自提供证据。 + +## 明确续授权只读完成验证 + +原来源的 origin 引用过期或不可用时,明确调用 +`manage_agent_recovery("review_completion_authorization", {"task_id": ""})`。 +审核服务产生的 `verification_spec`、保留/替换/当前 origin 限制,再以相同 `task_id`、返回的 +`snapshot`、`authorization_review` 及非空 `note` 调用 `create_authorized_completion`。 +可选 `owner_policy="source_owner"` 在创建时另须返回的 `ownership_review`;不能自行提供新验证 +规范。仍有效的旧限制保留,新根目录与原上限、前一读取者上限及当前 session 取交集。 +已重新授权的读取者不能改用一般完成审核来移除这些限制。 + +子任务永久只读,依真实已确认的原效果独立检查当前条件,不输入、不重放、不恢复 capture, +也不修改旧见证。来源/效果快照、实际 owner/reviewer 及原 DAG admission 都会重查。 +创建任务与最终完成各自在自己的 SQLite writer 内写入后重验,变化时共同回滚。 +最多支持十六层真实恢复链;已退役且成功的读取者可再次明确续授权,但保留前次较窄上限及所有仍有效 +的继承限制。来源/效果证据已改变时仍拒绝,不能借 scope 续授权默默修复旧证据。 + +历史 `get` 保留 succeeded 状态;新授权失效时,当前 `completion_contract` 为零、 +`completion_authorization` 为 unavailable,DAG 采纳与后续依赖验证会拒绝这份证据。 +新的只读标记损坏/丢失时,在 helper 启动前拒绝。以 `completion_task_id` 录制时沿用原语义动作及 +已审核的限缩 scope,但草稿仍须自己的新验证试跑。此流程不发布过期候选,也不续授权已发布技能; +既有技能重新授权流程保持分开。 + +Python、AC、CLI、具名 MCP、REST、Builder 共用两个操作;Recovery 页的两个明确 Actions +沿用所选任务、owner policy 与请求编辑器。可编辑示例为 `agent_completion_authorization_review.json` +与 `agent_completion_authorization_create.json`。remote 只读来源、跨主机移交、 +实际应用状态重建,以及暂缓的原生/设备/浏览器/二十四小时验收仍列于 `Progress.md`。 + +## 明确移交已续授权读取者的完成证据 + +现有 `review_handoff`/`create_handoff` 现在可明确将已重新授权、永久只读读取者的完成 +证据交给实际原 local DAG。指定该读取者的 task ID 与原 batch/node,由服务推导证明;不能自行提供 +policy、所有者覆盖或授权 bundle。一般成果移交沿用现有规则。 + +预览的 `evidence.completion_authorization` 显示完成任务/审核、固定的审核摘要、根目录数量及 +替换/保留/当前 origin ID,不含私人 principal 路径、动作参数或 capture。创建时以最上层返回的 `handoff_review` +作为请求的 `review`,并提供非空 `note`。每个真实任务都保留已审核的上限与所有仍有效的历史限制;不可用的 +引用须明确审核替换,发出移交时额外的 session 限制也持续有效。移交沿用读取者已实际验证的相同 +根目录;交集改变时须重新审核及执行只读完成验证,接收者的 session/profile 限制也会持续应用。 + +最多十六层真实恢复链可混合先前已审核的可执行子任务及私人读取者。成功的中间读取者必须具备实际 +私人历史 scope 与退役证明,一般已成功来源没有这个例外。发出或采纳移交时不启动 helper、不重放 +输入;旧来源状态、见证、收据及所有任务所有者维持原样。原所有者只取得有限完成投影,不能因此 +一般读取其他 caller 的任务。撤销或授权失效会阻止采纳及后续依赖验证。 + +原 accepted-request hash、原始提交见证、私人 admission、graph、owner/reviewer、整条来源/子任务 +快照与最后读取者的续授权都固定在证明内。读取与写入后重验使用同一个 SQLite writer,包含尚未提交 +的变更;发现变动即回滚任务/移交创建。继承的 `dag_batch` 选项不等于 admission,必须沿有界真实 +恢复链找到原请求及实际授权身份,不补造 admission。旧的一般完成 binding hash 保持兼容;各历史 +任务各自审核限制,不能通过合并历史绕过正常十六个有效 origin 上限或原根目录边界。 + +相同有效重试沿用原 note 与 ID,已撤销 ID 不会重新启用;重启与采纳保留最早终止见证的三十日期限。 +origin 失效后仍可查 get/list 历史与 revoke,但历史不代表可用完成证据或输入授权。Python、AC、 +CLI、具名 MCP、REST、Builder 共用五个现有操作,Handoffs Actions 与 JSON 编辑器/结果区可显示 +明确续授权审核,不自动派发同意。跨主机移交、remote 读取者、实际应用/设备 +来源及暂缓的原生/浏览器/真机/二十四小时验收仍列于 `Progress.md`。 + +## 明确移交任务来源的完成证据 + +现有五个移交操作也接受真实非 DAG 来源任务: + +- `review_handoff` 提供 `source_task` 与实际最后证据的 `task_id`。 +- `create_handoff` 再以最上层返回的 `handoff_review` 作为 `review`,并填写非空 `note`。 +- `list_handoffs` 提供 `source_task`;`get_handoff`/`revoke_handoff` 仍使用 `handoff_id`。 + +任务来源与 DAG batch/node 字段互斥,服务依实际保存的 grant 判断存储类别。真实 DAG 祖先仍须走 +原 batch/node 路径,不能借由已移除 `dag_batch` 的只读读取者绕过,也不补造 DAG 节点或 admission。 +一般任务不必虚构提交见证或 idempotency key;实际存在的原请求须固定并在同一 SQLite writer 重验。 + +现有技能操作明确选择 `handoff_id`。`record` 以 `completion_task_id` 采纳独立读取者,建立的 draft +仍须自己的新验证 trial;`accept` 使用完成读取者时,仍保留原 candidate 的真正验证任务。 +`review_execution` 与对应 `accept` 可选实际 `execution_task_id`;最后证据是独立读取者时,再提供 +`completion_task_id`。服务核对原本完整语义动作计划、真实执行 ID 及独立完成条件,不能把读取者 +当执行任务或替代验证 trial。 + +grant 只提供私人有限证据视图,原所有者、来源状态与收据维持原样,一般 get/list/observe/act/ +resume 权限不扩大。发出或采纳时不启动 helper、不重放输入。真实快照、可选原请求、实际 owner/ +reviewer、退役输入与有效历史 origin 均持续核对;新录制的 draft 保留发出与接收 session 上限。 +失效限制须经真实私人完成续授权,不能靠相同 hash 或自填 scope flag 替代;只读采纳也不会续授权 +已发布技能原本的输入权限。 + +来源祖先与后续移交链合计最多十六条真实恢复连接。期限沿用最早终止证据的三十日,改锚定较新的 +读取者不会延长旧祖先。DAG 与任务 grant 的 INSERT 后及相同重试都重验撤销墓碑;来源/请求/角色/ +origin/撤销变动会回滚 grant、draft 或发布。已撤销 ID 不重启,origin 失效后的 get/list/revoke +历史只显示有限 ID/hash,不代表持续有效的完成证据或输入授权。 + +Handoffs 页可明确选原本机 DAG 或原任务来准备 JSON;三个技能 Actions 准备带 grant 占位符的录制、 +发布与执行审核,不自动同意或发布。Python、AC、CLI、具名 REST/MCP 与 Builder 共用相同操作及 +真实 caller。`examples/` 提供 `agent_task_handoff_review.json`、`agent_task_handoff_create.json`、 +`agent_skill_recording_handoff.json`、`agent_skill_completion_handoff.json`、 +`agent_skill_execution_handoff_review.json` 与 `agent_skill_execution_handoff_accept.json`。 + +跨主机移交、remote 读取者、实际应用/设备来源、暂缓的原生与二十四小时验收,以及未解的 +HTTP409/bootstrap 问题仍列于 `Progress.md`。 + +wheel 与源码分发包包含 REST Dashboard 和 Swagger 的 HTML、CSS、JavaScript 资源。 +安装后的套件沿用相同的本机 REST 路由与授权规则;提供静态页面不授予任务或桌面输入权限。 diff --git a/docs/guides/zh-CN/implementation-notes.md b/docs/guides/zh-CN/implementation-notes.md new file mode 100644 index 000000000..722324e3d --- /dev/null +++ b/docs/guides/zh-CN/implementation-notes.md @@ -0,0 +1,516 @@ +# Implementation notes migrated from README + +Historical implementation notes preserved during the README reorganization on 2026-11-10. These entries describe different development stages and are not a current acceptance checklist. See [Progress](../../../Progress.md) and [updates](../../updates/README.md) for tracked status. + + +成果移交管理已共用 `manage_agent_transfer(operation, request)`、`AC_agent_transfer`、 +`ac_agent_transfer`、已授权的 `POST /agent/transfer` 与 Script Builder metadata。CLI 使用 +`agent-task transfer --operation review_export --request request.json`。审阅返回批准 token; +创建须提供该 token、原请求 key 与明确 note。导出/导入管理可指定已登记主机; +可携证据管理也可指定已登记主机,由来源核实私有权限。传输页提供四语 Actions、可编辑 JSON 与服务回复; +审阅不自动批准,批准模板保留原主机、token 与 key 并留空备注。选项变更或关闭页面后, +旧回复不覆盖画面,已接受的导入仍由服务持有。远端批准先保存明确同意,失联或协调端重启后以原键重发,保持同一授权。 +被动诊断仅列出本机契约,不代表即时授权或远程/原生能力已验证。只读完成证据在创建与使用时重新核实原私有同意,不恢复原输入权限。 +实现验证记录见 docs/updates/README.md;其余交付与验收见 Progress.md。 +examples/agent_transfer_export_review.json、agent_transfer_import_review.json 与 +agent_transfer_evidence_review.json 提供可编辑请求,并各有独立的 create 模板。 + +实验性的来源主机技能操作,可通过现有 `handoff_id` 明确选择可携授权与完成/执行任务。 +来源在技能事务内重新核对实际同意、接收者与私有证据,候选/发布写入后再次核对。 +保留原始动作、候选自己的验证试跑与明确版本批准;新的技能试跑建立服务生成的全新请求 key, +不为旧有未带 key 的试跑补造记录。此流程不将外部动作或策略移交协调端; +技能证据保留来源主机的原动作/试跑/版本;其余跨主机验收与交付见 Progress.md。 +选择移交证据的技能操作,全程保留 runtime 所有权,操作结束后才释放。 + +目的端导入目前仍为实验功能。明确启动的服务可通过 runtime 移交控制器与经验证的 +`/agent/transfer` 接受 `review_import`/`create_import`/`get_import`/`run_import`/ +`cancel_import`/`list_imports`。协调端可通过自己的不透明同意 token 路由这些有限操作; +目的端使用自己的来源登记与账号,不转发协调端 principal/origin 或来源凭据。 +批准意图在派送前提交;回复丢失后的精确重试仍对应同一笔导入。 +启动时接回已批准且尚未领取的工作;未结算 claim 会转为待审阅。明确的 `run_import` +以新队列代次重新核对原收件者、profile、实时 origin 与来源 grant,可重用已验证私有分块, +或只读核对既有完整目录与哈希,不重新下载/发布。续行时新增的 origin 限制仍持续生效。 +已明确排入队列且未领取的只读核对可跨再次重启;采认前重验当前字节、profile 与保留的 origin。 +导入收据确认完成前,目的端会在最后一次来源回复后重新核对完整文件清单与内容摘要。 +文件遭改写、丢失或增加未列入清单的文件时,导入保留 requires_review, +保留用户修改与原发布成果供审阅。 +目录身份、字节或权限变更不能确认发布。取消会使生产者失效;尚未完成收据确认的 +发布保留 requires_review,已确认发布的文件保留为用户成果。 +取消或过期的私有分块账号须确认生产者退出才清理;失败时保留配额,成功重试后才释放。 +收据维持原本固定期限。 +暂存目录与预先创建的文件会在复制字节前记录文件系统身份。生产者退出后, +过期清理可于重启后重试;遇到替换或无关对象时保留配额待审阅,不递归删除。 +来源维护会清理过期或已撤销的私有导出账号,包含重启或授权者移除后;失败时保留配额。 +来源或目的端清理完成前持续保有 runtime 所有权;无待清理数据时不获取 runtime 写入锁。 +创建/续行回复会在唤醒新投递前读取已提交的收据;后续以 get_import 查询当前进度,避免回复被新 writer 阻塞。 +后续维护会修剪已清理、撤销且过期的来源元数据以回收记录配额,保留同意/撤销凭据与其他记录类别。 +冷启动维护以只读探测发现待处理来源记录;没有待处理记录时不创建移交控制器。 +runtime 最后释放所有权时会与控制器构建互斥,并重验后建立的控制器是否退出;忙碌时保留所有权供稍后重试关闭。 +私有缓存路径重定向会在打开存储前拒绝;清理失败时保留配额。 +后续维护会在私有数据确认清理后,回收到期的目的端导入/派送元数据及其已结束队列记录。 +仍在执行、身份被替换或未知状态的队列会阻止回收;原同意/撤销凭证与已发布用户文件保留。 +冷启动维护不启动监听端或生产者;待清理账户的扫描不受大量未到期历史记录遮蔽。 +可移植证据保留与共用接口已接入;其余故障交错与正式交付见 Progress.md。 +来源证据实验功能已接入 owning runtime 与具名/共用账户的本机 transfer HTTP 管理路径, +提供 review_evidence/create_evidence/get_evidence/revoke_evidence/list_evidence。 +独立持久授权沿用真实恢复/完成验证、当前账户与原本机 DAG 审核;已登记 peer 的 evidence +读取核对实际接收的 key/规范与 DAG 节点,只返回 ID、哈希及有限验证,不授予一般任务读取或输入。 +审阅摘要不含 node.request_digest;即时读取才按精确已审阅原请求补入。 +来源主机技能证据、远端管理路由与共用接口已接入;其余故障验收与交付见 Progress.md。 +协调端 DAG 的实验采纳已接入独立审阅的远端恢复授权,固定原来源/key/规范/graph/node 与主机。 +批准与启动先持久保存暂定状态,离开本机 writer 后即时验证来源,再核对原同意与认领,才启用。 +停止会取消暂定状态;中断后只可用同一明确批准请求续接。确认期间保留 runtime 所有权, +不把独立 peer 读取串行化;认领/记录及最终采纳前后重新验证。 +授权失效会阻止后续调度,只对精确已接收的下游任务请求有限暂停;回复未知或丢失时保留认领并待审阅。 +已完成副作用与无关任务保留;不宣称已证明原生输入退休或完成整份故障矩阵。 +旧投递格式升级会保留原批准 origin 与固定期限;多次续行的额外 origin 仍累积生效。 +停止附加的 REST 观察端不会重派或取消服务持有的导入,也不释放 runtime 所有权;重新连接可读取同一笔成果。两主机与独立进程三主机测试已核对实际字节及账号范围。 +更多重启/取消交错、更多暂存故障交错、完整保留、可移植证据、client/GUI 接口与完整阶段检查 +仍列于 Progress.md;移交收据不授予任务输入权限,也不能证明任务完成。 + +来源导出的远端审阅/创建/查询/撤销已接合。协调端发出自己的不透明审阅 token, +绑定实际本机调用者、当前主机/凭据摘要、来源审阅、清单摘要与原 key。批准意图在转发前 +持久提交;回复丢失或协调端重启后,相同批准仍取回同一来源成果。更换调用者、主机、凭据、 +note/key 或来源回复摘要即拒绝。待审阅与持久路由各限128条;到期只清理本机路由 metadata, +保留同意边界。关闭 runtime 会清除尚未批准的本机审阅缓存,已批准的持久意图仍可恢复。 +来源使用自身账号,本机 principal/origin 不转发。目的端导入、可移植完成证据与公开接口均已接入; +其余验收与正式交付见 Progress.md。 + +既有远端 DAG 在固定主机配置及每次保留连接调用前后,均读取实际持久化通讯录。 +其他进程替换/移除端点或凭据、配置损坏或原本本机调用者被撤权时,操作会失效。 +读取不建立 console,也不隔离通讯录;既有本机服务委派与封闭远端路由保持兼容。 + +跨主机成果移交依明确审阅与各主机本机授权运行。来源核心可审阅已完成文件成果,建立不可变 blob, +并核对实际发行者/接收者。来源管理与 peer 只读 HTTP 路由已可提供经审阅的清单/分块。 +Peer 使用接收端本身的 bearer/RBAC 与速率限制,在外部 principal/用户数据库查询前拒绝 +本机 principal/origin header;本机服务 client 仅在管理流程保留实际所有者委派。 +移交请求在服务器读取前限制为1MiB;受限 client 在派送请求与解码成功/错误回复前核对上限, +不变更一般 HTTP 的既有上限。完整私有授权链/生命周期验收、目的端发布/ +证据采纳及共用公开接口已接入;其余验收与交付见 Progress.md。移交收据不授予任务输入权限。 + +来源导出在打开选定文件前,排除实际 runtime/移交数据库与 sidecar、当前来源所有者及 +发行者的用户数据库、服务连接文件与专属证据目录。服务登记实际私有文件,不保留一般成果的 +同名文件名;manifest 只核对选中的输出。Peer 读取与相同请求重试会重新核对当前路径权限, +不重新哈希历史用户成果,并保留操作期限。DAG 成果沿最多十六层真实恢复链核对原始 +提交任务、实际请求及本机 DAG admission,重新授权接纳者,并排除其不同位置的账号数据库。 +恢复子任务不补造提交记录;正常 standalone 不要求 DAG 提交记录。私有恢复链摘要在审阅、建立、 +相同请求重试与 peer 读取时重验;实际私有恢复所有者/审阅者绑定也纳入摘要,其数据库保持私有。 +来源操作在字节存取与 grant 写入边界配合取消;提交后回复被取消仍可依固定意图精确取回。 +成果期限依完成来源 updated+30 天计算,不因重试/重启刷新,也不改用较早祖先的期限。 +本机只读 reader 依当前私有完成授权导出,旧输入仍撤销;自动清理、目的端发布与证据采纳已接入。 +其余提交/撤权交错验收与正式交付见 Progress.md。 + +Runtime 透过实际 batch 主机 adapter 保管 TransferPeer;具名传输固定端点/凭据,于 HTTP 前后 +重读持久化通讯录并核对当前本机调用者。来源端使用自身凭据验证,不接收本机 principal/origin +header。来源私有排除只取得实际通讯录路径,不建立/重载 console 或隔离文件。封闭清单与规范 base64 分块须符合 +导出 ID/摘要、每块最多256KiB及原始期限;URL 路径前缀同样套用1MiB移交上限,一般 HTTP +保留既有上限;无效预算(含过大整数)在派送前回报类型化错误。两/三主机 +导入交付仍待完成。 + +空闲后台 worker 以只读预检识别空队列,减少轮询与任务状态、完成事务的写入锁竞争。 +发现工作后仍须在原有事务内重新核对与领取;保留 claim 代次、过期工作回收与重试上限, +不延长任务或传输期限。 + +租约维护会在停止事务内核对实际输入所有者与世代。延迟的监视程序不能改写已退役任务的 +恢复证据,也不能取消新租约;接受的最终停止状态与取消 token 会先于停止事务发布。 +仍有效的权限撤销与原有期限持续生效。 + +副作用已确认的浏览器任务,可通过已有完成审核与技能流程读取原来的 WebRunner context。 +原 helper 先永久结束 SDK 输入/网络,再释放输入 journal/租约;runtime 最多保留 16 个 context, +自分离前预留起最多保留 300 秒,不因分离耗时延长。预览/创建核对实际 effect task 的实时 SDK view;验证只借用原 context +读取最新有界 DOM/字段值,不重新配置输入、不 ACK 原生输入、不传输,也不另开浏览器或 helper。 +退出切换、能力探测与清理也拒绝嵌套工具与原生输入。 +同 profile 的不同任务分开保管,context ID 本身不授权。私有完成授权审核可在原上限内明确续授权 +验证 scope,原输入规范不变;已失效输入 origin 与有限私有保管本身均不授予读取权限。 +拥有者删除、目标停用、来源变动、期限或读取失败会使 context 失效;只有确认进程结束才释放 +进程拥有权,清理失败持续跟踪。重启不恢复页面,网络结束后的 DOM 不能当作新服务器数据。 +Python/AC/MCP/REST/CLI/Builder 与 GUI Actions 共用原审核 request;技能录制保留原动作, +发布须使用自己的实际新验证试跑与明确选择的完成证据。示例见 +`examples/agent_browser_retained_completion.py`。冷启动浏览器前缀重建、remote reader、正式部署, +以及暂缓的原生/浏览器/真机/24 小时验收仍待完成。 + +已停止且副作用已确认的任务,可用 `manage_agent_recovery("preview_completion", {"task_id": id})` +审核独立验证任务,再将精确 task_id/snapshot 与审核说明交给 `create_completion`,最后完成新任务。 +私有原子绑定只选择永久只读 helper,不重播来源动作;须有新鲜独立完成条件与输入退出证据。 +skill 计划须全部确认;动态任务不得含未处理的有限计划或未知效果。 +可先 observe 再 finish;相同 helper 配置只重新检查就绪,不替换权限,也不缓存就绪结果。 +来源/审核者权限持续有效,覆盖清理后、明确重试与重启。API/AC/MCP/REST/CLI/Builder 及 GUI Actions 共用此流程。 +remote reader、正式部署仍列于 Progress.md;桌面能力仍须另行原生验证。 + +只有受管任务节点的 DAG,可用 `manage_agent_dag("register", {"definition": graph, +"max_parallel": 4})` 注册持久批次,再明确 `run_dag(graph, batch_id=batch["batch_id"])`。 +注册不操作目标;保存整张图的拓扑、节点契约、主机设置与并行数,目标端 key/规范标记绑定批次。 +可能派送前先提交 claim,目标端精确规范、完成及输入释放证据通过后才放行依赖节点。成功、中断或 +提交回复遗失后都不能再次 begin;`get/list/inspect` 让协调记录跨重启保留。API/AC/MCP/REST/ +CLI/Builder 及 DAG Actions 的批次注册/读取、选填批次 ID 共享流程。 +停止后用 `review_continuation` 获取只读整图快照及逐节点决策,再把审阅的 `snapshot`、`decisions` +与非空 `note` 放入 `run_dag(graph, batch_id=id, recovery=request)`,批准并使用一次续接机会。 +只能采纳独立完成的原任务或真实 recovery 后继任务;派送限从未 claim 且目标端未接收的 pending +节点。本地授权可在相等或更窄根目录内更新,未知 claim 永不重放。DAG Actions 提供停止新派送、 +审阅及明确续接;已接受任务仍依自身生命周期处理。将协调交给已明确启动的服务,可调用 +`manage_agent_dag("run_background", {"batch_id": id, "definition": graph, "max_parallel": 4})`; +明确批准的续接另带 `approval_id`。DAG Actions 提供两个后台动作;关闭视图不停止已接受的服务工作, +`get.background` 提供有限队列状态。重启使旧 attempt 失效并要求审阅,不重放排队或未知派送。 +原 owner 与提交者的权限持续重新验证,本地任务绑定所属 runtime。 +既有 `prune_agent_tasks()` 与每小时维护会回收过期且未使用的注册及已安全结束的成功批次,默认 30 天。 +未决批次持续保护任务/恢复证据与接收 gate;结果新增 `deleted_batches`、`deleted_dag_deliveries`。 +其他队列与用户成果不受影响,远程证据保留仍须明确移交契约。 +caller 协调的受管批次固定来源服务路径、端点、凭证指纹及世代,本地节点共用同一 client;连接文件 +身份变更就停止后续调用并要求明确审阅。服务端批次证据直接读取所属 runtime,绑定不缓存 bearer +凭证。普通非批次 client 保留动态连接行为;受管批次须有含世代的连接数据。 +本地批次节点在持久 claim 后使用来源服务的封闭 `local_task` transport,以原 owner 接收精确规范/ +key,并在事务内记录真实 caller。输入前更新双方权限及 attempt;管理员失去跨 owner 管理权也会 +阻止执行。没有可信接收记录的旧请求不补造见证。任务 metadata 提供有限 `local_dag_admission` +审计数据,已接受输入仍依既有清理契约处理。 +若恢复后继任务须让原所有者读取,preview/review_authorization 请求加入 +`owner_policy="source_owner"`,明确 create/create_authorized 时另带回 `ownership.review` 为 +`ownership_review`。后继任务保留来源所有者,事务内另记实际审核者,输入前持续验证双方权限。 +GUI 提供所有者选择;省略策略仍由创建者持有,沿用既有读取隔离。DAG 可用正常恢复证据采纳独立完成 +的原 owner 后继任务;已存在的 caller-owned 子任务不自动变更归属或补造此记录。 +详见[续接协议](../../source/Zh/doc/ai_agents/agent_dag_batches_doc.rst)。 + +触发器可明确使用 `manage_agent_trigger("review_authorization", {"trigger_id":"..."})`,再以 +`create_authorized` 提供 `trigger_id`、`snapshot`、`authorization_review`、经审阅的 `spec` 与 `note`。 +新注册保留完整模板/设置/待处理上限,受原授权、仍有效限制与当前权限交集约束;事务内停用旧绑定, +并启用未来通知。共享历史让已接受事件与未完成任务跨更新、移除及重启保留,继承的旧排队事件不再派送。 +计划从未来时段开始,文件检查点保留。API/AC/MCP/REST/CLI/Builder 及 GUI 触发器菜单共享流程; +普通启用不能取代失效授权,审阅只准备注记留空的请求。 + +已发布技能可用 `manage_agent_skill("review_authorization", {"candidate_id":"..."})`,再明确 +`create_authorized`,提供 `candidate_id`、`snapshot`、`authorization_review`、经审阅的 `spec` 与 +`note`。完整计划与参数定义固定;保留原根目录上限及仍有效限制,与当前权限取交集。流程只创建 +同一技能的新草稿及审计证据,须重新验证并明确发布下一版,旧版本不变。相同批准去重,过期版本/ +授权内容拒绝。API/AC/MCP/REST/CLI/Builder 与 GUI 技能操作菜单共享此流程;trigger 更新使用上方独立流程。 + +来源授权失效的停止任务,可明确使用 `review_authorization`,再以 `create_authorized` 提供 +`task_id`、`snapshot`、经审阅的 `spec`、`note` 与 `authorization_review`。新任务保留所有仍有效的 +来源限制,将当前权限与原根目录上限取交集;根目录只可维持或缩小,其余权限、模式/模型、预算及 +完成条件固定。批准证据与唯一新任务在同一事务保存;来源及已撤销的见证不变。现有共享接口均提供 +这两种操作,GUI Actions 另有授权审阅/创建命令,详见[恢复指南](../../source/Zh/doc/ai_agents/agent_recovery_doc.rst)。 +任务恢复不解除输入隔离,也不重建应用状态;技能与 trigger 使用上方独立更新流程。 + +停止的任务可用 `manage_agent_recovery("preview", {"task_id": "..."})` 审阅来源回执与快照, +不接触应用程序。有限 skill 提供剩余动作及逐条结果;外部 agent/本机模型任务则提供空白目标的 +`review_template`,须由操作人明确填写剩余工作目标,不复制旧动作列表。明确 `create` 时提供 +快照、经审阅的规范与注记,创建有来源关联的新任务,重新观察并从零回执开始;重复批准返回同一 +任务。执行模式、模型/端点、范围、预算及完成条件固定,未知副作用须先人工核对;不移植旧 +capture、索引、坐标或已完成历史。可用 `AC_agent_task_recovery`、MCP/REST、 +`agent-task recovery preview|create request.json`,或「Agent 任务 → Actions → 审阅剩余工作/ +重新规划/创建经审阅的新任务」。已移交的来源不能再恢复,须由新任务继续。 +登录与窗口状态的恢复须明确声明,不能推断:继任任务(或任何任务)可列出 `resume_conditions`,只接受 +`screen`、`browser` 与 `file_*` 条件(回执是历史,不能证明现状);第一个动作只在新观察全部通过时 +才被接受,任一不成立或无法判定就转为 `waiting_user`,不会动作;有任何动作回执后此关卡即结束。 + +Android/iOS 内置受管 profile 仍未提供。内部远程副作用防护按实体设备标识保存动作前/后确认; +本地 helper 结束但动作未确认时,仍保留隔离。恢复须在 writer 退出后取得可信设备证据,再以 +后续能使旧指令失效的世代证明安全。尚无内置 SDK 证据来源、设备 profile 或原生验收; +剩余接合列于 `Progress.md`。 +内部 Android 传输只连接明确设置的现有 loopback ADB server,不调用 CLI、不管理 daemon、 +不重试或退回旧 shell;shell-v2 的退出证据有封包/输出上限,但不代表应用完成、实体设备 +身份或输入已释放。 +内部 Android session 会核对指定端点、实体序号、boot 与默认显示器焦点,并以原子方式固定 +boot。有限输入提案在命令连接内重验身份/焦点,限制文字与结果;提案不授权输入,仍须接合 +输入窗口、遮挡、锁定/真人活动与自有 worker。 +Android 检查后提案会绑定当前的原生输入窗口/队列及 keyguard 证据,核对完整触控路径、 +外部拦截与遮挡,并在命令连接内重验摘要。旧 ANR/历史记录不能证明当前状态;真人活动、 +全局监视器审阅仍须可信来源授权,内置受管设备执行仍未开放。 +内部 Android 动作协议 v2 区分完整前置拒绝、输入失败、输入后拒绝与输入返回。 +缺少/错误阶段或退出码不符都维持未知;输入返回不代表远程输入已清空或任务完成,也不授权重试。 +内部自有远程 SDK worker 会核对精确任务/所有者范围、重新授权与真人接回;可信主机 factory +创建前先启动 parent 监视。持久化 begin 并收到 ACK 后才调用 SDK,相符设备/世代的清理证据 +通过后才发送 end;缺证据维持隔离。可信设备控制来源、WDA adapter 与受管 profile 仍待接合。 +命令编译器以一次带标签的提取核对三个原生焦点字段,接受六种顺序,缺少/重复/空值仍拒绝。 +前后身份与输入安全检查、原本动作期限均保留。自有 POSIX 假设备减少 Git Bash 读取进程且维持 +原始文件 bytes;有限阶段/耗时诊断不含命令、参数或输出。 +内部 AndroidRemoteAdapter 已通过逐命令 AndroidCommandLease 接合 checked session 与 worker; +每个动作消耗一次新的身份/输入路由/安全观察,SDK 重新编译有限命令后才通过 ADB 发送一次。 +设备端防护须在真人接回、取消或到期后阻止旧写入;没有默认 provider,标准 ADB 或停止本地 +helper 不能提供这项保证。清理证据还须绑定新的随机命令 ID、boot 及独立输入/队列状态。 +可明确配置主机 hierarchy_reader,提供有界、限 app 的语义元素及经过审阅的非敏感文字;未配置时 +仍只有身份 metadata。XML 不授予文字权限;编辑/密码值及受保护子节点持续遮罩,不发布原始 +XML 或私有 freshness hash。公开观察版本随来源及动作更新;Android 元素引用须来自当前可操作 +的语义元素。新的画面读回可确认已审阅文字出现,缺少/部分/遮罩内容不能证明文字不存在。 +不新增 CLI/SDK 启动或捕获备用;真实来源、受保护字段值验证、Unicode/IME 与受管 profile 仍待交付。 + +受管画面完成验证将内置桌面与 WebRunner 预览视为部分文字证据;文件目标与等待窗口阶段没有 +语义画面证据。已知安全文字可确认出现或推翻不存在条件,遮罩与明确隐藏的标签不可作证。 +组合条件缺少任一必要证据时保持未知,已知矛盾则判定失败。精确 DOM/字段值应使用明确的 +浏览器完成读回;未声明覆盖标志的自定义 target 保留既有行为。 + +`lookup_agent_task("键", reviewed_spec)` 可选择由目标主机规范化规格,与原所有者提交时保存的 +不可变摘要比较;回复声明 `spec_match_contract=1`,并提供一致/不同/无法核对/查无记录。 +CLI 可加 `--spec reviewed.json`;AC/MCP/REST/Builder 共用可选对象。DAG 视图先查键,再在 +目标端明确支持契约时核对已审阅的节点规格;旧端保持 `unverified`,本地来源 witness 不发到远程。 +键改指向别的任务会使旧快照失效;规格一致时仍须核对完成报告的种类、数量与通过结果。 +节点比较不等于整个 DAG 拓扑/原批次批准, +`resume_permitted=false` 仍保留明确继续审阅。 + +`inspect_agent_dag(definition, timeout_seconds=30)` 可查看本地/已登记远程主机的现有提交, +不提交、不暂停、不续跑。提供 `AC_agent_dag_inspect`、MCP、REST 动作、CLI +`agent-task inspect-dag reviewed.json`、Builder 与 DAG Actions。最多 100 节点、最长 300 秒; +远程仍须主机管理权限,不发送本地身份/数据库路径/来源 metadata,不返回远程路径或原始错误。 +`recorded_completion` 仅描述查回的任务;节点规格可选择核对,`resume_permitted=false` 仍表示尚未 +授权整个 DAG 继续。查无记录不代表拒绝;GUI 在图编辑后丢弃旧视图。 + +提交回复丢失时,可用 `lookup_agent_task("原去重键")`、`AC_agent_task_lookup`、MCP、 +`POST /agent/lookup`、CLI `agent-task lookup 原去重键` 或任务视图 Actions 查询。仅读取原身份及 +用户数据库范围,不提交、不续跑、不取得输入控制权;`found=false` 只是当前快照,迟到请求仍 +可能被接收。GUI 不会让旧查询回复覆盖后来选择的任务/键。DAG 视图也使用此查询;规格绑定及继续审阅仍待完成; +只读查询仍须具任务访问权限。 + +现有 `run_dag`/`AC_run_dag`/MCP `ac_run_dag`、REST/CLI 动作文件、Script Builder 与 DAG +Actions 菜单支持受管任务节点:以 `task` 替代 `actions`/`action_file`,包含 `spec`、必填的 +`idempotency_key` 与可选的 `wait_seconds`。省略 `host` 使用明确启动的本地服务;远程使用管理员 +已登记的主机。目标端须已配置有后台派送的授权 runtime,本功能不部署服务。规格限 skill 或明确 +配置的本地模型模式,工具、目标主机路径及完成条件由目标端验证。 +节点只提交一次,等待完成条件通过、持久完成契约及输入释放证据后才启动下游。同一批次恢复 +须保留去重键;不自动恢复暂停任务或重放副作用。停止、超时或通信/权限失败时,已知任务 ID +才会提出有时限的暂停;未收到确证仍为未知。失败结果保留 ID/去重键并阻止依赖节点,GUI +表格显示任务 ID。本地身份、用户数据库路径及来源 witness 不发送到远程。正式多机部署及原生/ +设备验收仍分别跟踪。 + +DAG 类型与函数也可从 `je_auto_control.api`/`je_auto_control.api.core` 导入。 + +受管 HTTP 暂停/取消/停止全部/关闭服务使用独立的每 IP 配额,与普通流量同为每分钟 120 次、 +突发 30 次;状态查询不会耗尽停止请求的配额。登录、实时角色、任务归属、审计与有界输入清理仍须 +通过。共享客户端也为 DAG 批次/节点暂停保留传输容量;`/agent/dag` 的控制标头仅接受封闭的暂停 +请求,其他带标记的操作在派送前拒绝。自定义认证门保留自己的契约;这不保证 OS/网络饱和时的优先权。 + +受管任务在确认输入清理后才发布成功。清理失败或仍忙碌时保留输入租约并要求审阅;确认前 +中断仍需恢复。完成发布采用条件式状态转换,不覆盖同时到达的取消请求。现有 GUI/API 任务 +结果通过 `metadata.input_released` 显示释放状态;新成功记录保存 `completion_contract=1`,旧记录 +保持零而不自动认证。产物报告按最终状态更新,供后续 DAG 协调判断。 + +DAG 节点在线程池中保留调用者授权、取消与指令限制,自定义 runner 同样适用。每个节点执行前 +重新读取用户权限;已删除的用户会使节点失败,后续依赖节点跳过,各操作按更新后的角色 +检查权限。默认远程节点在打开主机通讯录或动作文件前要求 `manage_hosts`,避免通过主机凭据 +扩大本地操作权限。管理员及受信任的直接 Python 调用仍可远程派送。受管节点采用上述完成 +验证与停止契约;正式多机部署及原生验收仍待完成。 + +浏览器主机目标可通过可选的 `settings.helper_python` 指定已审核且已安装包的 Python +环境(本机绝对解释器路径)。明确指定的 helper 使用 `-I`,从该环境加载已安装包;虚拟环境 +解释器的符号链接保留环境身份。任务选项不能指定解释器。 +主机管理员可使用 `manage_agent_target("probe", {"name":"reviewed-browser"})`、`AC_agent_target`、 +MCP/REST、`agent-task target probe request.json` 或 GUI 主机目标的诊断操作。 +诊断以独立且有时限的自有 helper,通过 `je_web_runner` 检查浏览器依赖后结束,过程不获取输入 +所有权或启动浏览器。结果可显示 `python_dependencies_ready`;浏览器启动及原生证据仍明确保持 +`not_probed`/`not_recorded`。`last_probe` 仅为内存中的带时间诊断快照,不授予任务权限, +也不启用已禁用的目标。桌面/设备的原生诊断仍待完成。 +已准备的隔离环境安装两个功能工作树构建的 wheel;共享环境与正式工作树保持原状。正式服务 +配置及实际浏览器验收仍单独跟踪;所有浏览器自动化仍统一由 WebRunner(`je_web_runner`)提供。 + +桌面固定技能现在与浏览器技能共用会话连续性检查。桌面 scope 或自有 helper 结束后, +沿用旧前缀前必须审核,不能用历史记录证明暂停后的表单/窗口状态。未中断的会话可正常 +运行;文件 adapter 仍以持久化产物处理恢复。检查在替代 helper 启动前执行,现有继续运行/状态/ +记录接口会显示人工审核结果。暂存表单/登录/窗口状态恢复与可审核的剩余步骤重建仍待完成; +原生验收保持暂停。 + +固定浏览器技能的已验证前缀,现在必须保有原本仍存活的浏览器/helper 会话。 +暂停、清理、helper 中断或 runtime 重启后,旧动作记录无法证明表单仍保有之前的字段值; +继续运行会在启动替代 helper 或发送下一动作前进入人工审核。请明确检查剩余步骤并创建新任务。 +尚无保留尝试记录的暂停,以及已审核为 failed/not_applied 的尝试,允许全新开始。 +外部拥有者仍可重新观察新会话,再规划授权范围内的新动作;未中断的固定技能沿用原 +会话。登录及暂存表单状态的恢复仍是未完成工作。 + +本机 runtime 的用户及实时根目录授权转发,现在必须由明确的本机服务调用启用。 +普通具验证的 HTTP 请求仅携带指定的 Bearer token;runtime client 验证 loopback 服务目的地与 +路由后,才附上本机用户/来源存储库/witness 信息。版本化 `je_auto_control.api` 现在提供 +所有已声明的 `api.core` 名称,包含受管浏览器命令、目标恢复及技能;动作类型 stub 也涵盖 +所有出货命令。未解析的延后项目类型沿用生成器原有的 `Any` 策略,避免生成无效名称。 +并发预算读取改在数据库独占事务内采样时钟,避免锁获取顺序不同造成任务误判超时;真正的 +时钟倒退仍会停止任务。GUI/MCP/REST/CLI 共用这些修复;正式工作树及现有原生/浏览器/ +设备/24 小时验收暂停保持原状。 + +受管浏览器文件命令 `browser_link`、`browser_download`、`browser_upload`(对应 `AC_browser_*`) +委派给 WebRunner 传输契约版本 1。上/下载授权必须具有明确的主机及任务根目录;下载让浏览器 +Cookie 保留于自有 SDK/helper,核对完整长度及可选 SHA256,且不覆盖现有文件;复用必须符合 +指定 SHA256。上传将最多 4 MiB 的单个普通文件读成核对过的不可变快照,验证可选 SHA256 与 +SDK 元数据,不自动提交表单。网络操作仍全部位于 `je_web_runner`。 +浏览器 `download_archive` 预览接受查询页 `url`、明确 `allowed_origins`、授权范围内 `directory`, +以及具有单纯 `name`、`url` 或链接 `selector`/可选 `frame` 的 `files`;每文件可用 `page_url` 覆盖 +查询页。流程获取新链接、下载每文件最多 16 MiB,并生成供独立核对名称/大小/哈希的归档清单。 +GUI Actions 仅起草文件目标/流程/上传示例,不启动资源;MCP/REST/CLI/Builder/模型工具 +共用命令,链接读取仍需输入控制权限。部署与实际浏览器验收仍待完成,现有验收暂停保持生效。 + +浏览器任务可固定完成条件,例如 +`{"kind":"browser","operation":"value","selector":"#field","value":"expected"}`。 +操作为精确的 `text`、`value`、`visible`(布尔)或 `url`(不含定位);必须明确授权 +`AC_browser_read` 与任务 origins,完成条件不会增加权限。Finish 由同一个自有 helper 检查 +当前页面位于允许的 HTTP(S) origin,再通过受控读取命令独立取得 SDK 完整值;既有 receipt、 +有界预览或模型停止信号不能代替读回。空白/不可用/范围外页面、被拒读回或错误验证回复 +保持未知;比较不符保持失败。取消、权限撤销及人工审核错误保留原类型。 +GUI Actions 可起草不启动资源的浏览器完成示例;API/MCP/REST/CLI finish 共用验证器。 +SPA URL fragment 会保留,origin 比较仅略去 fragment。实际浏览器/应用验收及已审核传输仍待完成。 + +受管浏览器启动前,必须先确认 WebRunner 的 `ManagedBrowserSession.contract_version == 1`, +通过后才创建 policy 或开启代理/浏览器。缺失、布尔、文本、过旧或未知标记会保留可处理的 +就绪错误。SDK 来源 `575e5d2` 提供完整 text/value 读回:最多 8,000 个 UTF-16 code unit, +超限或无效 Unicode 即拒绝,不截短。AutoControl 对浏览器参数与流程预览数据应用相同 Unicode +上限,在副作用前拒绝。跨源契约通过真正的自有 helper 与替身 Chromium 验证;部署与实际 +浏览器/原生验收保持单独记录。 + + +`draft_agent_workflow("batch_form", config)` 与 `transfer` 可设置 `backend: browser`, +并提供明确的 `allowed_origins` 与已审核 browser target。CSV/XLSX 来源仍受 roots 限制; +浏览器草稿仅生成 `AC_browser_*` 动作,不退回桌面输入。填表提供 `url`、CSS `fields`、 +可选 frame/新建记录控件、提交与确认 selector;每次填入都有独立的精确 value 读回。 +可用 `confirmation_column` 从每行取得预期确认文字。转填提供 `source_url`/`destination_url`, +提取 text/value、应用白名单转换、填入并读回目标字段,再验证保存;提交前拒绝陈旧确认。 +`AC_browser_wait`/`browser_wait` 仅轮询 text/value,也支持稍后才出现的元素;`wait_seconds` +默认 5 秒,受 action budget 限制,超时才返回的匹配结果仍拒绝,不重放填入或点击。 +Python/core、共享 catalog/模型 schema、MCP、CLI/REST 任务操作、Builder 及 GUI 流程预览 +使用同一编译器。浏览器读回可作为独立技能证据。实际应用验收与正式上/下载设置仍待完成; +SDK 启动前须通过完整有界读回契约版本 1 的检查。 + +受管浏览器 profile(`kind: browser`)统一委派给 WebRunner 的 `je_web_runner` SDK; +开发来源为 `D:\Codes\WebRunner`,集成来源位于其隔离的受管 session 功能分支。 +Profile 必须提供精确的 `settings.allowed_origins`、浏览器专用工具,且不能授权桌面 app; +每项任务另须设置非空、更窄的 `options.allowed_origins`,每次激活均重新核对两层范围。 +注册不启动资源;helper 环境须明确安装已审核的受管 SDK 与 Chromium,缺少时就绪失败,不自动安装。 +`AC_browser_navigate`、`AC_browser_click`、`AC_browser_fill`、`AC_browser_select`、`AC_browser_check` +及 `AC_browser_read` 共用 Python/core、executor、MCP 与 Builder 定义。命令仅在受管 helper 中 +运行,通过既有 task submit/observe/act 周期驱动。读取操作为 `text`、`value` 或 `visible`; +WebRunner 拒绝秘密表单字段。DOM 索引在当前 observation 内解析 selector/frame,再核对新鲜度。 +失败副作用保持不确定且需对账;暂停/取消会结束拥有的资源。GUI Actions 可生成浏览器目标示例 +供审核;DOM 选择仅编辑动作请求。专用 helper 跨就绪检查保留同一个全新 session,正常清理先 +取得浏览器 ACK,再结束自己的进程树;符合完成审核条件的来源则将原本已冻结的 context +移交 runtime 有界保管。浏览器任务不获取共享桌面输入控制权。跨源受控测试使用真正 SDK、 +替身 Chromium、自有 IPC/loopback;实际浏览器/原生验收、正式传输设置及其余浏览器流程类型仍列于 `Progress.md`。 + +MCP 异步调用会保留接受请求时的角色、session、原路径策略与工具列表;session 或路径策略 +结束后,延迟分派会被拒绝。异步无状态调用仍使用固定 profile。插件工具列表变更会送达所有 +有效 HTTP session 流;session 启停只通知拥有者,并避免重复发送。流注册与 HTTP 标头 +共用锁,避免提早发送的通知破坏 HTTP 响应。 +纯 metadata 的 `benchmarks/mcp_discovery.py --repeats 20` 测量工具数、JSON bytes、预热后的 +进程内握手、搜索与启用耗时。Windows/Python 3.14.4 的记录中,完整模式初始有 732 个授权工具、 +358,029 bytes;渐进模式为 5 个、2,029 bytes,响应大小减少 99.43%。握手为 58.263/47.439 ms, +搜索中位数为 16.243/19.718 ms;渐进启用中位数为 42.486 ms。此本机测量不含冷启动导入及原生操作。 +有日期的 JSON 记录位于 `docs/benchmarks/`;既有参数策略的覆盖限制仍列于 `Progress.md`。 + +MCP 可选择 session 渐进揭露:`je_auto_control_mcp --tool-mode progressive` 初始只提供五个 +探索控制工具;`ac_mcp_tools_enable`/`ac_mcp_tools_disable` 只改变该 session。 +不会更新工具列表的客户端可使用 `--tool-mode static --tool-profile ac_screen_size,ac_list_windows`; +默认 `full` 保留不分页的授权工具列表。渐进/固定模式的 cursor 不透明、只能使用一次,并绑定 +快照与调用者;工具、角色或列表设置变更,以及 cursor 过期时,须重新运行 `tools/list`。 +启停只通知拥有者连接;session 结束会回收 cursor 并使尚在运行的 metadata callback 失效。 +HTTP/嵌入式使用 `MCPServer.configure_tool_disclosure(...)`;主机环境变量为 +`JE_AUTOCONTROL_MCP_DISCLOSURE` 与逗号分隔的 `JE_AUTOCONTROL_MCP_TOOL_PROFILE`。 +`plan_mcp_tool_profile(...)` 及 Diagnostics Actions 可预览启动参数,不会启动服务。 +无状态协议使用不分页的初始固定列表,不保留 session 启用状态。只读限制也覆盖后续新增的插件。 +未验证/共享 token 连接显示 operator 工具,与既有调用上限一致;主机管理工具仍须已验证身份。 + +MCP 工具探索提供 `search_mcp_tools(query, limit=10)`、`get_mcp_tool_schema(name)`、 +对应 AC/MCP 命令及 Diagnostics → Actions。搜索返回有界摘要、分类与所需权限;完整 schema +须指定单一工具查看。两种查询都重新验证角色,并遵守 registry 的只读筛选;MCP 查询使用该 +server 的实时 registry,包含插件变更。CLI 可运行 +`je_auto_control_mcp --search-tools document --limit 5` 或 `--tool-schema ac_mcp_tool_search`。 +完整模式仍为默认;各 session 的渐进揭露可按前述设置启用。 + +Agent 工具调用经 `executor.execute_one(name, arguments)` 返回原始结果,与动作脚本共用 +授权、变量插值、取消及日志边界;拒绝私有 executor 参数。受管任务交付进度见 `Progress.md`。 + +输入控制权会在分派及输入确认前写入持久记录。服务崩溃后,先手动释放按键与鼠标按钮,再以主机管理权限调用 `recover_agent_target(target, note)` 记录审核并恢复目标;任务未知结果仍须另外核对。工作区文档由输入 helper 之外的进程启动,指定的聚焦步骤会等待授权应用程序窗口就绪。 + +受管技能将已验证的语义流程录制为不可变候选。`manage_agent_skill` 可预览具有类型的参数、执行独立验证任务,并在明确审核该候选的成功证据后发布编号版本。定位器修复会产生须重新验证的候选;任务固定使用原版本与摘要。AC/MCP/REST/CLI 与 Agent Tasks 的 Actions 菜单提供相同操作。 + +原验证试跑的动作若已全部确认,可明确审核/创建并完成独立只读验证任务,再以 +`manage_agent_skill("accept", {...})` 提供原 `task_id` 与可选的 `completion_task_id`。 +发布保留精确候选/试跑摘要与 pin,核对最多十六层真实只读恢复链、实时权限及独立完成/清理证据。 +原试跑维持停止,动作不重播;Actions 菜单可准备待审核请求。发布记录在临时 reader 证据到期后 +仍保留历史 ID/摘要;尚未发布的采纳仍须有留存证据。 + +停止的原流程也可通过 `manage_agent_skill("record", request)` 明确提供 `completion_task_id`。 +`task_id` 仍指原流程,草稿保留其已确认语义动作,另采纳只读 reader 的私有独立完成证据。 +录制不重播动作、不改来源状态;来源/证据检查与草稿写入共用事务,并重验实时权限。 +`provenance.completion_review` 在 reader 保留期后只是历史记录,不授予当前权限。 +草稿与新增验证条件仍须自己的新验证试跑,不能直接发布;Actions 菜单只准备录制请求。 + +原验证试跑只执行部分动作时,先调用 `manage_agent_skill("review_execution", request)`, +提供 `candidate_id`、原 `task_id` 与另一个最终 `execution_task_id`;再以相同 ID、返回的 +`execution_review`、`expected_version` 及非空 `note` 明确 `accept`。最多十六层真实可执行恢复链 +必须确认完整原语义计划;不同的剩余流程即使成功也不足。比较包含 JSON 类型、capture 值、预期结果 +与 grounding,但不恢复旧 capture 或重建历史 UI 状态。各任务保留原限制与独立批准;当前 caller、 +全部 owner 及实际创建审核者都须持续有权限。版本、发布及历史 `publication.execution_review` +共同提交或回滚,写入后再次检查证据与权限。原试跑维持停止并保留 `publication.task_id`,不补造子任务 +为 validation trial。可选 `completion_task_id` 必须验证最终可执行任务的效果,其证据嵌套存于 +execution 审核记录;过期证据不能批准未发布候选。两个 Actions 示例只准备审核/接受请求, +`agent_skill_execution_review.json` 与 `agent_skill_execution_accept.json` 可编辑后使用。 + +受管任务保留来源路径策略:移除根目录后,后续动作、事件触发及技能验证会受阻。MCP 客户端根目录按会话隔离,来源授权结束后撤销;主机配置的固定策略则在明确更换前保留。服务停止会取消实际执行中的工作,包括取得输入前的模型初始化,尚未启动的投递则持续保存。 + +实验性的[受管 Agent 任务](../../AGENT_TASKS.md)提供所有者范围内的提交、观察、动作、验证、 +暂停、恢复、取消、控制权代次、持久化回执、WorkQueue 派送与本机 Ollama 推理。 +Python、AC、MCP、REST、CLI 与 Agent 任务面板共用后台服务,明确执行 +`je_auto_control agent-task start` 才启动;新流程不强制依赖外部服务。 +四条可预览模板涵盖下载归档、CSV/XLSX 填表、跨应用转移与工作区准备; +使用 `agent-task draft` 或 Actions 的「预览工作流程」检查后提交。 +持久化间隔、Cron、文件与事件绑定会保留核准范围,每次触发重新授权并去重; +提交标识避免重试与重启时创建重复任务。 +提供所有者范围内的回执与结果不明对账,关联执行历史、journal 及逐条报告; +服务缓存默认保留 30 天,保留用户输出与外部 journal。 +证据缓存以完整数据库路径及持久数据库身份绑定于 `.agent-evidence-cache/`。 +还原的数据库与旧版缓存保留原历史引用;下次动作或报告创建新的自有 journal 分段, +不读取或移动历史文件。任务 metadata 的 `artifact_cache_state` 为 `owned` 或 `historical`。 +保留清理只移除当前数据库可识别的自有缓存文件;历史文件保留,留存的私有根目录禁止成果导出。 + +Linux 上的 helper 程序可改由可选的 [owner 服务](../../../native/owner_service/README.md) 运行: +root guardian 把每个 helper 放进它自己的 cgroup v2 树,helper 帐号无法离开;关闭 channel 会 +结束整棵树(含逃离的后代),guardian 重启后会清理崩溃留下的程序。root 拥有的 +`/etc/je_auto_control/owner_service.json` 绑定档只让完全列出的 helper argv 经由服务启动; +驱动桌面或浏览器的 helper 一律以本机程序运行,因为受保护的 helper 以独立 ID、空环境运行,无法存取显示; +没有绑定档时 helper 仍以本机程序运行,`agent-task status` 在 `helper_containment` 回报模式。 +Python 包不会构建、安装或启动服务,且在审阅后的版本开启闸门前,构建出的服务拒绝受保护启动。 + +`agent-task readiness`(`agent_runtime_readiness`、`AC_agent_runtime_readiness`、MCP 工具及 Agent 任务面板的 +Actions 菜单)报告桌面输入与截取、真人在场来源、Android 与 iOS 控制、浏览器和本机模型各自的状态: +`unsupported`、`missing_dependency`、`unauthorized`、`not_probed`、`not_recorded` 或 `measured`。它只读环境变量、 +`PATH` 与已安装包,不连接设备、不启动 helper、不请求权限,所以不会报告 `measured`,每一项的 +`native_evidence` 都是 `not_recorded`;已安装的工具只算 `not_probed`,不代表可用。 + +部署或回退前须比对来源与制品哈希,不能只凭相同版本号判断私有缓存兼容性。 +不具此私有根目录保护的旧程序不得沿用新版数据库/缓存。经审核的回退须使用匹配的升级前状态 +及其原记录位置,先取得自有输入退出确证,并从所有旧版任务根目录排除留存的新版私有文件; +保留不明 journal,不重放副作用。无法核实时维持兼容版本。 + +Windows USB 枚举明确以 UTF-8 输出及解码,PowerShell 子进程保持隐藏。 +Python UTF-8 模式开启或关闭时,Unicode 设备名称与诊断均完整保留;枚举仍为只读。 +原生调用使用专属 helper,支持取消、超时、输入记录清理与跨数据库的桌面排他控制。 +Windows 共享桌面的持续来源跨 runtime/任务/helper 共用,监看开始后须重新累积解锁空闲 60 秒。 +仅支持已确认的活动本机 console;远程、shadow 及未知 session 一律拒绝。 +每个 helper 在输入 ACK 前后实时核实同一主机租约;来源/reader 失效会暂停输入, +未确认的按住输入清理仍保持隔离,须明确重试。关闭一个 runtime 不会停止其他 runtime 的来源。 +目标说明只公开粗略 `presence` 状态与 `native_evidence=not_recorded`,不启动探测。 +`agent-task stop-all` 停止可见任务。 +其他共享桌面须有可信活动 adapter。原生平台验收与其余待办列在 `Progress.md`。 + +Linux 内部 presence_peer_linux 以不可继承的 pidfd 保留原始 Unix stream 或 seqpacket 连接者, +核验账户、进程创建时间、namespace 与存活状态,不另依 PID 打开进程。进程身份不代表桌面或输入权限。 + +内部 LinuxListener 与 LinuxChannel transport 拥有受保护的 Unix endpoint、socket 与 peer。 +每个有界 JSON 数据包须有仍存活的原始 writer 的内核凭证与 pidfd;额外、缺失、负值或截断的控制数据 +直接拒绝,收到的描述符在交付前释放。排队与 I/O 共用同一期限;取消撤销交付,尚未完成或失败的 +清理维持未确定。未知文件系统对象保留不动。路径权限不能隔离同 UID 的敌对进程,用户空间的有界 +等待也不保证内核 syscall 的硬实时完成。 + +X11 与 macOS 已有真人活动来源。X11 只计入真实设备的 XInput2 raw 事件(XTEST 从属设备一律排除), +并从 logind 读 `Active`/`LockedHint`;没有 logind 或 `XDG_SESSION_ID` 时视为锁定。macOS 用只读的 session +event tap(需要辅助功能权限);只有进程从非 HID 来源状态发出的事件才算注入,有疑义时让任务等待而不是接手。 +Wayland 没有可信来源。Linux 的 presence broker、worker 与 server 已改经此 transport:自有 worker 绑定 +全新的私有 endpoint 并在 bootstrap 回复中报告,broker 只采用该 endpoint,连接时先核对 listener 即其所列 +进程,再做 presence challenge。macOS 尚无 presence transport;原生验收前 runtime 仍拒绝非 Windows 共享 +桌面任务;此 transport 不是完整 Linux 应用或原生输入验收。 + +[![PyPI](https://img.shields.io/pypi/v/je_auto_control)](https://pypi.org/project/je_auto_control/) +[![Python](https://img.shields.io/pypi/pyversions/je_auto_control)](https://pypi.org/project/je_auto_control/) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../../LICENSE) +[![Documentation](https://readthedocs.org/projects/autocontrol/badge/?version=latest)](https://autocontrol.readthedocs.io/en/latest/?badge=latest) + +**AutoControl** 是一套开源、跨平台的 **computer-use 与 GUI 自动化框架**,面向 AI agent、Python 应用程序与自动化测试。它能驱动鼠标与键盘、通过模板匹配、OCR、操作系统无障碍树或视觉模型找到 UI 目标、录制与回放操作流程,并以 JSON 动作文件执行—— +支持 Windows、macOS、Linux(X11 与 Wayland)、BSD、Android 与 iOS。 + +每项能力都以三种形式提供:**Python API**、可在 JSON 文件/CLI/服务器使用的 **`AC_*` 动作命令**, +以及 **GUI 标签页**。没有任何功能只存在于 GUI。 + +**[English](../../../README.md)** · **[繁體中文](../../../README/README_zh-TW.md)** + +--- diff --git a/docs/guides/zh-CN/integrations.md b/docs/guides/zh-CN/integrations.md new file mode 100644 index 000000000..3f4a6ab33 --- /dev/null +++ b/docs/guides/zh-CN/integrations.md @@ -0,0 +1,125 @@ +# Agents and integrations + +[README](../../../README/README_zh-CN.md) · [Documentation](../../README.md) + +## AI Agent 与 Computer Use + +**AutoControl 是开源、跨平台的 computer-use 与 GUI 自动化框架。** + +当 AI agent 需要操作真实桌面、原生应用程序、真实浏览器窗口、远程桌面或移动设备,而不只是操作浏览器 DOM/API 时,使用 AutoControl。 + +### 何时选择 AutoControl + +- 真实鼠标与键盘输入 +- 屏幕截图与坐标操作 +- OCR 与原生无障碍树 +- 图像/模板匹配 +- Vision-Language Model UI 定位 +- Anchor 与 self-healing locator +- 跨平台桌面/移动设备自动化 +- JSON 动作文件 +- MCP computer use + +建议的 agent loop: + +**observe → identify → act → wait → verify → recover** + +完整的 [AI Agent 指南](../../../AI.md) 提供 MCP 配置、工具选择、OpenAI 集成、安全性与 computer-use 关键词。 + +### AI-friendly MCP + +```bash +pip install je_auto_control +je_auto_control_mcp +``` + +MCP 提供完整的 `ac_*` 工具,以及 `click`、`type`、`screenshot`、`find_text`、`click_text`、`drag`、`focus_window`、`wait_image` 等短名称 alias。 + +只做检查: + +```bash +je_auto_control_mcp --read-only +``` + +只需要 canonical `ac_*` 名称: + +```bash +JE_AUTOCONTROL_MCP_ALIASES=0 je_auto_control_mcp +``` + +OpenAI agent 请使用 `export_openai_tools(only=[...])` 提供聚焦工具集,不要一次提供整个 AutoControl 命令目录。 + +### 项目识别 + +**项目:** AutoControl
+**Repository:** `Integration-Automation/AutoControlGUI`
+**Python package / PyPI:** `je_auto_control`
+**MCP command:** `je_auto_control_mcp` + + +--- + + +## 服务器与集成 + +| 接口 | 启动方式 | 说明 | +|---|---|---| +| **MCP 服务器** | `je_auto_control_mcp`(stdio)或 `AC_start_mcp_http_server` | 820 个工具,供 Claude Desktop/Claude Code/自定义 tool loop 使用:完整的 `ac_*` 工具接口,以及常用 GUI 操作的短名称 alias。除了以 `initialize` 握手的各版协议,也支持无状态的 MCP 2026-07-28。Bearer 认证、TLS、审计日志、限流、插件热重载、CI 假后端。 | +| **REST API** | `je_auto_control start-rest` | Bearer token、按 IP 限流与锁定、SQLite 审计 hook、`/metrics`、`/openapi.json`、`/docs` Swagger UI、`/dashboard`。 | +| **TCP socket 服务器** | `je_auto_control start-server` | 以换行分隔的 JSON 动作列表。默认绑定 `127.0.0.1`。 | +| **pytest 插件** | 安装后自动生效 | 提供 fixture 与供 pytest-bdd/behave 使用的 Gherkin step library。 | +| **语言服务器** | `python -m autocontrol_lsp.server` | 为 `AC_*` 动作 JSON 提供补全与诊断,命令清单直接取自运行期的命令表。 | +| **远程桌面** | `RemoteDesktopHost` 或 GUI | TCP、WebSocket 或 WebRTC;TOTP、信任列表、TURN 配置、文件/剪贴板/音频同步。 | + +除非明确指定,所有服务器都绑定在 `127.0.0.1`。 + +MCP 窗口状态工具 `ac_window_minimize`、`ac_window_maximize` 与 `ac_window_restore` 在后端接受请求时返回窗口 handle,被拒绝时回复 `isError: true`(包括 handle 失效或激活请求被拒)。Win32 原始 `ShowWindow` 的先前可见性由后端规范化处理。 + +**包闸门。** `AC_add_package_to_executor` 与 `AC_add_package_to_callback_executor` 会导入 Python 包并把成员注册成命令,所以从上面任何一个入口送来的动作列表都可能加载 `os` 或 `subprocess`。没有被放行的包不会加载:不在允许清单上的包在导入前就被拒绝,该动作以 `AutoControlExecuteActionException` 失败。放行包(含子模块)的方式:在 Python 里调用 `executor.allow_packages("name", …)`;对所有入口——两个 CLI、socket/REST/MCP 服务器与调度器——设置环境变量 `JE_AUTOCONTROL_ALLOWED_PACKAGES`(以逗号分隔的名称,进程启动时读取);或只对一次 CLI 执行使用 `je_auto_control run script.json --allow-package NAME`(可重复)。`executor.set_allow_arbitrary_packages(True)` 会对所有包打开闸门,也就是先前版本的默认行为(当时会发 `DeprecationWarning`)。这些都不是 `AC_*` 命令,所以动作列表不能自己打开闸门。 + +**可选的加固设置。** 下列各项在设置之前都是关闭的,没设置的服务器行为与先前相同。`JE_AUTOCONTROL_RBAC_USERS=<用户文件>` 让 REST API 与 MCP HTTP 传输把 bearer token 对应到用户,并按角色(viewer/operator/admin)授权每一个路由、工具与特权 `AC_*` 命令;此时共用 token 会被拒绝。`JE_AUTOCONTROL_MCP_PATH_ROOTS`(以操作系统的路径分隔符分开的目录)把每一个属于文件路径的 MCP 工具参数限制在这些目录里,`JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT=1` 再加上 client 的 `roots/list`,`JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` 限制 `ac_resolve_ref` 可以读哪些 `env://` 名称。`JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` 让端点只能验证 Ed25519 签名的动作文件而不能签名(`create_signing_keypair`;私钥留在签名的机器上)。远程桌面的 viewer 只把 host 推来的文件写在 `~/Downloads/AutoControl` 下面(`JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR`);这一项默认就是开的。 + +REST GUI 在用户存储文件启用时显示 RBAC 模式并禁用共用 token 字段。`rest_api_registry.status()` 提供 `rbac_enabled`,该模式的 `token` 为 `null`;请使用个别用户 token。只实现 `check()` 的自制 REST gate 仍可用于共用 token 模式;RBAC 要求已验证的用户 context,会拒绝没有身份的成功结果。 + +RBAC viewer 不会取得列管的敏感读取工具,即使 MCP `readOnlyHint` 为 true:剪贴板/历史、本机文档/数据/SQL 与 dotenv 读取、引用解析、认证数据生成、持久存储读取、对外检查、麦克风捕获与外部 VLM 请求都需要 operator/admin。断言容器的 spec 也可能读取这些资源,因此同样需要 operator。屏幕观察与纯输入解析保持既有分类。`ac_realize_item`、`ac_idempotency_begin` 与 `ac_rate_limit` 会改变状态,已从 `--read-only` 模式排除。 + +间隔/cron 调度、触发器、热键、watchdog 规则、webhook、e-mail 触发器与 observer 回调会保留注册者身份。每次触发重新检查来源用户文件与角色;已删除的用户、无法使用的来源文件与 viewer 不能执行后台工作。启动 daemon 不会改变已有工作的所有者。所有者信息不保存 RBAC bearer token;未带 `store_path` 的显式 Python `AuthorizationContext` 保留角色快照,未在 RBAC 下注册的工作会清除 worker 原有身份。observer/watchdog 回调使用独立变量作用域,watchdog 动作失败不会算成成功消除弹窗。嵌套回调会保留调用端的失败计数;webhook 所有者被撤销权限时响应 HTTP 403 与 `fired: false`。 + +### 远程桌面的线路协议 + +TCP host 在发送 `AUTH_FAIL` 前就释放认证失败的 client 名额。Viewer 即使因错误 token、错误握手消息或拒绝批准而失败,也能立即重试,不必等待 socket 清理或日志完成;待处理握手仍有独立的资源上限。 + +把主机开放出去之前值得先了解,而且这一段在其他文档里都没有写。默认传输是**裸 +TCP 上的长度前缀分帧**(不需要额外依赖),连接一开始就是 **HMAC-SHA256 的 +challenge/response 握手**:认证不通过的观看端在拿到任何一帧之前就会被断开。 +JPEG 帧按配置的 FPS 与质量编码,再通过一个共享的**最新帧槽**发给已认证的观看 +端——所以慢的观看端是**丢帧**,不会把其他人一起卡住。观看端发来的输入是 JSON, +会先比对**动作允许列表**才交给既有的输入包装层执行,观看端无法自己发明新的操作。 + +```python +# 让别人连进来——启动一个主机,把 token 与 port 给对方 +from je_auto_control import RemoteDesktopHost +host = RemoteDesktopHost(token="hunter2", bind="127.0.0.1", + port=0, fps=10, quality=70) +host.start() +print("listening on", host.port, "viewers:", host.connected_clients) +``` + +```python +# 控制另一台机器——连上去并发送输入 +from je_auto_control import RemoteDesktopViewer +viewer = RemoteDesktopViewer(host="10.0.0.5", port=51234, token="hunter2", + on_frame=lambda jpeg: ...) +viewer.connect() +viewer.send_input({"action": "mouse_move", "x": 100, "y": 200}) +viewer.disconnect() +``` + +也可以用 IP 允许列表(CIDR 网段或具体地址)限制谁能连进来,列表外的对端在握手 +阶段就会被拒绝: + +```python +RemoteDesktopHost(token="tok", ip_allowlist=["10.0.0.0/8", "192.168.1.100"]) +``` + +--- diff --git a/docs/guides/zh-CN/setup.md b/docs/guides/zh-CN/setup.md new file mode 100644 index 000000000..043ec72bc --- /dev/null +++ b/docs/guides/zh-CN/setup.md @@ -0,0 +1,294 @@ +# Installation and configuration + +[README](../../../README/README_zh-CN.md) · [Documentation](../../README.md) + +## 安装 + +```bash +pip install je_auto_control # 内核 +pip install je_auto_control[gui] # 加上 PySide6 桌面应用 +``` + +按需安装的可选组件: + +| Extra | 启用的功能 | +|---|---| +| `gui` | PySide6 桌面应用(51 个标签页):左侧可搜索的导航面板(`Ctrl+K`)按分类列出全部功能,标签页在第一次打开时才创建,**View → Theme** 切换深色/浅色。窄窗口的内容可滚动;关闭窗口时,主题、字号、导航面板显示(`Ctrl+B`)与宽度会保存到 `~/.je_auto_control/gui.ini`。主题直接使用 Qt,不需要 `qt-material`。 | +| `webrtc` | WebRTC 远程桌面、USB 直通(`aiortc`、`av`) | +| `signaling` | 独立的信令/rendezvous 服务器(`fastapi`、`uvicorn`) | +| `discovery` | mDNS / Zeroconf 局域网主机发现 | +| `pdf` / `office` | PDF 与 Excel/Word/PowerPoint 读取 | +| `fuzzy` / `locale` | `rapidfuzz` 模糊匹配、`babel` 区域解析 | +| `s3` / `audio` | S3 制品存储、系统音量控制 | + +使用标签页关闭按钮关闭 factory 创建的功能面板时,下一次 Qt event loop 会释放 widget、订阅与计时器;重新打开会创建新面板。**View → Tabs** 与嵌入用的 `hide_tab` 只隐藏并保留状态。`tab_registry.open/close` 与 `close_tab` 提供明确的生命周期接口。既有的所有者表单与 Remote Desktop 在生命周期迁移完成前,关闭后仍保留以供重用。 + +**Windows arm64** 装得起来也跑得起来,少的是上游在那里发不出来的那些: +`opencv-python` 与 `cryptography` 都没发 `win_arm64` wheel。所以 `find_image*`、 +`screenshot()`(OpenCV/BGR 那一支——Pillow 截图仍可用)、密钥金库、动作文件加密、 +ACME/TLS 与加密录影会抛出指名缺哪个 wheel 的错误,而不是难以追查的失败。 +鼠标、键盘、屏幕尺寸、窗口管理、无障碍树、动作执行器、MCP/REST/TCP 服务器 +与 GUI 都正常——这是实测的,不是推论的。其他平台不受影响。 + +**系统需求:** Python ≥ 3.11。 +Linux 请先安装构建依赖: + +```bash +sudo apt-get install cmake libssl-dev +``` + +OCR、VLM 与 LLM 后端(`pytesseract`、`easyocr`、`paddleocr`、`anthropic`、`openai`) +都是按需加载——只装你实际会用到的。Tesseract 方面,`find_tesseract_cmd()` 找出可执行文件 +(依次是 `$TESSERACT_CMD`、`PATH`、安装程序的默认文件夹),`set_tessdata_dir()` 把它指向 +语言数据文件夹,`ocr_status()`/`ocr_languages()` 在第一次 OCR 之前就说出缺了什么。 + +**日志文件:** 库写到 `~/.je_auto_control/logs/AutoControlGUI.log`,第一条记录时 +才创建(只 import 不会写任何文件),同一个账户的所有进程共用(追加写入、每行带进程 ID, +超过 10 MB 就改名为 `.1`)。要写到别处就设置 +`JE_AUTOCONTROL_LOG_FILE`,设为 `os.devnull` 则不写文件。 + +--- + +## 平台支持 + +| 平台 | 后端 | 输入 | 屏幕捕获 | 录制 | 窗口管理 | +|---|---|:---:|:---:|:---:|:---:| +| Windows 10 / 11 | Win32 ctypes(可选 Interception 驱动) | ✅ | ✅ | ✅ | ✅ | +| macOS 10.15+ | pyobjc / Quartz | ✅ | ✅ | ✅¹ | ✅ | +| Linux X11 | python-Xlib(可选 `uinput`) | ✅ | ✅ | ✅ | ✅ | +| Linux Wayland | 经桌面 portal 的 libei,或 ydotool/wtype + 截图工具 | ✅ | ✅ | ❌ | ❌ | +| FreeBSD/OpenBSD/NetBSD | python-Xlib,与 Linux 同一套 X11 后端 | ✅² | ⚠️² | ✅² | ✅² | +| Android | adb + uiautomator2 | ✅ | ✅ | — | — | +| iOS | WebDriverAgent / facebook-wda | ✅ | ✅ | — | — | + +¹ macOS 的录制走 Quartz event tap,需要**辅助功能**权限 +(系统设置 → 隐私与安全性 → 辅助功能)。没有授权时会直接抛出并指名 +缺的是哪个权限,而不是安静地录到一个空的 session。 + +² BSD 直接跑同一套 X11 后端——同一个 X server、同一个 `python-Xlib`,而输入、 +录制与窗口管理就只依赖这一个包。`freebsd` CI job 在真的 FreeBSD 14 上驱动真的 +输入,再从 X server 读回来;OpenBSD 与 NetBSD 走同一条代码路径,只是没有 CI +runner。唯一的例外是屏幕截取,卡住的是打包而不是平台:它走 Pillow/mss 与 +OpenCV,而 `opencv-python`、`pillow`、`cryptography` 都没有发 FreeBSD wheel。 +从 ports 构建之后,截取、图像匹配、OCR 与动作加密也都能用—— +`import je_auto_control` 本身已经不需要它们任何一个。 + +Wayland 的按键、按钮与指针输入在 `auto` 模式下,仅在可选原生后端缺失时改用 CLI。 +portal 请求开始后,拒绝、超时、握手失败、设备暂停或权限撤销都会停止输入, +不会自动切换提供者;重复调用保留不含原生资源的失败状态,不重开同意对话框。 +`JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND=libei` 强制原生输入,`=cli` 明确选择 CLI。 +解决权限问题后,可明确调用 `je_auto_control.linux_wayland.libei.reset_default_backend()` +以允许重新请求。原生组合键中断时会在同一后端尝试释放所有已按下的按键,并保留原始取消。 +此行为不改变明确的 wtype 文本输入路径或屏幕截取选择。 + +`ydotool` 退路需要 +**ydotool 1.0 以上**。AutoControl 送的每一个参数都是那一版才有的;0.1.x +(Debian bookworm 与目前所有 Ubuntu 仍以这个名字提供,Debian trixie 则根本没有) +对同一批参数返回 0 却不送出任何事件。AutoControl 会检测并直接拒绝, +而不是为根本没送出的输入回报成功。Arch、Fedora 与 Debian unstable 提供的是 1.0。 + +这条退路要能**准确定位**,还有一个前提:合成器的指针加速度必须是关的。 +`ydotool mousemove --absolute` 并不发任何绝对事件——它先把光标推到合成器夹取的 +那个角落,再发相对位移,所以这段位移会被合成器加速。对真的 wlroots session 量到的是: +libinput 的默认 profile 让光标走的距离正好是请求的两倍。ydotool 自己的 `--help` +也是这样写的;AutoControl 每个进程会记一次警告,而不是安静地把点击放到错的地方。 +请对 ydotoold 的设备关掉加速度(sway:`input type:pointer accel_profile flat` +加上 `pointer_accel 0`),或者装上 `liboeffis`,改走协议层本来就是绝对坐标的 libei。 + +倍率是合成器自己的设置,客户端读不回来,所以只有你知道它关了没有: +`JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL=flat` 表示已经关掉,移动就不再出声; +`=strict` 则宁可拒绝这次移动,也不让点击落在别的地方;不设置就维持 +“警告一次后照样移动”的默认。 + +Wayland 的屏幕截取需要合成器对应的工具,因为没有单一工具能覆盖全部:wlroots 系 +(sway、Hyprland、river)用 `grim`,GNOME 用 `gnome-screenshot`,KDE 用 `spectacle`。 +装好其中一个之后,所有截取路径——截图、图像与锚点定位、OCR、屏幕录制、远程桌面——都会 +经由它。三个都没装时,内置 D-Bus client 会通过 session bus 尝试 `xdg-desktop-portal`,第一次可能会弹 +同意对话框。再不行,截取会带着安装提示明确失败,而不是返回空白的 XWayland root; +`je_auto_control.api.run_diagnostics()`(以及 GUI 的 Diagnostics 标签页)的 `screen_capture` +检查会报告当前使用的是哪一层。 + +原生 Wayland 指针坐标在原始坐标与布局原点换算后仍不属于任何授权 EIS 区域时, +会以 `state="failed"` 的 `LibeiUnavailable` 拒绝,停止自动 CLI 备用, +不发送移动、frame 或后续点击。有效坐标、未提供区域的设备、同一 sender 的后续有效请求, +以及显式选择 CLI 的现有行为保持不变。 + +**输入/截取能力**提供 `je_auto_control.api`(也由包根目录导出)的 +`BackendContext`、`CapabilityStatus`、`CapabilitySnapshot` 与 `probe_capabilities`。 +调用 `probe_capabilities(BackendContext.current()).to_dict()`、无参数的 +`AC_probe_capabilities`/只读 `ac_probe_capabilities`,或选择 +**Diagnostics → Actions → 查看输入与截取能力**;Builder 提供相同无参数命令。 +`python -m examples.capabilities` 显示本机前置条件与确定性的 XWayland 范围示例,不操作桌面。 + +输入项描述按键/指针事件;现有 wtype 文字路径独立。探测只读环境、PATH 与不等待锁的现有原生状态, +不加载可选原生库、不连接、不读取事件、不截取或请求授权。找到工具或 bus 地址只代表 +`unverified`,不等于可用。缓存 libei 须完成握手,且键盘、绝对指针、按钮与滚轮事件种类都在运行才报告可用; +部分授权保持未验证,事件种类暂停或必要设备移除则报告暂停/撤销。八种状态为 `available`、`unverified`、`needs_permission`、 +`needs_dependency`、`unsupported`、`paused`、`revoked`、`failed`。 +`available` 仅是最近的本机观察,可能过时;实际操作仍重新验证权限。XWayland 一律 +`desktop_wide=False`,无法覆盖原生 Wayland 窗口;其他范围标记仍受授权区域限制,不代表已验证每个屏幕。 + +Context 会复制环境/工具数据,可由拥有者提供无原生对象的输入/截取观察,但不授予权限。 +默认本机结果不含环境值、命令参数、可执行文件路径或原生错误文字;AC/MCP 不接受外部提供观察。 +显式选择 CLI 与观察到可选原生依赖缺失后的自动备用分开;拒绝、暂停、撤销与失败不表示改走 CLI。 +截取工具/portal 选择独立诊断,重绘与切换语言只使用现有快照。原生 portal 恢复、compositor 重启、 +截取结果与 context 的接合,以及原生 session 的重试/取消/停止控制仍列于 `Progress.md`。 + +GUI 工作基础提供 `gui.task_controller.TaskController`: +`submit(work, owner=widget)` 返回调用者持有的 `TaskHandle`,通过 +`TaskOutcome`/`TaskProgress` 传递终态与进度。工作取得不依赖 Qt 的 +`CancellationToken`,提供 checkpoint、有界且可被取消唤醒的等待与进度报告。 +提交时捕获 context,执行前重新读取 store 用户;工作须持有数据、不引用 widget,并验证自身操作所需的 capability。 +现有 `DeferredAuthorization.scope()` 保持输入权限要求,`context_scope()` 仅更新并绑定身份。 + +拥有者、handle 或 controller 销毁时会请求协作式停止并丢弃延迟结果;每项工作有独立 ID/token, +回调在 GUI 线程执行。不强制中断不配合的调用,也不把已成功提交的结果改标为取消。 +错误与进度使用捕获的秘密遮罩 scope,终态不保留异常 traceback;线程启动失败会恢复两层登记并保留原失败。 +Diagnostics 已接入此共用控制器;其余面板/backend 迁移与原生 session 操作仍列于 `Progress.md`。 + +主动 **Diagnostics → Actions → 运行诊断** 以共用控制器在 GUI 线程外运行。 +**停止诊断** 请求协作式停止;四种语言的状态区分运行中、清理中、已取消和失败,并显示已完成检查数。 +重复运行不另开工作,关闭后丢弃延迟进度/结果,显式重试会建立新的拥有者工作。 +GUI 以不保留异常 traceback 的 typed outcome 呈现取消;核心/SDK/CLI 与 MCP handler +保持原始直接/包装取消对象。普通检查错误仍计入报告并继续其余项目。 + +两个 SDK namespace 导出 `CancellationToken`、`TaskProgress`、`cancellation_scope`。 +使用 `with cancellation_scope(token): report = run_diagnostics()`,拥有者可由另一线程调用 +`token.cancel()`;现有无参数诊断签名不变。Scope 不授予权限,`cancellation_scope(None)` +只在有时限的自有资源清理期间暂停取消。`AC_diagnose` 与新增的只读 `ac_diagnose` 共用报告; +MCP 不接受参数,使用请求取消/进度,与显式 GUI 操作同样需要 `read_screen`,拒绝外部 token/授权数据。 +这些是主动检查,截取可能请求同意;`ac_probe_capabilities` 保持独立的被动选项。 + +Scoped Wayland D-Bus 的连接/读取/部分写入,以最多 0.1 秒的间隔轮询,保持原本总时限。 +取消时在原 bus 以独立 0.25 秒预算尝试 Request.Close,再释放连接;取消的已返回图片会删除。 +Scoped CLI 截取会停止并回收自己建立的 helper/process group,清理有时限,pipe close 失败也不覆盖原取消, +已回收的数字 PID 不再作为信号目标。liboeffis 获取 session 时会观察停止并释放自身 context。 +不强制中断不配合或原生调用,清理期间 GUI 仍可操作;restore/重启、原生 session 控制、 +截取拥有者 metadata 与其余面板/backend 迁移保留于 `Progress.md`。 + +`python -m examples.cancellable_diagnostics` 默认只做受控取消示例,不调用 provider。 +`--active --cancel-after 2` 才显式运行诊断并在两秒后请求停止;真机/设备/API 验收另外列管。 + +打开 Diagnostics 只显示已翻译的「尚未运行」状态,不执行检查。 +选择 **Actions → 运行诊断** 才会启动现有主动检查,可能截取屏幕或需要 portal 同意; +切换语言不启动检查。显式的 `run_diagnostics`、`AC_diagnose` 与 MCP 诊断调用保持主动行为; +无副作用的能力查看使用下方独立操作。 + +未完成的 screenshot portal 请求会在断开原始 bus 前尝试 `Request.Close`, +使用独立的 0.25 秒 D-Bus I/O 预算。服务器返回替代 handle 时会跟随该 handle; +方法回复不确定时则使用预测 handle,已完成的 Response 不重复关闭。 +普通清理错误不覆盖主要截取失败;原始取消与强制中断对象会穿过包装及清理继续传播。 +D-Bus 写入与回复共用调用预算,连接建立有明确时限,connect/认证/Hello 中断时, +即使 `__enter__` 失败也会释放自己拥有的描述符。实际合成器/对话框取消仍待平台验收。 + +有一件只在 Wayland 出现、需要事先规划的事:**截取回来的图里可能有鼠标光标。** +这里没有任何一条截取请求光标,但只要 backend 没有光标平面(包含任何以 +`WLR_NO_HARDWARE_CURSORS=1` 运行的 session),wlroots 就会画**软件光标**并把它 +合成进输出缓冲区,而截取交回来的正是那一份。Windows 与 X11 都不含光标,所以 +“定位器、模板匹配或 OCR 在目标中间看到一个光标形状的洞”只会在这里发生。 +Wayland 不让客户端读光标位置,所以没有东西可以可靠地遮或避开:请在截取之前 +把指针移离要拍的区域。`screen_capture` 检查会以 `cursor_may_be_captured` 报告这件事。 + +如果以上都不适用你的环境,可以直接指定自己的命令——它优先于所有检测,`{output}` 会被 +换成临时 PNG 路径: + +```bash +export JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND="mycapture --png {output}" +``` + +Wayland 禁止非特权客户端进行全局输入录制——若要录制,请设置 +`JE_AUTOCONTROL_LINUX_DISPLAY_SERVER=x11` 并在 X11 会话下运行。窗口管理支持 +Windows、macOS(pyobjc)与 X11(含 XWayland);纯 Wayland 会话的协议不让客户端看到其他程序的窗口, +所以 `list_windows()` 返回空列表,其余窗口操作一律抛出带原因的 `AutoControlUnsupportedOperationException`。对于会忽略合成输入的应用, +可选用驱动层后端(`JE_AUTOCONTROL_WIN32_BACKEND=interception`、 +`JE_AUTOCONTROL_LINUX_BACKEND=uinput`、ViGEm 虚拟手柄);驱动未安装时会自动回退到原有行为。 + +--- + +## 配置 + +AutoControl 读取的每一个环境变量。这里没有任何一项是必填的:完全不设置时,AutoControl 会自行选择平台后端,服务器只绑定 `127.0.0.1`,所有需要主动开启的功能(签名强制、RBAC、USB 直通、工具路径限制)都是关闭的。[配置参考](https://autocontrol.readthedocs.io/en/latest/Zh/doc/configuration/configuration_doc.html)([源文件](../../source/Zh/doc/configuration/configuration_doc.rst))列出完整的可接受值,并把每个变量链接到说明该功能的页面;CI 会拿它以及下面的表格和代码比对。 + +### 平台后端 + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_WIN32_BACKEND` | `sendinput` | 设为 `interception` 时键盘与鼠标改走 Interception 驱动程序;找不到驱动或 DLL 时会警告并回退到 `SendInput`。 | +| `JE_AUTOCONTROL_LINUX_BACKEND` | `x11` | 设为 `uinput` 时直接写入内核输入事件;`/dev/uinput` 无法写入时会警告并回退到 XTest。 | +| `JE_AUTOCONTROL_LINUX_DISPLAY_SERVER` | `auto` | 决定加载哪一个 Linux 后端:`auto` 读取 `XDG_SESSION_TYPE` 与 `WAYLAND_DISPLAY`;`wayland` 或 `x11` 则强制指定(在 Wayland 会话设为 `x11` 只能操作 XWayland 窗口)。 | + +### Windows Interception 驱动程序 + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_INTERCEPTION_DLL` | 未设置:先找 `PATH`,再找包旁边 | `interception.dll` 的完整路径。 | +| `JE_AUTOCONTROL_INTERCEPTION_KEYBOARD` | `1` | 键盘事件要发往的 Interception 设备编号(`1`–`10`)。 | +| `JE_AUTOCONTROL_INTERCEPTION_MOUSE` | `11` | 鼠标事件要发往的 Interception 设备编号(`11`–`20`)。 | + +### Wayland + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND` | `auto` | 设为 `cli` 时通过 `ydotool` 发送输入,完全不向桌面 portal 提出请求。这是启动前就做好的选择:用户拒绝授权后,AutoControl 不会自行切换过去。 | +| `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL` | `warn` | 只影响 `ydotool` 路径的绝对移动(那其实是会被合成器加速的相对位移):`warn` 警告一次后照样移动,`flat` 表示加速已关闭、不再警告,`strict` 直接拒绝移动。 | +| `JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND` | 未设置 | 自定义的截图命令行,以 `{output}` 表示 PNG 的输出路径。优先于 `grim`、`gnome-screenshot`、`spectacle` 与 portal。 | +| `JE_AUTOCONTROL_WAYLAND_RECORD_DEVICES` | 未设置:一个都不读 | `PhysicalRecorder` 可以读取的 `/dev/input/event*` 设备(以逗号分隔);物理输入录制必须逐一指定设备才会启用。 | + +### MCP 服务器 + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_MCP_READONLY` | 未设置 | 设为 `1` 时只提供、也只能调用标记为只读的工具。 | +| `JE_AUTOCONTROL_MCP_TOOL_PROFILE` | 未设置 | `static` 模式的工具清单:以逗号分隔的工具名称与 `category:<名称>`。 | +| `JE_AUTOCONTROL_MCP_ALIASES` | `1` | 设为 `0` 时不注册 `ac_*` 工具之外的简短别名(`click`、`screenshot` …)。 | +| `JE_AUTOCONTROL_MCP_TOKEN` | 未设置 | HTTP 传输的 Bearer 令牌。启用 RBAC 之后不再接受。 | +| `JE_AUTOCONTROL_MCP_ALLOWED_ORIGINS` | 未设置:只接受本机来源 | HTTP 传输额外接受的浏览器来源(以逗号分隔,须完全相符,例如 `https://example.test:8443`)。 | +| `JE_AUTOCONTROL_MCP_CONFIRM_DESTRUCTIVE` | 未设置 | 设为 `1` 时具破坏性的工具在执行前先向客户端请求确认(MCP elicitation)。 | +| `JE_AUTOCONTROL_MCP_PATH_ROOTS` | 未设置:不限制 | 工具的每一个文件参数都必须落在这些目录内(以操作系统的路径分隔符分隔)。 | +| `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` | 未设置 | 设为 `1` 时同时接受 MCP 客户端通过 `roots/list` 报告的根目录。 | +| `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` | 未设置:不限制 | `ac_resolve_ref` 可以读取的环境变量名称(以逗号分隔,可用 `fnmatch` 模式);设了却没有指名任何变量时,一个都不允许。 | +| `JE_AUTOCONTROL_MCP_AUDIT` | 未设置 | JSON-lines 文件的路径,每一次 `tools/call` 写入一条记录。 | +| `JE_AUTOCONTROL_MCP_ERROR_SHOTS` | 未设置 | 工具每次失败时存放截图的目录。 | +| `JE_AUTOCONTROL_FAKE_BACKEND` | 未设置 | 设为 `1` 时 MCP 服务器只在内存中记录鼠标、键盘与剪贴板调用而不实际执行,供没有显示器的 CI 使用。 | + +### REST/RBAC 与 chat-ops + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_RBAC_USERS` | 未设置:沿用共享令牌 | 用户文件的路径。设置它就等于为 REST API 与 MCP HTTP 传输启用角色。 | +| `JE_AUTOCONTROL_CHATOPS_SCRIPT_ROOT` | 未设置:`run` 会被拒绝 | chat-ops 的 `run` 命令唯一可以加载动作文件的目录。 | + +### 执行与签署动作文件 + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_ALLOWED_PACKAGES` | 未设置:一个都不允许 | `AC_add_package_to_executor` 可以加载的包(以逗号分隔,含子模块),对所有入口生效。只在进程启动时读取一次。 | +| `JE_AUTOCONTROL_REQUIRE_SIGNED_ACTIONS` | 未设置 | 设为 `1` 时所有会执行动作文件的路径,都拒绝没有有效签名文件的动作文件。 | +| `JE_AUTOCONTROL_ACTION_SIGNING_PRIVATE_KEY` | 未设置 | Ed25519 私钥(PEM)的路径。只在负责签署的机器上设置;设置后签署会写出第 2 版的签名文件。 | +| `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` | 未设置 | 对应公钥的路径。在每一台执行端设置:它只能验证,不能签署。 | +| `JE_AUTOCONTROL_ACTION_SIGNING_PASSPHRASE` | 未设置 | 私钥创建时若设置了口令,在这里提供。 | +| `JE_AUTOCONTROL_ACCEPT_LEGACY_ACTION_SIGNATURES` | 未设置 | 设为 `1` 是迁移模式:设置公钥之后,第 2 版之前写出的 HMAC 签名文件会被拒绝,除非设置了这个变量。所有文件重新签署后请再关掉。 | + +### 远程桌面与信令 + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR` | `~/Downloads/AutoControl` | 远程桌面查看端存放主机传来文件的目录。收到的路径一律限制在这个目录内。 | +| `JE_AUTOCONTROL_USB_PASSTHROUGH` | 未设置 | 设为 `1` 时在远程桌面通道上启用 USB 直通指令。 | +| `AC_SIGNALING_SECRET` | 未设置 | 信令/配置同步服务器的共享密钥(`X-Signaling-Secret`)。服务器在没有 `--shared-secret` 时读取它。 | + +### GUI + +| 变量 | 默认 | 作用 | +|---|---|---| + +### 日志、数据与测试 + +| 变量 | 默认 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_LOG_FILE` | `~/.je_auto_control/logs/AutoControlGUI.log` | 日志文件写入的位置。指定空设备(`/dev/null`、`NUL`)即可关闭文件输出。在写入第一条记录时才读取,而不是在 import 时。 | +| `JE_AUTOCONTROL_ENV` | `default` | 资产库当前使用的环境(`active_environment()`),让同一份脚本在 `dev` 与 `prod` 读到不同的值。 | +| `JE_AUTOCONTROL_REDACTION` | `off` | 截图遮蔽的默认策略:`off`、`moderate` 或 `strict`。未知的名称会报错,不会被当成 `off`。 | +| `JE_AUTOCONTROL_PYTEST_ARTIFACTS` | `./autocontrol_screenshots` | 测试没有使用 `autocontrol_screenshot_dir` fixture 时,pytest 插件写入失败截图的目录。 | + +--- diff --git a/docs/guides/zh-CN/usage.md b/docs/guides/zh-CN/usage.md new file mode 100644 index 000000000..d14178b25 --- /dev/null +++ b/docs/guides/zh-CN/usage.md @@ -0,0 +1,203 @@ +# Automation usage + +[README](../../../README/README_zh-CN.md) · [Documentation](../../README.md) + +## 为什么选择 AutoControl + +- **一套 API,七个平台。** `wrapper/platform_wrapper.py` 在导入时挑选后端;同一份脚本在 + Windows、macOS、X11 与 Wayland 上都不需要改写。 +- **不写 Python 也能脚本化。** 911 个 `AC_*` 命令覆盖全部功能,因此一个 JSON 文件能做到库 + 能做的任何事——包含循环、分支、try/catch、宏与变量。 +- **默认无头运行。** `import je_auto_control` 绝不会加载 Qt。GUI 是可选包,包在同一个无头内核之外。 + 公开导出项在被访问时才加载来源模块。`__all__` 与 `dir()` 可列出名称,不必加载全部功能; + 通配符导入会请求所有名称。尚未解析的名称不会出现在 `vars(je_auto_control)`。 + X11 的普通包导入不会打开显示连接或输入设备,也不会启动键盘监听。 + 桌面操作在调用时才获取资源。读取 `keyboard_keys_table` 或调用 + `get_keyboard_keys_table()` 会解析实际服务器键码,因此需要 X 连接。 +- **四种定位方式。** 模板匹配、OCR、无障碍树、视觉语言模型——可通过锚点定位器与自愈回退串接组合。 +- **依赖基线轻量。** REST 服务器、JSON Schema 校验、JWT、TOTP、WebSocket 帧、ACME 客户端、 + USB/IP 协议与 Prometheus 指标全部以标准库实现;较重的依赖都是可选项。 + + +## 如何选择自动化层 + +AutoControl 不需要取代所有自动化工具;应选择最符合界面的那一层: + +| 需求 | 适合工具 | +|---|---| +| 稳定的浏览器 DOM/API 自动化 | Playwright/Selenium | +| 简单的 Python 鼠标键盘脚本 | PyAutoGUI 或 AutoControl | +| 原生桌面应用程序自动化 | **AutoControl** | +| 无障碍树 GUI 自动化 | **AutoControl** | +| OCR GUI 自动化 | **AutoControl** | +| 截图/视觉模型 GUI 定位 | **AutoControl** | +| Self-healing 跨平台 GUI locator | **AutoControl** | +| AI agent 操作真实桌面 | **AutoControl + MCP** | +| 确定性的 JSON GUI workflow | **AutoControl** | + +AutoControl 的差异在于把 **真实电脑输入 + 语义/视觉定位 + self-healing + agent/MCP 集成** 放在同一个跨平台自动化接口中。 + + +## 60 秒上手 + +**1. 作为 Python 库** + +```python +import je_auto_control as ac + +ac.set_mouse_position(500, 300) +ac.click_mouse("mouse_left") +ac.write("Hello World") +ac.hotkey(["ctrl_l", "s"]) + +x, y = ac.locate_image_center("save_button.png", detect_threshold=0.9) +ac.click_text("Submit") # OCR +ac.click_accessibility_element(name="OK") # 无障碍树 +ac.click_by_description("the green Submit button") # 视觉模型 +ac.screenshot("shot.png", screen_region=[0, 0, 800, 600]) +``` + +**2. 作为 JSON 动作文件** — `flow.json` + +```json +[ + ["AC_set_var", {"name": "user", "value": "alice"}], + ["AC_locate_and_click", {"image": "login.png", "mouse_keycode": "mouse_left"}], + ["AC_write", {"write_string": "${user}"}], + ["AC_retry", {"max_attempts": 3, "body": [ + ["AC_wait_text", {"target": "Welcome", "timeout": 10}] + ]}], + ["AC_assert_text", {"text": "Welcome"}], + ["AC_generate_html_report", {"html_name": "report"}] +] +``` + +```bash +je_auto_control run flow.json --var user=bob +je_auto_control run flow.json --dry-run # 只列出步骤,不会真的动鼠标 +``` + +**3. 作为桌面应用** + +```bash +pip install je_auto_control[gui] +python -c "import je_auto_control; je_auto_control.start_autocontrol_gui()" +``` + +录制一段流程、在可视化 Script Builder 里编辑,然后存成 CLI 能直接执行的同一种 JSON 格式。 +(`python -m je_auto_control` 是旧式的动作文件执行器——`-e`、`-d`、`-c`、`--execute_str`——不会打开 GUI。) + +--- + +## 能力总览 + +每一行都能无头执行。“GUI 标签页”是同一功能在桌面应用中的位置;标签页的命令都放在窗口的 +**Actions** 菜单里。 + +| 能力 | Python API | `AC_*` 命令 | GUI 标签页 | +|---|---|---|---| +| 鼠标 | `click_mouse`(`clicks=2` 即双击)、`set_mouse_position`、`mouse_scroll`、`tween_drag`/`drag_path`(以 `step_delay_s`、`settle_s` 控制节奏) | `AC_click_mouse`、`AC_tween_drag`、`AC_drag_path` | Auto Click | +| 键盘 | `write`、`write_secret`、`hotkey`、`type_keyboard`、`keyboard_key_name`(键码 → 标准键名;Windows 也接受 `ctrl`、`esc`、`enter` 等别名) | `AC_write`、`AC_write_secret`、`AC_hotkey` | Auto Click | +| 屏幕与像素 | `screenshot`、`screen_size`、`get_pixel` | `AC_screenshot` | Screenshot | +| 图像匹配 | `locate_image_center`、`locate_and_click` | `AC_locate_and_click` | Image Detect | +| OCR 文字 | `click_text`、`wait_for_text`、`read_text_in_region`、`ocr_status` | `AC_click_text`、`AC_wait_text`、`AC_ocr_status` | OCR Reader | +| 无障碍树 | `find_accessibility_element`、`click_accessibility_element` | `AC_a11y_find`、`AC_a11y_click` | Accessibility | +| 视觉模型定位 | `locate_by_description`、`click_by_description` | `AC_vlm_locate`、`AC_vlm_click` | VLM | +| 锚点定位 | — | `AC_anchor_click`、`AC_anchor_locate` | — | +| 自愈定位器 | `self_heal_run`、`self_heal_locate`、`self_heal_click` | `AC_self_heal_click` | Self-Healing | +| 自然语言规划 | `plan_actions`、`run_from_description` | `AC_llm_plan` | LLM Planner | +| Computer-use agent | `AgentLoop`、`run_agent` | `AC_run_agent` | Computer Use | +| 录制与回放 | `record`、`stop_record` | `AC_record`、`AC_stop_record` | Record | +| JSON 脚本 | `execute_action`、`execute_files` | 全部 911 个命令 | Script、Script Builder | +| 变量与流程控制 | `execute_action_with_vars` | `AC_set_var`、`AC_loop`、`AC_for_each`、`AC_try`、`AC_retry` | Variables | +| 数据驱动执行 | — | `AC_for_each_row`(CSV/JSON/SQLite/Excel) | Data Sources | +| 断言 | `assert_text`、`assert_image` | `AC_assert_text` 等 21 个 | Assertions | +| 测试套件 | `run_suite` | `AC_run_suite` | Test Suites | +| 调度(间隔 + cron) | `default_scheduler` | — | Scheduler | +| 全局热键 | `default_hotkey_daemon` | — | Hotkeys | +| 事件触发 | `default_trigger_engine` | `AC_email_trigger_add` | Triggers、Webhooks、Email | +| 窗口管理 *(Windows、macOS、X11)* | `list_windows`、`focus_window` | `AC_focus_window`、`AC_snap_window` | Window Manager | +| 剪贴板(文本 + 图片) | `get_clipboard`、`set_clipboard`、`get_clipboard_image`、`set_clipboard_image` | `AC_clipboard_get`、`AC_clipboard_set`、`AC_clipboard_get_image`、`AC_clipboard_set_image` | — | +| 远程桌面 | `RemoteDesktopHost`、`RemoteDesktopViewer` | `AC_start_remote_host`、`AC_remote_connect` | Remote Desktop | +| USB 枚举与直通 | `list_usb_devices`、`enable_usb_passthrough` | `AC_usb_*`(16 个命令) | USB Devices、USB Share | +| 密钥保险库 | `default_secret_manager` | `AC_secret_set` + `${secrets.NAME}` | Secrets | +| 报表(HTML/JSON/XML) | `generate_html_report` | `AC_generate_html_report` | Report | +| 运行历史 | `HistoryStore`、`manual_history_scope` | `AC_history_list`、`AC_history_capture` | Run History、Script Executor、Script Builder | +| 动作日志 | `execute_journal_run`、`inspect_journal` | `AC_journal_capture`、`AC_journal_read` | Run History、Script Builder | +| 指标与追踪 | `default_metric_registry`、`render_metrics_text` | — | — | +| 系统诊断 | `run_diagnostics` | `AC_diagnose` | Diagnostics | +| 测试代码生成 | `generate_code` | — | — | + +自愈定位器会在回退或点击前原样传递取消。稽核日志在写入或返回记录前遮蔽本次运行已解析的秘密值;返回的定位结果保留原值,读取时不改写既有日志文件。 + +实时 image/VLM 自愈现在共用一次延迟逻辑截图及实际裁切原点,两条路径的 `screen_region` 均为 `[左, 上, 右, 下]`。Schema-v2 记录增加 run/step 身份、内容与配置版本、frame hash、策略/截图耗时及实际 backend/model,仍兼容旧记录。未配置验证的点击仅记录已送出或失败,验证保持未知。GUI 提供区域输入与所选记录证据,Script Builder 保留结构化区域 JSON。旧 `healed`/`heal_rate` 统计定位候选,独立的操作指标需要明确验证。 + +实验性 `self_heal_run(SelfHealRequest(...))` 默认只定位。明确选择 `operation="click"`,再通过 `VerificationRequest(verifier=...)`(Python bool callback)或 `VerificationRequest(description=...)`(已配置的 VLM)于输入送出后验证条件。VLM 验证使用新截取的逻辑图像,可能产生 API 费用。`verified` 分为真、假及未知;`found` 与 `issued` 本身不代表操作通过验证。异常与取消原样传递,不重试点击。`AC_self_heal_run` 和 MCP `ac_self_heal_run` 接受嵌套 `request`;明确验证失败使命令/CLI 失败,或返回含结构化结果的 MCP `isError`。GUI **Self-Healing** 提供选填的操作后条件,Script Builder 可编辑 JSON 请求。独立 VLM 截取也改用相同的内存逻辑原点/Retina 归一化。Framework assertion 会中止定位后备。 + +已捕获的自愈记录新增可选的 `journal_path`,搭配 run/step ID。实验性 `inspect_heal_source(path, run_id, step_id)`、`AC_self_heal_source` 与 MCP `ac_self_heal_source` 只读取原始步骤经清理的生命周期快照。在 **Self-Healing** 选取记录后,使用 **动作 → 查看原始步骤** 打开后台读取器;切换目标时会等待旧读取停止并保留请求者上下文,关闭则取消待处理工作;Run History 读取器也可选填步骤 ID。先筛选 run/step 再应用输出上限,整份日志仍会验证,进度通知前后重查路径根目录,取消不返回部分结果。旧记录或未经动作日志捕获的操作没有来源链接;查阅不会重放命令。 + +实验性因果同步提供 `CausalBucket`、`CausalConfigStore`、`SyncActor`、保留冲突的 entry 版本与持久化本机 `SyncOutbox`。独立且经过验证的 `GET/PUT /config/{user_id}/causal` 第三版协议,在保存重发收据的同一个 CAS 事务内验证设备注册、确认、退休/完整同步 epoch 与删除回收。回收后保留永久的最小删除凭据;旧版写入不能覆盖已升级账号。私有 `AC_config_store_get`/`AC_config_store_commit` 与对应 MCP/Builder 命令可读取及提交带显式 `_actor` 的因果 JSON;纯数据合并/peer 与私有 outbox 命令仍可使用。显式的 `CausalSyncClient` 与 `AC_config_causal_fetch`、`AC_config_causal_commit`、`AC_sync_outbox_flush`(含 MCP/Builder)已提供第三版 HTTP 投递:结果不明时重发固定请求,只有明确的过期版本才在有界预算内重新合并。`CausalReceipt` 在 outbox 原子确认原收据与最新完整快照;命令凭据使用实时的 `options.secret_env` 引用。`CausalSyncClient.control` 与私有 `AC_sync_peer_control`/`ac_sync_peer_control`/Builder Data 命令可持久化注册、确认、回收、退休与完整重同步。`SyncControlRequest(operation_id=...)` 让已完成 RPC 的重试保持幂等;完整重同步须明确提供 `discard_pending=True`,收到收据后才原子采用新世代并归档待送旧编辑。本机 `status` 不读取凭据或网络。`python -m examples.causal_peer_control` 提供暂存 loopback 工作流;明确的本机资产版本可通过 `AssetManifest`、`DirectoryAssetTransport`、`build_asset_manifest`、`sync_assets` 与私有 `AC_sync_asset_manifest`/`AC_sync_assets`(MCP/Builder)操作。全部资产先暂存并通过 SHA-256/大小验证,再一次发布完整目录;受损缓存拒绝使用,脚本保持未执行。`python -m examples.sync_assets` 只使用暂存目录。七种实验性 adapter 已将显式选定的脚本、locator、热键、触发器、通讯录、JSON 设置与已保存的原生 GUI 偏好设置保存为持久化因果 profile。`SyncBindings` 将显式指定的秘密与机器值换成具名引用;`materialize_sync_profile` 发布完整且未启用的原生格式版本。私有 `AC_sync_adapter_snapshot`、`AC_sync_adapter_apply`、`AC_sync_adapter_resolve`、`AC_sync_profile_materialize` 与对应 MCP/Builder 命令提供相同流程。`python -m examples.sync_adapters` 仅使用临时文件。私有绝对路径绑定接受高熵目录名称,仍拒绝可识别的凭证格式。原生数值定义会在存储前以分类错误拒绝超出范围的值,包括超大 JSON 整数。`WorkspaceSettingsSyncAdapter` 仅读取原生 GUI INI 的主题、字号、导航显示/宽度,并发布未启用的 `workspace.ini`;显式复制为独立工作文件后,才能交给新 GUI 使用。`python -m examples.sync_workspace` 不导入 Qt。`SyncWorkspace` 已整合明确来源、持久离线捕捉、因果 HTTP、精确冲突审阅与完整重同步来源基线。私有 `AC_sync_workspace`/`ac_sync_workspace`/Builder Data 共用 status/capture/sync/review/resolve/preferences/materialize 与明确 peer 控制,全部需要 DRIVE;网络凭据使用 `options.secret_env`。`python -m examples.sync_workspace_http` 以两组临时来源与 loopback 演示冲突解决、重启及退休编辑不重放。接收数据保持未启用。引用资产传输见下方;明确的原生工作副本加载见下方,`ConfigSyncClient` 保留时间戳合并。参阅[因果/outbox 指南](../../source/Zh/doc/causal_sync/causal_sync_doc.rst)与 `python -m examples.causal_sync`。 + +延迟创建的 **工作区同步** 页面通过 **Actions** 提供本机状态/采集、网络同步与设备控制、精确因果查看/解决冲突,以及完整未启用发布。粘贴明确的私有工作区配置,凭据只填环境变量名称。同步不会自动应用收到的偏好设置。选择 `workspace`、查看当前版本后,再执行“应用已查看的 GUI 偏好设置”,才会更新当前窗口的主题、字号及导航面板。`SyncWorkspace.preferences(observed=change_ids)` 与现有 AC/MCP/Builder 的 `preferences` 操作,仅在已查看版本完全匹配且无冲突时返回四个标准值;缺少或删除的值采用安全默认值。Worker 保留调用者 context、重新验证 DRIVE 权限,支持取消并在关闭后丢弃旧结果。页面显示修订版、待发送/冲突/引用数与最近成功同步版本;打开页面不会启动连接。 + +明确的原生加载使用 `load_sync_profile(directory, target_root, expected_digest=...)` 与 `LoadedSyncProfile`,并提供私有 `AC_sync_profile_load`/`ac_sync_profile_load`/Builder Data。以已发布的 `files` 文件夹及精确查看的 manifest 摘要创建全新可编辑工作区,先验证全部 bytes、标准原生文件及封存 heads 一致,再原子发布。加载的热键及每个触发器节点都是停用的原生对象;定位器与通讯录 handle 使用工作副本。类型化资产引用及原生热键/触发器路径按工作根目录解析,脚本文字保留原意,秘密保持 placeholder。在“工作区同步”发布后,文件夹/摘要字段会填入结果;选择工作副本存放文件夹,再执行“加载已查看的原生 profile”。其他明确 Actions 可检查所选原生类别、在 Builder 打开已加载脚本快照,或应用其偏好快照。每次操作都重新验证当前调用者与捕获所有者的权限;打开脚本后仍须明确执行 Run;Builder 将导入的命令名称与位置参数显示为字面文字。`python -m examples.sync_profile_load` 使用七种临时来源与真实 PNG,不调用网络或设备。 + +文件夹镜像改用 SHA-256 内容比对,不再依赖修改时间递增:只改时间不重发,时间相同或较旧的内容修改仍会发送。FolderSyncEngine 重启时保留待发与离线修改,逐文件检查停止请求,并持续拥有尚未结束的发送工作。传输所有者可在发布文件后明确调用 record_received(path),避免回发收到的内容。原生 GUI 的固定内容回执处理见下文。 + +文件发送现在会等待每个 DataChannel callback,将缓冲数据限制在 1 MiB,并将通道失败报告给调用方。可选的 `cancelled` 判断会停止排队写入;声明的字节数可检测来源截短或增长。原生文件夹任务绑定授权、引擎、viewer 与 peer connection,所有权变化时停止。收件箱下载移至事件循环之外,通过每个通道最多 32 个请求的队列依次发送。默认手动模式接受数据不代表远端发布完成;确认模式见下文。GUI 重连交接见下文。 + +原生文件接收器现在会在关闭、文件/控制通道关闭、连接进入终止状态、更换通道或撤销文件权限时清除未完成内容。已关闭的接收器拒绝延迟数据;具体 peer/通道与认证检查会保护替换后的传输,也会拒绝 viewer 在认证前接收文件。状态清理先于用户 callback,避免旧失败影响 callback 建立的新连接。文件/审计/状态 callback 保留原始取消及强制中断对象。清理会尝试关闭文件及删除暂存文件,文件系统失败写入日志。现有 Remote Desktop 控件自动使用此生命周期;已完成的目标与原有线上格式仍可使用。 + +本机 `FileReceiveReceipt(path, sha256, size)` 现在会在原子发布后固定原始接收内容。`FileTransferReceiver.handle_message(on_receipt=...)` 与原生 host/viewer 的 `set_file_receipt_callback()` 提供回执,不必重读已发布文件。`FolderSyncEngine.record_receipt()` 避免回发并保留后续本机修改;现有 `record_received(path)` 则明确快照当前内容。GUI 文件夹开关绑定接收回执的引擎及 viewer,并在访问监控目录前重新验证原始授权。相对收件箱/监控路径绑定创建时的工作目录,现有路径通知使用绝对路径。这些本机回执供下文的原生确认模式使用;GUI 重连交接见下文。 + +原生 `FileTransferSender.send`、viewer 的 `send_file` 与 host 的 `push_file` 现在接受仅限关键字的 `require_commit=True`。确认模式会先探测已认证的原生对端,再读取来源元数据/内容;通过第二版 begin/end 元数据发送,并在原子发布后核对传输 ID、不可预测的结束 nonce、SHA-256 及字节数。相对来源路径会在交换前固定。每个文件都重新确认支持与权限,等待有时限;取消、通道/事件循环替换或撤销权限都保留失败状态。GUI 文件夹发送一律要求此模式,因此仅接受但丢失的数据不会推进投递状态;不确定的发送会由同一引擎重试。手动发送仍默认使用原有线上格式。GUI 文件夹投递要求两端都支持确认传输;不支持时会在发送文件内容前失败。GUI 明确重连/恢复见下文。 + +GUI 重连时会为每个面板保留一份内存中的文件夹基准。重新连接后再按开始同步:相同的已认证 host 指纹、绝对监控路径与本机用户,会通过新授权的 sender 接续失败/离线修改。缺少或更换 host 指纹、路径或用户时建立新基准;旧工作仍在运行时拒绝交接,待它退出后才能重试。明确关闭文件夹同步会重置基准;停止/重连 viewer 则保留,关闭应用后清除。指纹沿用既有已认证 host 元数据的信任模型,没有新增密码学身份保证。SDK 可先停止 FolderSyncEngine,待工作确实退出后导出 checkpoint(),将不可变的 FolderSyncCheckpoint 传给路径/递归设置相同且 sender 已明确授权的新引擎。基准包含初始忽略文件与收到的内容,并非远端确认清单。 + +TCP/WebSocket 剪贴板传输沿用明确的 SDK 调用与 GUI 推送剪贴板按钮。收到的文字/图片不会自动传回或广播;用户仍可明确重复发送相同内容。Viewer/host 在读到缓冲消息后,会重新检查原始连接、认证及完整控制权限,再应用剪贴板数据。Viewer 会在编码前固定原通道,拒绝改发至替换后的连接。GUI 排队中的传输保留具体 viewer 与连接发起用户,写入本机剪贴板、明确读取及发送前都会重新检查权限与所有权。过期或撤销的工作会被忽略或报告权限错误;普通 provider/callback 错误仍受控,原始取消与强制中断对象继续传播。文字/图片 JSON 格式及既有 API 不变。Callback 注册仅以弱引用绑定一次原始 viewer,避免断线 viewer 自己保留自己及 Qt 面板直到循环垃圾回收;实际排队数据仍保留原始 peer 与权限,直到处理或丢弃。受控本机协议、loopback 与 offscreen 测试替换原生剪贴板 provider;真机与付费 API 验收仍暂缓。 + +实验性引用资产使用 `SyncAssetBlob`、`SyncAssetReference`、`SyncAssetStore` 与 `SyncAssetHTTPClient`。明确的 `SyncBindings.assets` 别名将选定文件封存为不可变 SHA-256 引用;只改资产也会建立新的因果版本。`SyncWorkspace` 在准备新定义请求前上传已验证分块,支持中断续传,并在完整且未启用的发布前下载引用内容。现有私有 AC/MCP/Builder 工作区/profile 命令共用这些字段。`asset_cache_path` 选择 client cache;signaling 的 `--asset-store`/`AUTOCONTROL_SYNC_ASSET_STORE` 选择独立 server 数据库。带验证的第一版资产路由使用 256-KiB 分块、每文件 64 MiB 上限,每账户默认限制 256 MiB、8,192 块与 4,096 条 blob 收据。超过配额会明确失败;不可变历史不自动回收。原生输出路径相对于 generation 根目录。`python -m examples.sync_referenced_assets` 经临时 loopback HTTP 传送真实 PNG 与脚本,不执行脚本或改当前工作区。 + +实验性持久化配置使用 `ConfigStore.commit(..., base_revision=..., operation_id=...)` 与第二版 signaling PUT envelope。SQLite 事务使 bucket 与重发收据在重启后保留;过期版本或 ID 改配其他内容会冲突。`ConfigSyncClient` 默认条件写入;旧版盲写须在 client/server 明确开启。`--config-store` 选择延迟打开的数据库。私有 `AC_config_store_get`/`AC_config_store_commit` 与对应 MCP 工具共用 Script Builder 的显式 Data 命令。只存储数据,不执行脚本或启用触发器;因果合并与离线 outbox 单独交付。参阅[持久化配置指南](../../source/Zh/doc/config_store/config_store_doc.rst)与 `python -m examples.config_store`。 + +实验性日志产码候选支持 `generate_candidate_from_log(path, run_id=...)`、`AC_generate_candidate_from_log` 与 MCP `ac_generate_candidate_from_log`。它会整合开始/完成快照,保留已记录的控制来源与重试证据,并将不完整重建标为已观察路径。失败/未完成调用、未知命令及遮罩输入均列为排除项,不编造并行顺序。Python/pytest/Robot 产物通过静态、命令及不发送输入的干跑检查。`codegen --from-log run.jsonl --run-id selected` 输出 JSON 审阅包;`-o review.zip` 或 `write_candidate_archive` 可将代码、动作与来源信息一起原子导出。Recording Editor 与 Script Builder 的 **动作 → 审阅日志候选脚本** 提供代码/差异/来源/警告;Builder 导入为独立操作,拒绝覆盖审阅期间的编辑变更。生成与导入均不执行候选。参阅[候选指南](../../source/Zh/doc/journal_candidates/journal_candidates_doc.rst)与 `python -m examples.journal_candidates`。 + +实验性候选模板版本提供 `create_template_candidate`、`preview_template_candidate`、`verify_template_candidate`、`accept_template_candidate`、`revert_template_candidate`,以及对应 `AC_template_candidate_*`/`ac_template_candidate_*` 操作。新的不可变 JSON 版本包保存原始字节及按目标 PNG/JPEG/BMP 格式编码的候选;预览返回有界缩略图。验证在本机数据集比较两个固定版本;接受须有已标注命中、预期 miss、全部已标注案例正确,并提供已预览版本的 SHA-256。接受时重新验证数据集,只原子替换仍匹配的原始内容;恢复精确还原原始字节,拒绝覆盖后续修改。未知样本与原生操作结果分别呈现。验证使用记录的阈值;启用图像不修改脚本阈值。**Self-Healing → 候选模板** 提供五个动作、后台任务、取消与 JSON 证据。运行 `python -m examples.template_candidates` 可执行只使用临时文件的示例。 + +实验性固定图像比较支持 `evaluate_locators`、`evaluate_healing_manifest`、`AC_self_heal_evaluate`、MCP `ac_self_heal_evaluate` 与 **Self-Healing → 版本比较**。报告分别呈现已标注正确率、误判、未知与已验证恢复,包含 p50/p95 及来源,可由 `write_healing_report` 或 GUI 动作导出 JSON/HTML。本机数据集入口不会截图、点击或自行选择网络 backend。参阅[数据集、统计母体与限制](../../../benchmarks/self_healing/README.md)。 + +除了这张表,`utils/` 下还有 311 个无头包,覆盖断言、韧性、数据质量、i18n 审计、脱敏、 +治理、可观测性等等。完整的逐模块地图在 **[architecture_explore.md](../../../architecture_explore.md)**。 + +--- + +实验性的结构化日志已从 `je_auto_control` 导出(也可通过 `utils.action_journal` 使用):`journal_scope` 记录现有 executor 调用,`execute_action_with_journal` 隔离一次执行。本机 loop/parallel/DAG 步骤保留 parent ID,并区分失败、取消与 dry-run。现有 history 拥有者会自动链接显式捕获,包括本机 parallel/DAG worker 开启的 journal;`HistoryStore.journals_for_run` 可查询非拥有式链接,清理 history 不会删除日志文件。CLI 支持 `run script.json --journal run.jsonl [--journal-run-id ID]` 与 `journal run.jsonl [--run-id ID] [--limit 100]`。查询会按追加顺序显示遮罩后的生命周期快照,默认最多 100 条,上限 10,000 条。`AC_journal_capture` 接受命名参数,在拥有者 executor 上执行嵌套 `body`,保留原变量作用域;`AC_journal_read` 与 CLI、公开的 `inspect_journal` 共用遮罩后的有界查询。两个命令都可在 Script Builder 编辑。捕获会在 history 链接、创建文件及执行动作前拒绝含有当次执行已知密钥值的标识符或目标路径。MCP 的 `ac_journal_capture` 与 `ac_journal_read` 提供结构化结果、进度与协作式取消。捕获的日志根目录限制与 observer 会保留到嵌套捕获及本机 workers;查询可在逐条验证时取消。Python 可通过 `JournalRunOptions` 与 `execute_journal_run` 使用相同控制。 + +手动执行可通过 `manual_history_scope`、`AC_history_capture`、CLI 的 `run --history [--history-db PATH]`,或 Script Executor/Script Builder 的 **记录到运行历史** 选择记录。GUI 的可选日志路径也能独立使用;GUI/CLI 保留原有结果 JSON 与变量作用域,命令则返回 `history_id`、`record`、`failed_actions`。已有与嵌套捕获都会关联到新的手动历史记录。CLI 预览使用 `cli.preview` 标签,普通执行使用 `cli.run`。 + +Run History 提供只读日志查看。使用 **操作 → 使用所选执行的日志** 选择来源关联,或用 **选择日志** 指定外部文件;设置执行 ID 与快照上限后,使用 **读取日志**。开始/完成快照保持分离,选中后会显示完整的遮罩数据。**取消读取日志** 与关闭视图会在逐条边界请求取消;文件解析在后台 worker 执行,仅选择关联不会打开文件。 + +`${secrets.NAME}` 解析后的值会在 executor 执行期间的应用程序诊断中遮罩,包括嵌套动作及本机 parallel/DAG。CLI/REST/MCP 请求与排程、trigger、hotkey、email 执行会将遮罩保留到错误处理及 audit/history 写入完成;报表记录保存遮罩后的快照。DAG 会将拥有者的遮罩保留到 node 诊断完成,包括独立调用与自定义 local runner。watchdog、observer 与 callback executor 会将遮罩保留到最后的错误处理;独立规则彼此隔离。CLI stderr 会遮罩,API 结果、抛出的异常与 CLI 结果数据保留原始值。遮罩于拥有者的请求或执行结束时清除。中止的 history 记为 `error`,journal 步骤保持 `cancelled`,不再获取错误截图。取消会穿过非严格执行、恢复/重试、回调与本机 worker;history 结算失败也不会取代原始硬中止信号。 + +## 命令行界面 + +每次 `je_auto_control run`(包括 `--dry-run` 与未带 `--var`)使用独立变量作用域。顶层 `run_from_description` 与 `StateMachine.run()` 也会隔离变量,同一次执行内的动作与状态仍可共享;嵌套调用沿用已有的执行作用域。自行创建的 `Executor()` 保留自己的变量。 + +```bash +je_auto_control run script.json [--var name=value] [--dry-run] [--allow-package NAME] +je_auto_control validate script.json # 别名:lint +je_auto_control fmt script.json [--check] +je_auto_control list-commands [--filter mouse] [--json] +je_auto_control record out.json [--duration 5] +je_auto_control codegen script.json --target pytest -o test_flow.py +je_auto_control failure-bundle failure.zip --error "login timed out" +je_auto_control list-jobs +je_auto_control start-server --port 9938 # TCP socket 服务器 +je_auto_control start-rest --port 9939 # REST API +je_auto_control version +``` + +`--var name=value` 会尽量以 JSON 解析(`count=10` 会变成整数),否则视为字符串。 +`run` 只要有任何动作失败就以 1 退出(仍会跑完整份脚本),CI 步骤会随之失败。旧版 `python -m je_auto_control -e file.json` 入口仍然可用,它的 `-e`、`-d` 与 `--execute_str` 标志也同样在有动作失败时以 1 退出。由 [TestPioneer](https://github.com/Integration-Automation/TestPioneer) 启动时(它会设置 `TEST_PIONEER_ARTIFACT_DIR`),以相对名称要求的 HTML、JSON、XML 报告会写到该目录底下。 + +--- diff --git a/docs/guides/zh-TW/development.md b/docs/guides/zh-TW/development.md new file mode 100644 index 000000000..e8884420a --- /dev/null +++ b/docs/guides/zh-TW/development.md @@ -0,0 +1,90 @@ +# Development and resources + +[README](../../../README/README_zh-TW.md) · [Documentation](../../README.md) + +## 文件與範例 + +| 資源 | 內容 | +|---|---| +| [`examples/`](../../../examples) | 45 個自足腳本:截圖點擊、OCR、排程器、遠端桌面、agent loop、可觀測性、錄製、變數、熱鍵、觸發器、報表、MCP、REST、機密、外掛、computer use、Wayland、跨主機 DAG、chat-ops、pytest/BDD、錨點定位、動作日誌、因果 peer 控制。 | +| [Read the Docs](https://autocontrol.readthedocs.io/en/latest/) | 完整 API 參考,含英文與中文。 | +| [architecture_explore.md](../../../architecture_explore.md) | 逐層記錄每個模組的職責。 | +| [docs/CAPABILITY_MATRIX.md](../../CAPABILITY_MATRIX.md) | 能力 × 平台對照矩陣。 | +| [docs/API_LIFECYCLE.md](../../API_LIFECYCLE.md) | 穩定 API 與棄用政策。 | +| [docs/updates/](../../updates/README.md) | 更新紀錄:各版本說明與完成的工作,每月一個檔(原 `WHATS_NEW.md`)。 | +| [CHANGELOG.md](../../../CHANGELOG.md) | 相容性變更記錄。 | +| [SECURITY.md](../../../SECURITY.md) | 安全政策與回報方式。 | + +--- + +## 開發 + +```bash +git clone https://github.com/Integration-Automation/AutoControlGUI.git +cd AutoControl +pip install -r dev_requirements.txt +uv sync # 或:以已提交的 uv.lock 做可重現安裝 +``` + +```bash +python -m pytest test/unit_test/headless # 無頭單元測試 +python -m pytest test/integrated_test/ # 跨模組流程測試 + +ruff check je_auto_control/ +pylint je_auto_control/ +bandit -c pyproject.toml -r je_auto_control/ + +python test/verify/typing_contract_verify.py # mypy,整個套件,三個目標平台 +python test/verify/typing_contract_verify.py --extras # 同一項檢查,改用真正的 PySide6/aiortc 型別 +python -m sphinx -b html -W docs/source docs/_build/html # 文件,警告視為錯誤 +``` + +dev/main 的無頭工作會保留七天的 `native--` artifact,內含合併行程輸出、 +套件/執行環境版本與退出碼。Linux 經 GDB 保留各執行緒原生堆疊;其他平台保留 Python +faulthandler 輸出,測試失敗仍會使工作失敗。可在 repo 執行單一指令 +`python scripts/ci_native_diagnostics.py --artifact-dir test-artifacts -- python -m pytest -v --tb=short --timeout=120`; +Linux 安裝 GDB 後,可在 `--` 前加入 `--native`。 +含空白/引號的 argv 仍是原始參數,已處理的 `SIGINT` 會傳給子行程。 +Linux 先在完整套件的 debugger 外驗證診斷工具;前置檢查紀錄也收在同一 artifact。 + +選定的 dev 推送由 `.github/workflows/ei-lifecycle.yml` 在隔離 libei/libeis +容器執行,將版本及兩份原生紀錄保留於 `ei-lifecycle--` artifact 十四天。 +半開與 live 釋放子行程分別有十/六十秒時限與 faulthandler;其他子行程失敗使 CI 失敗, +釋放成功必須有 begin/end 標記。半開探測另須有相同整數 fd 數量,live 清理先釋放擁有的 +device refs。run 39507190704 在 libei/libeis 1.3.901-1 通過 9/9 與 20/20 檢查, +包含座標越界拒絕且不轉用 CLI。半開 `ei_unref` 仍會 SIGSEGV,因此保留 runtime 保護, +helper 隔離仍待完成。裝置暫停與序號回讀仍未驗證;受控 socket peer 不代表合成器授權、 +真機或多螢幕驗收。 + +歡迎貢獻——請見 [CONTRIBUTING.md](../../../CONTRIBUTING.md) 與 +[CODE_OF_CONDUCT.md](../../../CODE_OF_CONDUCT.md)。CI 會強制兩條規則:`import je_auto_control` +絕不能載入 PySide6;每個功能都必須同時具備無頭 API 與 GUI 介面。 + +--- + +## 授權 + +[MIT License](../../../LICENSE) © JE-Chen。 +內含與選用第三方元件的授權請見 [Third_Party_License.md](../../../Third_Party_License.md)。 + +- **首頁**:https://github.com/Integration-Automation/AutoControlGUI +- **PyPI**:https://pypi.org/project/je_auto_control/ +- **文件**:https://autocontrol.readthedocs.io/en/latest/ + +舊式 MCP 動作包裝、平行分支及本機 DAG worker 也會保留相同的來源限制。 + +受管指標動作可指定該次觀察的元素索引或縮圖座標,由主機檢查目前畫面並換算原生座標,包含縮放與負螢幕原點。收據保存幾何依據,不保存影像位元組。`AgentObservationStale` 表示分派前已拒絕動作;本機 agent 只在 adapter 確認沒有按住或待處理輸入時,於重試預算內重新觀察。 + +緊急停止先回傳帶有 metadata.details_deferred 的精簡狀態,完整產物連結可由個別任務查詢。 + +受管滑鼠按下前會正規化按鈕擁有權並確認實際游標位置。Windows 指標檢查會拒絕其他視窗遮擋。影像只將指定視窗繪製至清空的私有 GDI 記憶體,幾何變動會拒絕該畫面;繪製或讀取失敗亦會釋放資源。不改用桌面擷取。這些路徑已用模擬原生 API 測試,實際原生驗收仍未驗證。 + +Agent 任務介面將任務範圍、工作流程設定、觸發器、技能及恢復分頁。觀察頁顯示唯讀元素和已驗證、嚴格遮罩的 JPEG,每個邏輯畫面像素對應一個呈現像素。選取元素或影像座標只會編輯該次觀察的動作請求;由 Actions 的「執行觀察動作」透過共用任務 API 送出。切換任務會清除預覽,遲到回覆不能替換目前任務;新畫面必須重新選取,舊索引不能直接重用。關閉介面只解除請求訂閱。 + +受管工作流程可用 workflow_wait/AC_workflow_wait 等待指定控制項的精確值或狀態,只重複讀取;可取消且受動作預算限制,預設五秒、上限六十秒,不重送寫入或提交。固定技能每一步都驗證已完成收據與固定順序,恢復亦不能跳過讀回失敗的步驟;模型自主迴圈仍保留停滯偵測。新表單/跨應用範本會在提交前拒絕原本已匹配的確認值,提交後等待新的狀態轉換。批次可設定 new_record_selector 逐筆重設;確認只證明設定的介面轉換,有交易識別值時應使用它。歸檔範本完成時會重讀指定清單及檔案摘要,清單上限一 MB,總驗證資料上限六十四 MiB。 + +AgentHumanReview 表示未儲存內容或未知對話框需人工審閱;包含外部觀察請求都會記錄 waiting_user 並釋放輸入控制權,明確恢復後仍會重新檢查。Windows 依原生對話框/停用擁有者及英中日已知未儲存文字判定。Workspace 也會拒絕標題首尾帶星號的文件,並可在視窗設定加入 unsaved_selector 與 unsaved_value,於改變排列前檢查應用特有指示;不宣稱能推斷所有程式的未儲存狀態。標準檔案對話框沿用 AC_handle_file_dialog 執行器,受管 driver 只接受唯一精確標題、相同 PID、已確認前景,以及授權根目錄內的絕對路徑。UIA 控制項須屬於實際指定的根視窗,同 PID 的其他視窗也會拒絕。模擬原生與本機 HTTP 測試已有覆蓋,實際平台驗收仍未驗證。 + +主機目標以 AgentTargetProfile 與 manage_agent_target(AC_agent_target,register/get/disable/enable/probe)設定。名稱及設定固定不可替換,目前提供 desktop/files/browser adapter,未實作類型會被拒絕;瀏覽器可使用主機審閱的 helper_python。任務固定主機設定摘要,不能擴大工具、應用、根目錄或網路來源。啟停狀態會跨重啟保存並於分派時檢查;停用會要求暫停及清理,重新啟用仍須明確恢復任務。list_agent_targets/AC_agent_target_list/CLI agent-task targets 只提供被動資訊,readiness=not_probed、native_evidence=not_recorded;完整設定需要 manage_hosts。CLI agent-task target 及 GUI「主機目標」頁使用同一服務。匿名有效 MCP 工具 session 的直接及舊式包裝呼叫都以 operator 權限執行;MCP 主機管理需要已驗證的管理員,可信任的直接 Python 呼叫維持原行為。瀏覽器自動化統一由 WebRunner(je_web_runner)提供,本機開發來源為 D:/Codes/WebRunner;browser profile 使用受管 je_web_runner SDK 契約,依賴診斷不代表原生可用。 + +既有瀏覽器自動化(包含 open_path(URL) 與 AC_open_path)統一交由 WebRunner,Python 套件名稱為 je_web_runner。URL 計畫的 backend 現為 je_web_runner,原本比較 webbrowser 描述值的呼叫端需改用新值;函式介面與本機檔案開啟維持相容。實際 URL 執行需要設定的 WebRunner 專案,缺少時傳出 WebRunnerBridgeError,不改用 OS 瀏覽器。本機開發來源為 D:/Codes/WebRunner;純計畫及注入 opener 測試不需要該套件。協定支援由 WebRunner 與其選用的瀏覽器決定。既有瀏覽器 GUI/MCP/AC 及錄製的 WR_* 動作都使用同一橋接。 diff --git a/docs/guides/zh-TW/evidence.md b/docs/guides/zh-TW/evidence.md new file mode 100644 index 000000000..93ef6f3dc --- /dev/null +++ b/docs/guides/zh-TW/evidence.md @@ -0,0 +1,121 @@ +# Completion evidence and handoffs + +[README](../../../README/README_zh-TW.md) · [Documentation](../../README.md) + +## Local DAG 完成證據的明確移交 + +其他 caller 持有的既有復原子任務,可透過明確且可撤銷的移交,向原 local DAG 提供完成證據。 +以 `manage_agent_recovery` 的 `review_handoff` 提供最終 `task_id`、`batch_id`、`node_id`, +有權管理者再用相同 ID、將返回的 `handoff_review` 填入 `review`,並附非空 `note` 執行 +`create_handoff`。接收者由服務依真實原始 admission 決定。在 `review_continuation` 的 successor +決策中,除 `node_id`、`action`、`task_id` 外明列 `handoff_id`,再審閱並批准整份 continuation。 +最多支援十六層真實復原鏈,包含經私有 admission 的永久唯讀最終驗證者;一般任務歸屬維持原樣。 + +`get_handoff`/`revoke_handoff` 使用 `handoff_id`;`list_handoffs` 使用 `batch_id`、`node_id`。 +建立與採認時重查實際 owner、建立審閱者、簽發 session 的來源根限制、當前接收端限制、固定 scope、 +效果快照、獨立完成及資源退役。批准、開始及後續相依驗證都重查同意;撤銷或證據遺失會阻止採認。 +期限不超過最早終止見證既有的三十天保留期限。公開回應只含有限 ID、摘要與狀態,不含私有參數、 +capture 或 principal 資料庫路徑;不授予一般任務讀取/輸入權、不移轉歸屬或重播。 +跨主機及非 DAG 的移交契約仍列於 `Progress.md`。 + +Agent Tasks 的成果移交頁提供操作選單與 JSON 編輯器;Actions 只準備審閱、建立、撤銷請求, +不自動派送。五個可編輯的 `agent_handoff_*.json` 範例涵蓋 review/create/get/list/revoke。 +Python、AC、CLI、具名 MCP、REST、Builder 共用這些 recovery 操作。本次證據涵蓋契約及自有檔案 +流程;暫緩的原生桌面、瀏覽器、裝置及二十四小時驗收仍須各自提供證據。 + +## 明確續授權唯讀完成驗證 + +原來源的 origin 參照過期或不可用時,明確呼叫 +`manage_agent_recovery("review_completion_authorization", {"task_id": ""})`。 +審閱服務產生的 `verification_spec`、保留/替換/當前 origin 限制,再以相同 `task_id`、返回的 +`snapshot`、`authorization_review` 及非空 `note` 呼叫 `create_authorized_completion`。 +可選 `owner_policy="source_owner"` 在建立時另須返回的 `ownership_review`;不能自行提供新驗證 +規格。仍有效的舊限制保留,新根目錄與原上限、前一讀者上限及當前 session 取交集。 +已重新授權的讀者不能改用一般完成審閱來移除這些限制。 + +子任務永久唯讀,依真實已確認的原效果獨立檢查當前條件,不輸入、不重播、不恢復 capture, +也不修改舊見證。來源/效果快照、實際 owner/reviewer 及原 DAG admission 都會重查。 +建立任務與最終完成各自在自己的 SQLite writer 內寫入後重驗,變更時共同回滾。 +最多支援十六層真實復原鏈;已退役且成功的讀者可再次明確續授權,但保留前次較窄上限及所有仍有效 +的繼承限制。來源/效果證據已改變時仍拒絕,不能藉由 scope 續授權默默修復舊證據。 + +歷史 `get` 保留 succeeded 狀態;新授權失效時,當前 `completion_contract` 為零、 +`completion_authorization` 為 unavailable,DAG 採認與後續相依驗證會拒絕這份證據。 +新的唯讀標記損壞/遺失時,在 helper 啟動前拒絕。以 `completion_task_id` 錄製時沿用原語義動作及 +已審閱的限縮 scope,但草稿仍須自己的新驗證試跑。此流程不發布過期候選,也不續授權已發布技能; +既有技能重新授權流程維持分開。 + +Python、AC、CLI、具名 MCP、REST、Builder 共用兩個操作;Recovery 頁的兩個明確 Actions +沿用所選任務、owner policy 與請求編輯器。可編輯範例為 `agent_completion_authorization_review.json` +與 `agent_completion_authorization_create.json`。remote 唯讀來源、跨主機移交、 +實際應用狀態重建,以及暫緩的原生/裝置/瀏覽器/二十四小時驗收仍列於 `Progress.md`。 + +## 明確移交已續授權讀者的完成證據 + +既有 `review_handoff`/`create_handoff` 現在可明確將已重新授權、永久唯讀讀者的完成 +證據交給實際原 local DAG。指定該讀者的 task ID 與原 batch/node,由服務推導證明;不能自行提供 +policy、擁有者覆寫或授權 bundle。一般成果移交沿用既有規則。 + +預覽的 `evidence.completion_authorization` 顯示完成任務/審閱、固定的審閱摘要、根目錄數量及 +替換/保留/當前 origin ID,不含私人 principal 路徑、動作參數或 capture。建立時以最上層返回的 `handoff_review` +作為請求的 `review`,並提供非空 `note`。每個真實任務都保留已審閱的上限與所有仍有效的歷史限制;不可用的 +參照須明確審閱替換,發出移交當下額外的 session 限制也持續有效。移交沿用讀者已實際驗證的相同 +根目錄;交集改變時須重新審閱及執行唯讀完成驗證,接收者的 session/profile 限制也會持續套用。 + +最多十六層真實復原鏈可混合先前已審閱的可執行子任務及私人讀者。成功的中間讀者必須具備實際 +私人歷史 scope 與退役證明,一般已成功來源沒有這個例外。發出或採認移交時不啟動 helper、不重播 +輸入;舊來源狀態、見證、收據及所有任務擁有者維持原樣。原擁有者只取得有限完成投影,不能因此 +一般讀取其他 caller 的任務。撤銷或授權失效會阻止採認及後續相依驗證。 + +原 accepted-request hash、原始提交見證、私人 admission、graph、owner/reviewer、整條來源/子任務 +快照與最後讀者的續授權都固定在證明內。讀取與寫入後重驗使用同一個 SQLite writer,包含尚未提交 +的變更;發現變動即回滾任務/移交建立。繼承的 `dag_batch` 選項不等於 admission,必須沿有界真實 +復原鏈找到原請求及實際授權身分,不補造 admission。舊的一般完成 binding hash 保持相容;各歷史 +任務各自審閱限制,不能藉由合併歷史繞過正常十六個有效 origin 上限或原根目錄界線。 + +相同有效重試沿用原 note 與 ID,已撤銷 ID 不會重新啟用;重啟與採認保留最早終止見證的三十日期限。 +origin 失效後仍可查 get/list 歷史與 revoke,但歷史不代表可用完成證據或輸入授權。Python、AC、 +CLI、具名 MCP、REST、Builder 共用五個既有操作,Handoffs Actions 與 JSON 編輯器/結果區可顯示 +明確續授權審閱,不自動派送同意。跨主機移交、remote 讀者、實際應用/裝置 +來源及暫緩的原生/瀏覽器/真機/二十四小時驗收仍列於 `Progress.md`。 + +## 明確移交任務來源的完成證據 + +既有五個移交操作也接受真實非 DAG 來源任務: + +- `review_handoff` 提供 `source_task` 與實際最後證據的 `task_id`。 +- `create_handoff` 再以最上層返回的 `handoff_review` 作為 `review`,並填寫非空 `note`。 +- `list_handoffs` 提供 `source_task`;`get_handoff`/`revoke_handoff` 仍使用 `handoff_id`。 + +任務來源與 DAG batch/node 欄位互斥,服務依實際保存的 grant 判定儲存類別。真實 DAG 祖先仍須走 +原 batch/node 路徑,不能藉由已移除 `dag_batch` 的唯讀讀者繞過,也不補造 DAG 節點或 admission。 +一般任務不必虛構提交見證或 idempotency key;實際存在的原請求須固定並在同一 SQLite writer 重驗。 + +既有技能操作明確選擇 `handoff_id`。`record` 以 `completion_task_id` 採認獨立讀者,建立的 draft +仍須自己的新驗證 trial;`accept` 使用完成讀者時,仍保留原 candidate 的真正驗證任務。 +`review_execution` 與對應 `accept` 可選實際 `execution_task_id`;最後證據是獨立讀者時,再提供 +`completion_task_id`。服務核對原本完整語義動作計畫、真實執行 ID 及獨立完成條件,不能把讀者 +當執行任務或替代驗證 trial。 + +grant 只提供私人有限證據視圖,原擁有者、來源狀態與收據維持原樣,一般 get/list/observe/act/ +resume 權限不擴大。發出或採認時不啟動 helper、不重播輸入。真實快照、可選原請求、實際 owner/ +reviewer、退役輸入與有效歷史 origin 均持續核對;新錄製的 draft 保留發出與接收 session 上限。 +失效限制須經真實私人完成續授權,不能靠相同 hash 或自填 scope flag 替代;唯讀採認也不會續授權 +已發布技能原本的輸入權限。 + +來源祖先與後續移交鏈合計最多十六條真實復原連結。期限沿用最早終止證據的三十日,改錨定較新的 +讀者不會延長舊祖先。DAG 與任務 grant 的 INSERT 後及相同重試都重驗撤銷墓碑;來源/請求/角色/ +origin/撤銷變動會回滾 grant、draft 或發布。已撤銷 ID 不重啟,origin 失效後的 get/list/revoke +歷史只顯示有限 ID/hash,不代表持續有效的完成證據或輸入授權。 + +Handoffs 頁可明確選原本機 DAG 或原任務來準備 JSON;三個技能 Actions 準備帶 grant 佔位符的錄製、 +發布與執行審閱,不自動同意或發布。Python、AC、CLI、具名 REST/MCP 與 Builder 共用相同操作及 +真實 caller。`examples/` 提供 `agent_task_handoff_review.json`、`agent_task_handoff_create.json`、 +`agent_skill_recording_handoff.json`、`agent_skill_completion_handoff.json`、 +`agent_skill_execution_handoff_review.json` 與 `agent_skill_execution_handoff_accept.json`。 + +跨主機移交、remote 讀者、實際應用/裝置來源、暫緩的原生與二十四小時驗收,以及未解的 +HTTP409/bootstrap 問題仍列於 `Progress.md`。 + +wheel 與原始碼發行套件包含 REST Dashboard 和 Swagger 的 HTML、CSS、JavaScript 資源。 +安裝後的套件沿用相同的本機 REST 路由與授權規則;提供靜態頁面不授予任務或桌面輸入權限。 diff --git a/docs/guides/zh-TW/implementation-notes.md b/docs/guides/zh-TW/implementation-notes.md new file mode 100644 index 000000000..bd47411a2 --- /dev/null +++ b/docs/guides/zh-TW/implementation-notes.md @@ -0,0 +1,515 @@ +# Implementation notes migrated from README + +Historical implementation notes preserved during the README reorganization on 2026-11-10. These entries describe different development stages and are not a current acceptance checklist. See [Progress](../../../Progress.md) and [updates](../../updates/README.md) for tracked status. + + +成果移交管理已共用 `manage_agent_transfer(operation, request)`、`AC_agent_transfer`、 +`ac_agent_transfer`、具授權的 `POST /agent/transfer` 與 Script Builder metadata。CLI 使用 +`agent-task transfer --operation review_export --request request.json`。審閱回傳批准 token; +建立須提供該 token、原請求 key 與明確 note。匯出/匯入管理可指定已登記主機; +可攜證據管理也可指定已登記主機,由來源核實私有權限。傳輸頁提供四語 Actions、可編輯 JSON 與服務回覆; +審閱不自動核准,核准範本保留原主機、token 與 key 並留白備註。選項變更或關閉頁面後, +舊回覆不覆寫畫面,已接受的匯入仍由服務持有。遠端核准先保存明確同意,失聯或協調端重啟後以原鍵重送,維持同一授權。 +被動診斷僅列出本機契約,不代表即時授權或遠端/原生能力已驗證。只讀完成證據在建立與取用時重新核對原私有同意,不恢復原輸入權限。 +實作驗證紀錄見 docs/updates/README.md;其餘交付與驗收見 Progress.md。 +examples/agent_transfer_export_review.json、agent_transfer_import_review.json 與 +agent_transfer_evidence_review.json 提供可編輯請求,並各有獨立的 create 範本。 + +實驗性的來源主機技能操作,可透過既有 `handoff_id` 明確選取可攜授權與完成/執行任務。 +來源在技能交易內重新核對實際同意、接收者與私有證據,候選/發布寫入後再次核對。 +保留原始動作、候選自己的驗證試跑與明確版本批准;新的技能試跑建立服務產生的全新請求 key, +不為舊有未帶 key 的試跑補造紀錄。此流程不將外部動作或政策移交協調端; +技能證據保留來源主機的原動作/試跑/版本;其餘跨主機驗收與交付見 Progress.md。 +選取移交證據的技能操作,全程保留 runtime 擁有權,操作結束後才釋放。 + +目的端匯入目前仍為實驗功能。明確啟動的服務可透過 runtime 移交控制器與經驗證的 +`/agent/transfer` 接受 `review_import`/`create_import`/`get_import`/`run_import`/ +`cancel_import`/`list_imports`。協調端可透過自己的不透明同意 token 路由這些有限操作; +目的端使用自己的來源登錄與帳號,不轉送協調端 principal/origin 或來源憑證。 +核准意圖在派送前提交;回覆遺失後的精確重試仍對應同一筆匯入。 +啟動時接回已核准且尚未領取的工作;未結算 claim 會轉為待審閱。明確的 `run_import` +以新佇列世代重新核對原收件者、profile、即時 origin 與來源 grant,可重用已驗證私有分塊, +或唯讀核對既有完整目錄與雜湊,不重新下載/發布。續行時新增的 origin 限制仍持續生效。 +已明確排入佇列且未領取的唯讀核對可跨再次重啟;採認前重驗目前位元組、profile 與保留的 origin。 +匯入收據確認完成前,目的端會在最後一次來源回應後重新核對完整檔案清單與內容摘要。 +檔案遭改寫、遺失或增加未列入清單的檔案時,匯入保留 requires_review, +保留使用者修改與原發布成果供審閱。 +目錄身分、位元組或授權變更不能確認發布。取消會使產生者失效;尚未完成收據確認的 +發布保留 requires_review,已確認發布的檔案保留為使用者成果。 +取消或到期的私有分塊帳戶須確認產生者退場才清理;失敗時保留配額,成功重試後才釋放。 +收據維持原本固定期限。 +暫存目錄與預先建立的檔案會在複製位元組前記錄檔案系統身分。產生者退場後, +到期清理可於重啟後重試;遇到置換或無關物件時保留配額待審閱,不遞迴刪除。 +來源維護會清理到期或已撤銷的私有匯出帳戶,包含重啟或授權者移除後;失敗時保留配額。 +來源或目的端清理完成前持續保有 runtime 擁有權;無待清理資料時不取得 runtime 寫入鎖。 +建立/續行回覆會在喚醒新派送前讀取已提交的收據;後續以 get_import 查詢目前進度,避免回覆被新 writer 擋住。 +後續維護會修剪已清理、撤銷且到期的來源中繼資料以回收筆數配額,保留同意/撤銷憑證與其他記錄類別。 +冷啟動維護以唯讀探測發現待處理來源記錄;沒有待處理記錄時不建立移交控制器。 +runtime 最後釋放擁有權時會與控制器建構互斥,並重驗晚建立的控制器是否退場;忙碌時保留擁有權供稍後重試關閉。 +私有快取路徑轉向會在開啟儲存前拒絕;清理失敗時保留配額。 +後續維護會在私有資料確定清理後,回收到期的目的端匯入/派送中繼資料及其已結束佇列紀錄。 +仍在執行、身分被替換或未知狀態的佇列會阻止回收;原同意/撤銷憑證與已發布使用者檔案保留。 +冷啟動維護不啟動監聽端或產生者;待清理帳戶的掃描不受大量未到期歷史紀錄遮蔽。 +可攜證據保留與共用介面已接入;其餘故障交錯與正式交付見 Progress.md。 +來源證據實驗功能已接入 owning runtime 與具名/共用帳戶的本機 transfer HTTP 管理路徑, +提供 review_evidence/create_evidence/get_evidence/revoke_evidence/list_evidence。 +獨立持久授權沿用真實恢復/完成驗證、當前帳戶與原本機 DAG 審核;已登錄 peer 的 evidence +讀取核對實際接收的 key/規格與 DAG 節點,只回傳 ID、雜湊及有限驗證,不授予一般任務讀取或輸入。 +審閱摘要不含 node.request_digest;即時讀取才依精確已審閱原請求補入。 +來源主機技能證據、遠端管理路由與共用介面已接入;其餘故障驗收與交付見 Progress.md。 +協調端 DAG 的實驗採認已接入獨立審閱的遠端恢復授權,固定原來源/key/規格/graph/node 與主機。 +核准與啟動先持久保存暫定狀態,離開本機 writer 後即時查驗來源,再核對原同意及認領,才啟用。 +停止會取消暫定狀態;中斷後只可用同一明確核准請求續接。確認期間保留 runtime 擁有權, +不把獨立 peer 讀取序列化;認領/紀錄及最終採認前後重新驗證。 +授權失效會阻擋後續排程,只對精確已接收的下游任務請求有限暫停;回覆未知或遺失時保留認領並待審閱。 +已完成副作用與無關任務保留;不宣稱已證明原生輸入退休或完成整份故障矩陣。 +舊派送格式升級會保留原核准 origin 與固定期限;多次續行的額外 origin 仍累積生效。 +停止附加的 REST 觀察端不會重派或取消服務持有的匯入,也不釋放 runtime 擁有權;重新連線可讀取同一筆成果。兩主機與獨立程序三主機測試已核對實際位元組及帳號範圍。 +更多重啟/取消交錯、更多暫存故障交錯、完整保留、可攜證據、client/GUI 介面與完整階段檢查 +仍列於 Progress.md;移交收據不授予任務輸入權限,也不能證明任務完成。 + +來源匯出的遠端審閱/建立/查詢/撤銷已接合。協調端發出自己的不透明審閱 token, +綁定實際本機呼叫者、目前主機/憑證摘要、來源審閱、清單摘要與原 key。批准意圖在轉送前 +耐久提交;回覆遺失或協調端重啟後,相同批准仍取回同一來源成果。改換呼叫者、主機、憑證、 +note/key 或來源回覆摘要即拒絕。待審閱與耐久路由各限128筆;到期只清理本機路由 metadata, +保留同意邊界。關閉 runtime 會清除尚未批准的本機審閱快取,已批准的耐久意圖仍可恢復。 +來源使用自身帳號,本機 principal/origin 不轉送。目的端匯入、可攜完成證據與公開介面均已接入; +其餘驗收與正式交付見 Progress.md。 + +既有遠端 DAG 在固定主機設定及每次保留連線呼叫前後,均讀取實際持久化通訊錄。 +其他程序替換/移除端點或憑證、設定損壞或原本本機呼叫者被撤權時,操作會失效。 +讀取不建立 console,也不隔離通訊錄;既有本機服務委派與封閉遠端路由保持相容。 + +跨主機成果移交依明確審閱與各主機本機授權運作。來源核心可審閱已完成檔案成果,建立不可變 blob, +並核對實際發行者/接收者。來源管理與 peer 唯讀 HTTP 路由已可提供經審閱的清單/分塊。 +Peer 使用接收端本身的 bearer/RBAC 與速率限制,在外部 principal/使用者資料庫查詢前拒絕 +本機 principal/origin header;本機服務 client 僅在管理流程保留實際擁有者委派。 +移交要求在伺服器讀取前限制為1MiB;受限 client 在派送要求與解碼成功/錯誤回覆前核對上限, +不變更一般 HTTP 的既有上限。完整私有授權鏈/生命週期驗收、目的端發布/ +證據採認及共用公開介面已接入;其餘驗收與交付見 Progress.md。移交收據不授予任務輸入權限。 + +來源匯出在開啟選定檔案前,排除實際 runtime/移交資料庫與 sidecar、目前來源擁有者及 +發行者的使用者資料庫、服務連線檔與專屬證據目錄。服務登記實際私有檔案,不保留一般成果的 +同名檔名;manifest 只核對選中的輸出。Peer 讀取與相同要求重試會重新核對目前路徑權限, +不重新雜湊歷史使用者成果,並保留操作期限。DAG 成果沿最多十六層真實恢復鏈核對原始 +提交任務、實際請求及本機 DAG admission,重新授權接納者,並排除其不同位置的帳號資料庫。 +恢復子任務不補造提交列;正常 standalone 不要求 DAG 提交列。私有恢復鏈摘要在審閱、建立、 +相同要求重試與 peer 讀取時重驗;實際私有恢復擁有者/審閱者綁定也納入摘要,其資料庫保持私有。 +來源操作在位元組存取與 grant 寫入邊界配合取消;提交後回覆被取消仍可依固定意圖精確取回。 +成果期限依完成來源 updated+30 天計算,不因重試/重啟刷新,也不改用較早祖先的期限。 +本機唯讀 reader 依目前私有完成授權匯出,舊輸入仍撤銷;自動清理、目的端發布與證據採認已接入。 +其餘提交/撤權交錯驗收與正式交付見 Progress.md。 + +Runtime 透過實際 batch 主機 adapter 保管 TransferPeer;具名傳輸固定端點/憑證,於 HTTP 前後 +重讀持久化通訊錄並核對目前本機呼叫者。來源端使用自身憑證驗證,不接收本機 principal/origin +header。來源私有排除只取得實際通訊錄路徑,不建立/重載 console 或隔離檔案。封閉清單與正規 base64 分塊須符合 +匯出 ID/摘要、每塊最多256KiB及原始期限;URL 路徑前綴同樣套用1MiB移交上限,一般 HTTP +保留既有上限;無效預算(含過大整數)在派送前回報型別化錯誤。兩/三主機 +匯入交付仍待完成。 + +閒置背景 worker 以唯讀預檢辨識空佇列,減少輪詢與任務狀態、完成交易的寫入鎖競爭。 +發現工作後仍須在原有交易內重新核對與認領;保留 claim 世代、過期工作回收與重試上限, +不延長任務或傳輸期限。 + +租約維護會在停止交易內核對實際輸入擁有者與世代。延遲的監看程序不能改寫已退休任務的 +恢復證據,也不能取消新租約;接受的最終停止狀態與取消 token 會先於停止交易發布。 +仍有效的撤權與原有期限持續生效。 + +副作用已確認的瀏覽器任務,可透過既有完成審閱與技能流程讀取原本的 WebRunner context。 +原 helper 先永久結束 SDK 輸入/網路,再釋放輸入 journal/租約;runtime 最多保留 16 個 context, +自分離前預留起最多保留 300 秒,不因分離耗時延長。預覽/建立核對實際 effect task 的即時 SDK view;驗證只借用原 context +讀取最新有界 DOM/欄位值,不重新配置輸入、不 ACK 原生輸入、不傳輸,也不另開瀏覽器或 helper。 +退休切換、能力探測與清理也拒絕巢狀工具與原生輸入。 +同 profile 的不同任務分開保管,context ID 本身不授權。私有完成授權審閱可在原上限內明確續授權 +驗證 scope,原輸入規格不變;已失效輸入 origin 與有限私有保管本身均不授予讀取權限。 +擁有者刪除、目標停用、來源變動、期限或讀取失敗會使 context 失效;只有確認程序結束才釋放 +程序擁有權,清理失敗持續追蹤。重啟不還原頁面,網路結束後的 DOM 不能當作新伺服器資料。 +Python/AC/MCP/REST/CLI/Builder 與 GUI Actions 共用原審閱 request;技能錄製保留原動作, +發布須使用自己的實際新驗證試跑與明確選取的完成證據。範例見 +`examples/agent_browser_retained_completion.py`。冷啟動瀏覽器前綴重建、remote reader、正式部署, +以及暫緩的原生/瀏覽器/真機/24 小時驗收仍待完成。 + +已停止且副作用已確認的任務,可用 `manage_agent_recovery("preview_completion", {"task_id": id})` +審閱獨立驗證任務,再將精確 task_id/snapshot 與審閱說明交給 `create_completion`,最後完成新任務。 +私有原子綁定只選擇永久唯讀 helper,不重播來源動作;須有新鮮獨立完成條件與輸入退休證據。 +skill 計畫須全部確認;動態任務不得含未處理的有限計畫或未知效果。 +可先 observe 再 finish;相同 helper 設定只重新檢查就緒,不替換權限,也不快取就緒結果。 +來源/審閱者權限持續有效,涵蓋清理後、明確重試與重啟。API/AC/MCP/REST/CLI/Builder 及 GUI Actions 共用此流程。 +remote reader、正式部署仍列於 Progress.md;桌面能力仍須另行原生驗證。 + +只有受管任務節點的 DAG,可用 `manage_agent_dag("register", {"definition": graph, +"max_parallel": 4})` 註冊耐久批次,再明確 `run_dag(graph, batch_id=batch["batch_id"])`。 +註冊不操作目標;保存整張圖的拓樸、節點契約、主機設定與並行數,目的端 key/規格標記綁定批次。 +可能派送前先提交 claim,目的端精確規格、完成及輸入釋放證據通過後才放行相依節點。成功、中斷或 +提交回覆遺失後都不能再次 begin;`get/list/inspect` 讓協調紀錄跨重啟保留。API/AC/MCP/REST/ +CLI/Builder 及 DAG Actions 的批次註冊/讀取、選填批次 ID 共用流程。 +停止後以 `review_continuation` 取得唯讀整圖快照及逐節點決策,再把審閱的 `snapshot`、`decisions` +與非空 `note` 放入 `run_dag(graph, batch_id=id, recovery=request)`,核准並使用一次續接機會。 +只能採認獨立完成的原任務或真實 recovery 後繼任務;派送限從未 claim 且目的端未接收的 pending +節點。本機授權可在相等或更窄根目錄內更新,未知 claim 永不重播。DAG Actions 提供停止新派送、 +審閱及明確續接;已接受任務仍依自身生命週期處理。將協調交給已明確啟動的服務,可呼叫 +`manage_agent_dag("run_background", {"batch_id": id, "definition": graph, "max_parallel": 4})`; +明確批准的續接另帶 `approval_id`。DAG Actions 提供兩個背景動作;關閉視圖不停止已接受的服務工作, +`get.background` 提供有限佇列狀態。重啟使舊 attempt 失效並要求審閱,不重播排隊或未知派送。 +原 owner 與提交者的權限持續重新驗證,本機任務綁定所屬 runtime。 +既有 `prune_agent_tasks()` 與每小時維護會回收過期且未使用的註冊及已安全結束的成功批次,預設 30 天。 +未決批次持續保護任務/復原證據與接收 gate;結果新增 `deleted_batches`、`deleted_dag_deliveries`。 +其他佇列與使用者成果不受影響,遠端證據保留仍須明確移交契約。 +caller 協調的受管批次固定來源服務路徑、端點、憑證指紋及世代,本機節點共用同一 client;連線檔 +身分變更就停止後續呼叫並要求明確審閱。服務端批次證據直接讀取所屬 runtime,綁定不快取 bearer +憑證。一般非批次 client 保留動態連線行為;受管批次須有含世代的連線資料。 +本機批次節點在耐久 claim 後使用來源服務的封閉 `local_task` transport,以原 owner 接收精確規格/ +key,並在交易內記錄真正 caller。輸入前更新雙方權限及 attempt;管理員失去跨 owner 管理權也會 +阻止執行。沒有可信接收紀錄的舊請求不補造見證。任務 metadata 提供有限 `local_dag_admission` +稽核資料,已接受輸入仍依既有清理契約處理。 +若復原後繼任務須讓原擁有者讀取,preview/review_authorization 請求加入 +`owner_policy="source_owner"`,明確 create/create_authorized 時另帶回 `ownership.review` 為 +`ownership_review`。後繼任務保留來源擁有者,交易內另記實際審閱者,輸入前持續驗證雙方權限。 +GUI 提供擁有者選擇;省略政策仍由建立者持有,沿用既有讀取隔離。DAG 可用正常復原證據採認獨立完成 +的原 owner 後繼任務;已存在的 caller-owned 子任務不自動變更歸屬或補造此紀錄。 +詳見[續接協定](../../source/Zh/doc/ai_agents/agent_dag_batches_doc.rst)。 + +觸發器可明確使用 `manage_agent_trigger("review_authorization", {"trigger_id":"..."})`,再以 +`create_authorized` 提供 `trigger_id`、`snapshot`、`authorization_review`、經審閱的 `spec` 與 `note`。 +新註冊保留完整模板/設定/待處理上限,受原授權、仍有效限制與目前權限交集約束;交易內退休舊綁定, +並啟用未來通知。共用歷史讓已接受事件與未完成任務跨更新、移除及重啟保留,沿用的舊排隊事件不再派送。 +排程從未來時段開始,檔案檢查點保留。API/AC/MCP/REST/CLI/Builder 及 GUI 觸發器選單共用流程; +一般啟用不能取代失效授權,審閱只準備註記留空的請求。 + +已發布技能可用 `manage_agent_skill("review_authorization", {"candidate_id":"..."})`,再明確 +`create_authorized`,提供 `candidate_id`、`snapshot`、`authorization_review`、經審閱的 `spec` 與 +`note`。完整計畫與參數定義固定;保留原根目錄上限及仍有效限制,與目前權限取交集。流程只建立 +同一技能的新草稿及稽核證據,須重新驗證並明確發布下一版,舊版本不變。相同核准去重,過期版本/ +授權內容拒絕。API/AC/MCP/REST/CLI/Builder 與 GUI 技能操作選單共用此流程;trigger 更新使用上方獨立流程。 + +來源授權失效的停止任務,可明確使用 `review_authorization`,再以 `create_authorized` 提供 +`task_id`、`snapshot`、經審閱的 `spec`、`note` 與 `authorization_review`。新任務保留所有仍有效的 +來源限制,將目前權限與原根目錄上限取交集;根目錄只可維持或縮小,其餘權限、模式/模型、預算及 +完成條件固定。核准證據與唯一新任務在同一交易保存;來源及已撤銷的見證不變。既有共用介面均提供 +這兩種操作,GUI Actions 另有授權審閱/建立命令,詳見[恢復指南](../../source/Zh/doc/ai_agents/agent_recovery_doc.rst)。 +任務恢復不解除輸入隔離,也不重建應用狀態;技能與 trigger 使用上方獨立更新流程。 + +停止的任務可用 `manage_agent_recovery("preview", {"task_id": "..."})` 審閱來源收據與快照, +不接觸應用程式。有限 skill 提供剩餘動作及逐筆結果;外部 agent/本機模型任務則提供空白目標的 +`review_template`,須由操作人明確填寫剩餘工作目標,不複製舊動作清單。明確 `create` 時提供 +快照、經審閱的規格與註記,建立有來源關聯的新任務,重新觀察並從零收據開始;重複核准回傳同一 +任務。執行模式、模型/端點、範圍、預算及完成條件固定,未知副作用須先人工核對;不移植舊 +capture、索引、座標或已完成歷史。可用 `AC_agent_task_recovery`、MCP/REST、 +`agent-task recovery preview|create request.json`,或「Agent 任務 → Actions → 審閱剩餘工作/ +重新規劃/建立經審閱的新任務」。已移交的來源不能再恢復,須由新任務繼續。 +登入與視窗狀態的恢復須明確宣告,不能推論:繼任任務(或任何任務)可列出 `resume_conditions`,只接受 +`screen`、`browser` 與 `file_*` 條件(收據是歷史,不能證明現況);第一個動作只在新觀察全部通過時 +才被接受,任一不成立或無法判定就轉為 `waiting_user`,不會動作;有任何動作收據後此關卡即結束。 + +Android/iOS 內建受管 profile 仍未提供。內部遠端副作用防護會依實體裝置識別保存動作前/後確認; +本機 helper 結束但動作未確認時,仍保留隔離。恢復須在 writer 退出後取得可信裝置證據,並以 +後續能使舊指令失效的世代證明安全。尚無內建 SDK 證據來源、裝置 profile 或原生驗收; +剩餘接合列於 `Progress.md`。 +內部 Android 傳輸只連明確設定的既有 loopback ADB server,不呼叫 CLI、不管理 daemon、 +不重試或退回舊 shell;shell-v2 的退出證據有封包/輸出上限,但不代表應用完成、實體裝置 +身分或輸入已釋放。 +內部 Android session 會核對指定端點、實體序號、boot 與預設顯示器焦點,並以原子方式固定 +boot。有限輸入提案在命令連線內重驗身分/焦點,限制文字與結果;提案不授權輸入,仍須接合 +輸入視窗、遮擋、鎖定/真人活動與自有 worker。 +Android 檢查後提案會綁定目前的原生輸入視窗/佇列及 keyguard 證據,核對完整觸控路徑、 +外部攔截與遮擋,並在命令連線內重驗摘要。舊 ANR/歷史紀錄不能證明目前狀態;真人活動、 +全域監看器審閱仍須可信來源授權,內建受管裝置執行仍未開放。 +內部 Android 動作協定 v2 區分完整前置拒絕、輸入失敗、輸入後拒絕與輸入返回。 +缺少/錯誤階段或退出碼不符都維持未知;輸入返回不代表遠端輸入已清空或任務完成,也不授權重試。 +內部自有遠端 SDK worker 會核對精確任務/擁有者範圍、重新授權與真人接回;可信主機 factory +建立前先啟動 parent 監看。持久化 begin 並收到 ACK 後才呼叫 SDK,相符裝置/世代的清理證據 +通過後才送 end;缺證據維持隔離。可信裝置控制來源、WDA adapter 與受管 profile 仍待接合。 +命令編譯器以一次帶標籤的擷取核對三個原生焦點欄位,接受六種順序,缺少/重複/空值仍拒絕。 +前後身分與輸入安全檢查、原本動作期限均保留。自有 POSIX 假裝置減少 Git Bash 讀取程序且維持 +原始檔案 bytes;有限階段/耗時診斷不含命令、參數或輸出。 +內部 AndroidRemoteAdapter 已透過逐命令 AndroidCommandLease 接合 checked session 與 worker; +每個動作消耗一次新的身分/輸入路由/安全觀察,SDK 重新編譯有限命令後才透過 ADB 送出一次。 +裝置端防護須在真人接回、取消或到期後阻止舊寫入;沒有預設 provider,標準 ADB 或停止本機 +helper 不能提供這項保證。清理證據還須綁定新的隨機命令 ID、boot 及獨立輸入/佇列狀態。 +可明確配置主機 hierarchy_reader,提供有界、限 app 的語義元素及經審閱的非敏感文字;未配置時 +仍只有身分 metadata。XML 不授予文字權限;編輯/密碼值及受保護子節點持續遮罩,不發布原始 +XML 或私有 freshness hash。公開觀察版本隨來源及動作更新;Android 元素參照須來自目前可操作 +的語義元素。新的畫面讀回可確認已審閱文字出現,缺少/部分/遮罩內容不能證明文字不存在。 +不新增 CLI/SDK 啟動或擷取備援;真實來源、受保護欄位值驗證、Unicode/IME 與受管 profile 仍待交付。 + +受管畫面完成驗證將內建桌面與 WebRunner 預覽視為部分文字證據;檔案目標與等待視窗階段沒有 +語義畫面證據。已知安全文字可確認出現或推翻不存在條件,遮罩與明確隱藏的標籤不可作證。 +組合條件缺少任一必要證據時保持未知,已知矛盾則判定失敗。精確 DOM/欄位值應使用明確的 +瀏覽器完成讀回;未宣告覆蓋旗標的自訂 target 保留既有行為。 + +`lookup_agent_task("鍵", reviewed_spec)` 可選擇由目的地主機正規化規格,與原擁有者提交時保存的 +不可變摘要比對;回覆宣告 `spec_match_contract=1`,並提供一致/不同/無法核對/查無紀錄。 +CLI 可加 `--spec reviewed.json`;AC/MCP/REST/Builder 共用可選物件。DAG 檢視先查鍵,再於 +目的地明確支援契約時核對已審閱的節點規格;舊端維持 `unverified`,本機來源 witness 不送到遠端。 +鍵改指向別的任務會使舊快照失效;比對一致時仍須核對完成報告的種類、數量與通過結果。 +節點比對不等於整張 DAG 拓樸/原批次批准, +`resume_permitted=false` 仍保留明確續接審閱。 + +`inspect_agent_dag(definition, timeout_seconds=30)` 可檢視本機/已登錄遠端主機的既有提交, +不提交、不暫停、不續跑。提供 `AC_agent_dag_inspect`、MCP、REST 動作、CLI +`agent-task inspect-dag reviewed.json`、Builder 與 DAG Actions。最多 100 節點、最長 300 秒; +遠端仍須主機管理權限,不傳送本機身分/資料庫路徑/來源 metadata,不回傳遠端路徑或原始錯誤。 +`recorded_completion` 只描述查回的任務;節點規格可選擇核對,`resume_permitted=false` 仍表示尚未 +授權整張 DAG 續接。查無紀錄不代表拒絕;GUI 在圖形編輯後捨棄舊檢視。 + +提交回覆遺失時,可用 `lookup_agent_task("原去重鍵")`、`AC_agent_task_lookup`、MCP、 +`POST /agent/lookup`、CLI `agent-task lookup 原去重鍵` 或任務視圖 Actions 查詢。只讀取原身分及 +使用者資料庫範圍,不提交、不續跑、不取得輸入控制權;`found=false` 只是當下快照,晚到請求仍 +可能被接收。GUI 不會讓舊查詢回覆覆蓋後來選取的任務/鍵。DAG 檢視亦沿用此查詢;規格綁定及續接審閱仍待完成; +唯讀查詢仍須具任務存取權限。 + +既有 `run_dag`/`AC_run_dag`/MCP `ac_run_dag`、REST/CLI 動作檔、Script Builder 與 DAG +Actions 選單支援受管任務節點:以 `task` 取代 `actions`/`action_file`,內容包含 `spec`、必填的 +`idempotency_key` 與可選的 `wait_seconds`。省略 `host` 使用明確啟動的本機服務;遠端使用管理員 +已登錄的主機。該端須已配置有背景派送的授權 runtime,本功能不部署服務。規格限 skill 或明確 +配置的本機模型模式,工具、目的地主機路徑及完成條件由該端驗證。 +節點只提交一次,等待完成條件通過、持久完成契約及輸入釋放證據後才啟動下游。同一批次恢復 +須保留去重鍵;不自動恢復暫停任務或重播副作用。停止、逾時或通訊/權限失敗時,已知任務 ID +才會提出有時限的暫停;未收到確證仍為未知。失敗結果保留 ID/去重鍵並阻擋相依節點,GUI +表格顯示任務 ID。本機身分、使用者資料庫路徑及來源 witness 不送到遠端。正式多機部署及原生/ +裝置驗收仍分開追蹤。 + +DAG 型別與函式亦可由 `je_auto_control.api`/`je_auto_control.api.core` 匯入。 + +受管 HTTP 暫停/取消/停止全部/關閉服務使用獨立的每 IP 配額,與一般流量同為每分鐘 120 次、 +突發 30 次;狀態查詢不會耗盡停止請求的配額。登入、即時角色、任務歸屬、稽核與有界輸入清理仍須 +通過。共用客戶端也為 DAG 批次/節點暫停保留傳輸容量;`/agent/dag` 的控制標頭僅接受封閉的暫停 +請求,其他帶標記的操作在派送前拒絕。自訂驗證閘門保留自己的契約;這不保證 OS/網路飽和時的優先權。 + +受管任務在確認輸入清理後才發布成功。清理失敗或仍忙碌時保留輸入租約並要求審閱;確認前 +中斷仍需恢復。完成發布採條件式狀態轉換,不覆寫同時到達的取消要求。既有 GUI/API 任務 +結果以 `metadata.input_released` 顯示釋放狀態;新成功紀錄保存 `completion_contract=1`,舊紀錄 +維持零而不自動認證。成果報告依最終狀態更新,供後續 DAG 協調判定。 + +DAG 節點在執行緒池中保留呼叫者授權、取消與指令限制,自訂 runner 亦適用。每個節點執行前 +重新讀取使用者權限;已刪除的使用者會使節點失敗,後續相依節點略過,各操作依更新後的角色 +檢查權限。預設遠端節點在開啟主機通訊錄或動作檔案前要求 `manage_hosts`,避免透過主機憑證 +擴大本機操作權限。管理員及受信任的直接 Python 呼叫仍可遠端派送。受管節點沿用上述完成 +驗證與停止契約;正式多機部署及原生驗收仍待完成。 + +瀏覽器主機目標可透過可選的 `settings.helper_python` 指定已審閱且已安裝套件的 Python +環境(本機絕對直譯器路徑)。明確指定的 helper 使用 `-I`,從該環境載入已安裝套件;虛擬環境 +直譯器的符號連結保留環境身分。任務選項不能指定直譯器。 +主機管理者可使用 `manage_agent_target("probe", {"name":"reviewed-browser"})`、`AC_agent_target`、 +MCP/REST、`agent-task target probe request.json` 或 GUI 主機目標的診斷操作。 +診斷以獨立且有時限的自有 helper,透過 `je_web_runner` 檢查瀏覽器依賴後結束,過程不取得輸入 +擁有權或啟動瀏覽器。結果可顯示 `python_dependencies_ready`;瀏覽器啟動及原生證據仍明確保持 +`not_probed`/`not_recorded`。`last_probe` 僅為記憶體中的具時間診斷快照,不授予任務權限, +也不啟用停用的目標。桌面/裝置的原生診斷仍待完成。 +已準備的隔離環境安裝兩個功能工作樹建置的 wheel;共用環境與正式工作樹保持原狀。正式服務 +設定及實際瀏覽器驗收仍分開追蹤;所有瀏覽器自動化仍統一由 WebRunner(`je_web_runner`)提供。 + +桌面固定技能現在與瀏覽器技能共用工作階段連續性檢查。桌面 scope 或自有 helper 結束後, +沿用舊前綴前必須審閱,不能用歷史紀錄證明暫停後的表單/視窗狀態。未中斷的工作階段可正常 +執行;檔案 adapter 仍以持久化產物處理復原。檢查在替代 helper 啟動前執行,既有續跑/狀態/ +紀錄介面會顯示人工審閱結果。暫存表單/登入/視窗狀態恢復與可審閱的剩餘步驟重建仍待完成; +原生驗收維持暫停。 + +固定瀏覽器技能的已驗證前綴,現在必須保有原本仍存活的瀏覽器/helper 工作階段。 +暫停、清理、helper 中斷或 runtime 重啟後,舊動作紀錄無法證明表單仍保有先前欄位值; +續跑會在啟動替代 helper 或送出下一動作前進入人工審閱。請明確檢視剩餘步驟並建立新任務。 +尚無保留嘗試紀錄的暫停,以及已審閱為 failed/not_applied 的嘗試,允許全新開始。 +外部擁有者仍可重新觀察新工作階段,再規劃授權範圍內的新動作;未中斷的固定技能沿用原 +工作階段。登入及暫存表單狀態的恢復仍是未完成工作。 + +本機 runtime 的使用者及即時根目錄授權轉送,現在必須由明確的本機服務呼叫啟用。 +一般具驗證的 HTTP 請求只帶指定的 Bearer token;runtime client 驗證 loopback 服務目的地與 +路由後,才附上本機使用者/來源儲存庫/witness 資訊。版本化 `je_auto_control.api` 現在提供 +所有已宣告的 `api.core` 名稱,包含受管瀏覽器命令、目標復原及技能;動作型別 stub 也涵蓋 +所有出貨命令。未解析的延後專案型別沿用產生器既有的 `Any` 政策,避免產生無效名稱。 +並行預算讀取改在資料庫獨佔交易內取樣時鐘,避免鎖取得順序不同造成任務誤判逾時;真正的 +時鐘倒退仍會停止任務。GUI/MCP/REST/CLI 共用這些修正;正式工作樹及既有原生/瀏覽器/ +裝置/24 小時驗收暫停維持原狀。 + +受管瀏覽器檔案命令 `browser_link`、`browser_download`、`browser_upload`(對應 `AC_browser_*`) +委派給 WebRunner 傳輸契約版本 1。上/下載授權必須具有明確的主機及任務根目錄;下載讓瀏覽器 +Cookie 保留於自有 SDK/helper,核對完整長度及可選 SHA256,且不覆寫既有檔案;重用必須符合 +指定 SHA256。上傳將最多 4 MiB 的單一一般檔案讀成核對過的不可變快照,驗證可選 SHA256 與 +SDK 中繼資料,不自動提交表單。網路操作仍全部位於 `je_web_runner`。 +瀏覽器 `download_archive` 預覽接受查詢頁 `url`、明確 `allowed_origins`、授權範圍內 `directory`, +以及具有單純 `name`、`url` 或連結 `selector`/可選 `frame` 的 `files`;每檔可用 `page_url` 覆寫 +查詢頁。流程擷取新連結、下載每檔最多 16 MiB,並產生供獨立核對名稱/大小/雜湊的歸檔清單。 +GUI Actions 只草擬檔案目標/流程/上傳範例,不啟動資源;MCP/REST/CLI/Builder/模型工具 +共用命令,連結讀取仍需輸入控制權限。部署與實際瀏覽器驗收仍待完成,既有驗收暫停保持生效。 + +瀏覽器任務可固定完成條件,例如 +`{"kind":"browser","operation":"value","selector":"#field","value":"expected"}`。 +操作為精確的 `text`、`value`、`visible`(布林)或 `url`(不含定位);必須明確授權 +`AC_browser_read` 與任務 origins,完成條件不會增加權限。Finish 由同一個自有 helper 檢查 +目前頁面位於允許的 HTTP(S) origin,再透過受控讀取命令獨立取得 SDK 完整值;既有 receipt、 +有界預覽或模型停止訊號不能代替讀回。空白/不可用/範圍外頁面、被拒讀回或錯誤驗證回覆 +保持未知;比較不符保持失敗。取消、權限撤銷及人工審閱錯誤保留原類型。 +GUI Actions 可草擬不啟動資源的瀏覽器完成範例;API/MCP/REST/CLI finish 共用驗證器。 +SPA URL fragment 會保留,origin 比對僅略去 fragment。實際瀏覽器/應用驗收及已審閱傳輸仍待完成。 + +受管瀏覽器啟動前,必須先確認 WebRunner 的 `ManagedBrowserSession.contract_version == 1`, +通過後才建立 policy 或開啟代理/瀏覽器。缺少、布林、文字、過舊或未知標記會保留可處理的 +就緒錯誤。SDK 來源 `575e5d2` 提供完整 text/value 讀回:最多 8,000 個 UTF-16 code unit, +超限或無效 Unicode 就拒絕,不截短。AutoControl 對瀏覽器參數與流程預覽資料套用相同 Unicode +上限,在副作用前拒絕。跨來源契約透過真正的自有 helper 與替身 Chromium 驗證;部署與實際 +瀏覽器/原生驗收保持分列。 + + +`draft_agent_workflow("batch_form", config)` 與 `transfer` 可設定 `backend: browser`, +並提供明確的 `allowed_origins` 與已審閱 browser target。CSV/XLSX 來源仍受 roots 限制; +瀏覽器草稿只產生 `AC_browser_*` 動作,不退回桌面輸入。填表提供 `url`、CSS `fields`、 +可選 frame/新增資料控制項、送出與確認 selector;每次填入都有獨立的精確 value 讀回。 +可用 `confirmation_column` 從每列取得預期確認文字。轉填提供 `source_url`/`destination_url`, +擷取 text/value、套用白名單轉換、填入並讀回目的欄位,再驗證儲存;送出前拒絕陳舊確認。 +`AC_browser_wait`/`browser_wait` 只輪詢 text/value,也支援稍後才出現的元素;`wait_seconds` +預設 5 秒,受 action budget 限制,逾時才回來的相符結果仍拒絕,不重播填入或點擊。 +Python/core、共用 catalog/模型 schema、MCP、CLI/REST 任務操作、Builder 及 GUI 流程預覽 +使用同一編譯器。瀏覽器讀回可作為獨立技能證據。實際應用驗收與正式上/下載設定仍待完成; +SDK 啟動前須通過完整有界讀回契約版本 1 的檢查。 + +受管瀏覽器 profile(`kind: browser`)統一委派給 WebRunner 的 `je_web_runner` SDK; +開發來源為 `D:\Codes\WebRunner`,整合來源位於其隔離的受管 session 功能分支。 +Profile 必須提供精確的 `settings.allowed_origins`、瀏覽器專用工具,且不能授權桌面 app; +每項任務另須設定非空、較窄的 `options.allowed_origins`,每次啟用均重新核對兩層範圍。 +註冊不啟動資源;helper 環境須明確安裝已審閱的受管 SDK 與 Chromium,缺少時就緒失敗,不自動安裝。 +`AC_browser_navigate`、`AC_browser_click`、`AC_browser_fill`、`AC_browser_select`、`AC_browser_check` +及 `AC_browser_read` 共用 Python/core、executor、MCP 與 Builder 定義。命令只在受管 helper 中 +運作,透過既有 task submit/observe/act 週期驅動。讀取操作為 `text`、`value` 或 `visible`; +WebRunner 拒絕秘密表單欄位。DOM 索引在目前 observation 內解析 selector/frame,再核對新鮮度。 +失敗副作用保持不確定且需對帳;暫停/取消會結束擁有的資源。GUI Actions 可產生瀏覽器目標範例 +供審閱;DOM 選取只編輯動作請求。專用 helper 跨就緒檢查保留同一個全新 session,正常清理先 +取得瀏覽器 ACK,再結束自己的程序樹;符合完成審閱條件的來源則將原本已凍結的 context +移交 runtime 有界保管。瀏覽器任務不取得共用桌面輸入控制權。跨來源受控測試使用真正 SDK、 +替身 Chromium、自有 IPC/loopback;實際瀏覽器/原生驗收、正式傳輸設定及其餘瀏覽器流程種類仍列於 `Progress.md`。 + +MCP 非同步呼叫會保留接受請求時的角色、session、原路徑政策與工具清單;session 或路徑政策 +結束後,延遲分派會被拒絕。非同步無狀態呼叫仍使用固定 profile。外掛工具清單變更會送達所有 +有效 HTTP session 串流;session 啟停只通知擁有者,並避免重複發送。串流註冊與 HTTP 標頭 +共用鎖,避免提早送出的通知破壞 HTTP 回應。 +純 metadata 的 `benchmarks/mcp_discovery.py --repeats 20` 量測工具數、JSON bytes、暖機後的 +程序內交握、搜尋與啟用耗時。Windows/Python 3.14.4 的紀錄中,完整模式初始有 732 個授權工具、 +358,029 bytes;逐步模式為 5 個、2,029 bytes,回應大小減少 99.43%。交握為 58.263/47.439 ms, +搜尋中位數為 16.243/19.718 ms;逐步啟用中位數為 42.486 ms。此本機量測不含冷啟動匯入及原生操作。 +有日期的 JSON 紀錄位於 `docs/benchmarks/`;既有參數政策的涵蓋限制仍列於 `Progress.md`。 + +MCP 可選擇 session 逐步揭露:`je_auto_control_mcp --tool-mode progressive` 初始只提供五個 +探索控制工具;`ac_mcp_tools_enable`/`ac_mcp_tools_disable` 只改變該 session。 +不會更新工具清單的客戶端可使用 `--tool-mode static --tool-profile ac_screen_size,ac_list_windows`; +預設 `full` 保留不分頁的授權工具清單。逐步/固定模式的 cursor 不透明、只能使用一次,並綁定 +快照與呼叫者;工具、角色或清單設定變更,以及 cursor 過期時,須重新執行 `tools/list`。 +啟停只通知擁有者連線;session 結束會回收 cursor 並使尚在執行中的 metadata callback 失效。 +HTTP/嵌入式使用 `MCPServer.configure_tool_disclosure(...)`;主機環境變數為 +`JE_AUTOCONTROL_MCP_DISCLOSURE` 與逗號分隔的 `JE_AUTOCONTROL_MCP_TOOL_PROFILE`。 +`plan_mcp_tool_profile(...)` 及 Diagnostics Actions 可預覽啟動參數,不會啟動服務。 +無狀態協定使用不分頁的初始固定清單,不保留 session 啟用狀態。唯讀限制也涵蓋後續新增的外掛。 +未驗證/共享 token 連線顯示 operator 工具,與既有呼叫上限一致;主機管理工具仍須已驗證身分。 + +MCP 工具探索提供 `search_mcp_tools(query, limit=10)`、`get_mcp_tool_schema(name)`、 +對應 AC/MCP 指令及 Diagnostics → Actions。搜尋回傳有界摘要、分類與所需權限;完整 schema +須指定單一工具查閱。兩種查詢都重新驗證角色,並遵守 registry 的唯讀篩選;MCP 查詢使用該 +server 的即時 registry,包含外掛變更。CLI 可執行 +`je_auto_control_mcp --search-tools document --limit 5` 或 `--tool-schema ac_mcp_tool_search`。 +完整模式仍為預設;各 session 的逐步揭露可依前述設定啟用。 + +Agent 工具呼叫經 `executor.execute_one(name, arguments)` 回傳原始結果,與動作腳本共用 +授權、變數插值、取消及日誌邊界;拒絕私有 executor 參數。受管任務交付進度見 `Progress.md`。 + +輸入控制權會在分派及輸入確認前寫入持久紀錄。服務崩潰後,先手動放開按鍵與滑鼠按鈕,再以主機管理權限呼叫 `recover_agent_target(target, note)` 記錄審閱並恢復目標;任務未知結果仍須另外核對。工作區文件由輸入 helper 之外的程序啟動,指定的聚焦步驟會等待授權應用程式視窗就緒。 + +受管技能將已驗證的語義流程錄製為不可變候選。`manage_agent_skill` 可預覽具型別的參數、執行獨立驗證任務,並在明確審閱該候選的成功證據後發布編號版本。定位器修復會產生須重新驗證的候選;任務固定使用原版本與摘要。AC/MCP/REST/CLI 與 Agent Tasks 的 Actions 選單提供相同操作。 + +原驗證試跑的動作若已全部確認,可明確審閱/建立並完成獨立唯讀驗證任務,再以 +`manage_agent_skill("accept", {...})` 提供原 `task_id` 與可選的 `completion_task_id`。 +發布保留精確候選/試跑摘要與 pin,核對最多十六層真實唯讀復原鏈、即時權限及獨立完成/清理證據。 +原試跑維持停止,動作不重播;Actions 選單可準備待審閱請求。發布紀錄在暫存 reader 證據到期後 +仍保留歷史 ID/摘要;尚未發布的採認仍須有留存證據。 + +停止的原流程也可透過 `manage_agent_skill("record", request)` 明確提供 `completion_task_id`。 +`task_id` 仍指原流程,草稿保留其已確認語義動作,另採認唯讀 reader 的私有獨立完成證據。 +錄製不重播動作、不改來源狀態;來源/證據檢查與草稿寫入共用交易,並重驗即時權限。 +`provenance.completion_review` 在 reader 保留期後只是歷史紀錄,不授予當前權限。 +草稿與新增驗證條件仍須自己的新驗證試跑,不能直接發布;Actions 選單只準備錄製請求。 + +原驗證試跑只執行部分動作時,先呼叫 `manage_agent_skill("review_execution", request)`, +提供 `candidate_id`、原 `task_id` 與另一個最終 `execution_task_id`;再以相同 ID、返回的 +`execution_review`、`expected_version` 及非空 `note` 明確 `accept`。最多十六層真實可執行復原鏈 +必須確認完整原語義計畫;不同的剩餘流程即使成功也不足。比對包含 JSON 型別、capture 值、預期結果 +與 grounding,但不恢復舊 capture 或重建歷史 UI 狀態。各任務保留原限制與獨立批准;當前 caller、 +全部 owner 及實際建立審閱者都須持續有權限。版本、發布及歷史 `publication.execution_review` +共同提交或回滾,寫入後再查證據與權限。原試跑維持停止並保留 `publication.task_id`,不補造子任務 +為 validation trial。可選 `completion_task_id` 必須驗證最終可執行任務的效果,其證據巢狀存於 +execution 審閱紀錄;過期證據不能批准未發布候選。兩個 Actions 範例只準備審閱/接受請求, +`agent_skill_execution_review.json` 與 `agent_skill_execution_accept.json` 可編輯後使用。 + +受管任務保留來源路徑政策:移除根目錄後,後續動作、事件觸發及技能驗證會受阻。MCP 客戶端根目錄依連線階段隔離,來源授權結束後撤銷;主機設定的固定政策則在明確更換前保留。服務停止會取消實際執行中的工作,包含取得輸入前的模型初始化,尚未啟動的派送則持續保存。 + +實驗性的[受管 Agent 任務](../../AGENT_TASKS.md)提供擁有者範圍內的提交、觀察、動作、驗證、 +暫停、恢復、取消、控制權世代、持久化回執、WorkQueue 派送與本機 Ollama 推論。 +Python、AC、MCP、REST、CLI 與 Agent 任務面板共用背景服務,明確執行 +`je_auto_control agent-task start` 才啟動;新流程不強制依賴外部服務。 +四條可預覽範本涵蓋下載歸檔、CSV/XLSX 填表、跨應用轉移與工作區準備; +使用 `agent-task draft` 或 Actions 的「預覽工作流程」檢查後提交。 +持久化間隔、Cron、檔案與事件綁定會保留核准範圍,每次觸發重新授權並去重; +提交識別碼避免重試與重啟時建立重複任務。 +提供擁有者範圍內的回執與結果不明對帳,連結執行歷史、journal 及逐筆報告; +服務快取預設保留 30 天,保留使用者輸出與外部 journal。 +證據快取以完整資料庫路徑及持久資料庫身分綁定於 `.agent-evidence-cache/`。 +還原的資料庫與舊版快取保留原歷史參照;下次動作或報告建立新的自有 journal 分段, +不讀取或搬移歷史檔案。任務 metadata 的 `artifact_cache_state` 為 `owned` 或 `historical`。 +保留清理只移除目前資料庫可辨識的自有快取檔;歷史檔案保留,留存的私有根目錄禁止成果匯出。 + +Linux 上的 helper 程序可改由選用的 [owner 服務](../../../native/owner_service/README.md) 執行: +root guardian 把每個 helper 放進它自己的 cgroup v2 樹,helper 帳號無法離開;關閉 channel 會 +結束整棵樹(含逃離的後代),guardian 重啟後會清理崩潰留下的程序。root 擁有的 +`/etc/je_auto_control/owner_service.json` 綁定檔只讓完全列出的 helper argv 經由服務啟動; +驅動桌面或瀏覽器的 helper 一律以本機程序執行,因為受保護的 helper 以獨立 ID、空環境執行,無法存取顯示; +沒有綁定檔時 helper 仍以本機程序執行,`agent-task status` 在 `helper_containment` 回報模式。 +Python 套件不會建置、安裝或啟動服務,且在審閱後的版本開啟閘門前,建置出的服務拒絕受保護啟動。 + +`agent-task readiness`(`agent_runtime_readiness`、`AC_agent_runtime_readiness`、MCP 工具及 Agent 任務面板的 +Actions 選單)回報桌面輸入與擷取、真人在場來源、Android 與 iOS 控制、瀏覽器和本機模型各自的狀態: +`unsupported`、`missing_dependency`、`unauthorized`、`not_probed`、`not_recorded` 或 `measured`。它只讀環境變數、 +`PATH` 與已安裝套件,不連線裝置、不啟動 helper、不要求權限,所以不會回報 `measured`,每一項的 +`native_evidence` 都是 `not_recorded`;已安裝的工具只算 `not_probed`,不代表可用。 + +部署或回復前須比對來源與成品雜湊,不能只憑相同版本號判斷私有快取相容性。 +不具此私有根目錄保護的舊程式不得沿用新版資料庫/快取。經審閱的回復須使用相符的升級前狀態 +及其原記錄位置,先取得自有輸入退場確證,並從所有舊版任務根目錄排除留存的新版私有檔案; +保留不明 journal,不重播副作用。無法核實時維持相容版本。 + +Windows USB 列舉明確以 UTF-8 輸出及解碼,PowerShell 子程序維持隱藏。 +Python UTF-8 模式開啟或關閉時,Unicode 裝置名稱與診斷均完整保留;列舉仍為唯讀。 +原生呼叫使用專屬 helper,支援取消、逾時、輸入記錄清理與跨資料庫的桌面排他控制。 +Windows 共用桌面的持續來源跨 runtime/任務/helper 共用,監看開始後須重新累積解鎖閒置 60 秒。 +僅支援已確認的作用中本機 console;遠端、shadow 及不明 session 一律拒絕。 +每個 helper 在輸入 ACK 前後即時查核同一主機租約;來源/reader 失效會暫停輸入, +未確認的按住輸入清理仍保持隔離,須明確重試。關閉一個 runtime 不會停止其他 runtime 的來源。 +目標說明只公開粗略 `presence` 狀態與 `native_evidence=not_recorded`,不啟動探測。 +`agent-task stop-all` 停止可見任務。 +其他共用桌面須有可信活動 adapter。原生平台驗收與其餘待辦列在 `Progress.md`。 + +Linux 內部 presence_peer_linux 以不可繼承的 pidfd 保留原始 Unix stream 或 seqpacket 連線者, +查核帳戶、程序建立時間、namespace 與存活狀態,不另依 PID 開啟程序。程序身分不代表桌面或輸入權限。 + +內部 LinuxListener 與 LinuxChannel transport 擁有受保護的 Unix endpoint、socket 與 peer。 +每個有界 JSON 封包須有仍存活的原始 writer 的核心憑證與 pidfd;額外、遺失、負值或截斷的控制資料 +直接拒絕,收到的描述元在交付前釋放。排隊與 I/O 共用同一期限;取消撤銷交付,尚未完成或失敗的 +清理維持未確定。未知檔案系統物件保留不動。路徑權限不能隔離同 UID 的敵對程序,使用者空間的有界 +等待也不保證核心 syscall 的硬即時完成。 + +X11 與 macOS 已有真人活動來源。X11 只計入真實裝置的 XInput2 raw 事件(XTEST 從屬裝置一律排除), +並從 logind 讀 `Active`/`LockedHint`;沒有 logind 或 `XDG_SESSION_ID` 時視為鎖定。macOS 用唯讀的 session +event tap(需要輔助使用權限);只有程序從非 HID 來源狀態送出的事件才算注入,有疑義時讓任務等待而不是接手。 +Wayland 沒有可信來源。Linux 的 presence broker、worker 與 server 已改經此 transport:自有 worker 綁定 +全新的私有 endpoint 並在 bootstrap 回覆中回報,broker 只採用該 endpoint,連線時先核對 listener 即其所列 +程序,再做 presence challenge。macOS 尚無 presence transport;原生驗收前 runtime 仍拒絕非 Windows 共用 +桌面任務;此 transport 不是完整 Linux 應用或原生輸入驗收。 + +[![PyPI](https://img.shields.io/pypi/v/je_auto_control)](https://pypi.org/project/je_auto_control/) +[![Python](https://img.shields.io/pypi/pyversions/je_auto_control)](https://pypi.org/project/je_auto_control/) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../../LICENSE) +[![Documentation](https://readthedocs.org/projects/autocontrol/badge/?version=latest)](https://autocontrol.readthedocs.io/en/latest/?badge=latest) + +**AutoControl** 是一套開源、跨平台的 **computer-use 與 GUI 自動化框架**,面向 AI agent、Python 應用程式與自動化測試。它能驅動滑鼠與鍵盤、透過樣板比對、OCR、作業系統無障礙樹或視覺模型找到 UI 目標、錄製與重播流程,並以 JSON 動作檔執行——支援 Windows、macOS、Linux(X11 與 Wayland)、BSD、Android 與 iOS。 + +每項能力都以三種形式提供:**Python API**、可在 JSON 檔/CLI/伺服器使用的 **`AC_*` 動作指令**, +以及 **GUI 分頁**。沒有任何功能只存在於 GUI。 + +**[English](../../../README.md)** · **[简体中文](../../../README/README_zh-CN.md)** + +--- diff --git a/docs/guides/zh-TW/integrations.md b/docs/guides/zh-TW/integrations.md new file mode 100644 index 000000000..a1dd132bf --- /dev/null +++ b/docs/guides/zh-TW/integrations.md @@ -0,0 +1,126 @@ +# Agents and integrations + +[README](../../../README/README_zh-TW.md) · [Documentation](../../README.md) + +## AI Agent 與 Computer Use + +**AutoControl 是開源、跨平台的 computer-use 與 GUI 自動化框架。** + +當 AI agent 需要操作真實桌面、原生應用程式、真正的瀏覽器視窗、遠端桌面或行動裝置,而不只是操作瀏覽器 DOM/API 時,使用 AutoControl。 + +### 何時選擇 AutoControl + +- 真實滑鼠與鍵盤輸入 +- 螢幕擷取與座標操作 +- OCR 與原生無障礙樹 +- 影像/樣板比對 +- Vision-Language Model UI 定位 +- Anchor 與 self-healing locator +- 跨平台桌面/行動裝置自動化 +- JSON 動作檔 +- MCP computer use + +建議的 agent loop: + +**observe → identify → act → wait → verify → recover** + +完整的 [AI Agent 指南](../../../AI.md) 提供 MCP 設定、工具選擇、OpenAI 整合、安全性與 computer-use 關鍵字。 + +### AI-friendly MCP + +```bash +pip install je_auto_control +je_auto_control_mcp +``` + +MCP 提供完整的 `ac_*` 工具,以及 `click`、`type`、`screenshot`、`find_text`、`click_text`、`drag`、`focus_window`、`wait_image` 等短名稱 alias。 + +只做檢查: + +```bash +je_auto_control_mcp --read-only +``` + +只需要 canonical `ac_*` 名稱: + +```bash +JE_AUTOCONTROL_MCP_ALIASES=0 je_auto_control_mcp +``` + +OpenAI agent 請使用 `export_openai_tools(only=[...])` 提供聚焦工具集,不要一次提供整個 AutoControl 命令目錄。 + +### 專案識別 + +**專案:** AutoControl
+**Repository:** `Integration-Automation/AutoControlGUI`
+**Python package / PyPI:** `je_auto_control`
+**MCP command:** `je_auto_control_mcp` + + +--- + + +## 伺服器與整合 + +| 介面 | 啟動方式 | 說明 | +|---|---|---| +| **MCP 伺服器** | `je_auto_control_mcp`(stdio)或 `AC_start_mcp_http_server` | 820 個工具,供 Claude Desktop/Claude Code/自訂 tool loop 使用:完整的 `ac_*` 工具介面,以及常用 GUI 操作的短名稱 alias。除了以 `initialize` 握手的各版協定,也支援無狀態的 MCP 2026-07-28。Bearer 驗證、TLS、稽核記錄、限流、外掛熱重載、CI 假後端。 | +| **REST API** | `je_auto_control start-rest` | Bearer token、逐 IP 限流與鎖定、SQLite 稽核 hook、`/metrics`、`/openapi.json`、`/docs` Swagger UI、`/dashboard`。 | +| **TCP socket 伺服器** | `je_auto_control start-server` | 以換行分隔的 JSON 動作清單。預設綁 `127.0.0.1`。 | +| **pytest 外掛** | 安裝後自動生效 | 提供 fixture 與供 pytest-bdd/behave 使用的 Gherkin step library。 | +| **語言伺服器** | `python -m autocontrol_lsp.server` | 為 `AC_*` 動作 JSON 提供補全與診斷,指令清單直接取自執行期的指令表。 | +| **遠端桌面** | `RemoteDesktopHost` 或 GUI | TCP、WebSocket 或 WebRTC;TOTP、信任清單、TURN 設定、檔案/剪貼簿/音訊同步。 | + +除非明確指定,所有伺服器都綁在 `127.0.0.1`。 + +MCP 視窗狀態工具 `ac_window_minimize`、`ac_window_maximize` 與 `ac_window_restore` 在後端接受要求時回傳視窗 handle,遭拒時回覆 `isError: true`(包括 handle 失效或啟用請求被拒)。Win32 原始 `ShowWindow` 的先前可見性由後端正規化處理。 + +**套件閘門。** `AC_add_package_to_executor` 與 `AC_add_package_to_callback_executor` 會匯入 Python 套件並把成員註冊成命令,所以從上面任何一個入口送來的動作清單都可能載入 `os` 或 `subprocess`。沒有被放行的套件不會載入:不在允許清單上的套件在匯入前就被拒絕,該動作以 `AutoControlExecuteActionException` 失敗。放行套件(含子模組)的方式:在 Python 裡呼叫 `executor.allow_packages("name", …)`;對所有入口——兩個 CLI、socket/REST/MCP 伺服器與排程器——設定環境變數 `JE_AUTOCONTROL_ALLOWED_PACKAGES`(以逗號分隔的名稱,行程啟動時讀取);或只對一次 CLI 執行使用 `je_auto_control run script.json --allow-package NAME`(可重複)。`executor.set_allow_arbitrary_packages(True)` 會對所有套件打開閘門,也就是先前版本的預設行為(當時會發 `DeprecationWarning`)。這些都不是 `AC_*` 命令,所以動作清單不能自己打開閘門。 + +**選用的強化設定。** 下列各項在設定之前都是關閉的,沒設定的伺服器行為與先前相同。`JE_AUTOCONTROL_RBAC_USERS=<使用者檔>` 讓 REST API 與 MCP HTTP 傳輸把 bearer token 對到使用者,並依角色(viewer/operator/admin)授權每一個路由、工具與特權 `AC_*` 命令;此時共用 token 會被拒絕。`JE_AUTOCONTROL_MCP_PATH_ROOTS`(以作業系統的路徑分隔字元分開的目錄)把每一個屬於檔案路徑的 MCP 工具參數限制在這些目錄裡,`JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT=1` 再加上 client 的 `roots/list`,`JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` 限制 `ac_resolve_ref` 可以讀哪些 `env://` 名稱。`JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` 讓端點只能驗證 Ed25519 簽章的動作檔而不能簽章(`create_signing_keypair`;私鑰留在簽章的機器上)。遠端桌面的 viewer 只把 host 推來的檔案寫在 `~/Downloads/AutoControl` 底下(`JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR`);這一項預設就是開的。 + +REST GUI 在使用者存放檔啟用時顯示 RBAC 模式並停用共用 token 欄位。`rest_api_registry.status()` 提供 `rbac_enabled`,該模式的 `token` 為 `null`;請使用個別使用者 token。只實作 `check()` 的自製 REST gate 仍可用於共用 token 模式;RBAC 要求已驗證的使用者 context,會拒絕沒有身分的成功結果。 + +RBAC viewer 不會取得列管的敏感讀取工具,即使 MCP `readOnlyHint` 為 true:剪貼簿/歷史、本機文件/資料/SQL 與 dotenv 讀取、參照解析、認證資料產生、持久存放區讀取、對外檢查、麥克風擷取與外部 VLM 請求都需要 operator/admin。斷言容器的 spec 也可能讀取這些資源,因此同樣需要 operator。螢幕觀察與純輸入解析維持既有分類。`ac_realize_item`、`ac_idempotency_begin` 與 `ac_rate_limit` 會改變狀態,已從 `--read-only` 模式排除。 + +間隔/cron 排程、觸發器、熱鍵、watchdog 規則、webhook、e-mail 觸發器與 observer 回呼會保留註冊者身分。每次觸發重新檢查來源使用者檔與角色;已刪除的使用者、無法使用的來源檔與 viewer 不能執行背景工作。啟動 daemon 不會改變既有工作的擁有者。擁有者資訊不保存 RBAC bearer token;未帶 `store_path` 的明確 Python `AuthorizationContext` 保留角色快照,未在 RBAC 下註冊的工作會清除 worker 原有身分。observer/watchdog 回呼使用獨立變數範圍,watchdog 動作失敗不會算成成功排除彈窗。巢狀回呼會保留呼叫端的失敗計數;webhook 擁有者被撤銷權限時回應 HTTP 403 與 `fired: false`。 + +### 遠端桌面的線路協定 + +TCP host 在送出 `AUTH_FAIL` 前就釋放認證失敗的 client 名額。Viewer 即使因錯誤 token、錯誤握手訊息或拒絕核准而失敗,也能立即重試,不必等 socket 清理或日誌完成;待處理握手仍有獨立的資源上限。 + +把主機開出去之前值得先知道,而且這段在其他文件裡都沒有寫。預設傳輸是**裸 TCP +上的長度前綴分幀**(不需要額外相依),連線一開始就是 **HMAC-SHA256 的 +challenge/response 握手**:驗證沒過的觀看端在拿到任何一張畫面之前就會被斷掉。 +JPEG 影格依設定的 FPS 與品質編碼,再透過一個共用的**最新影格槽**發給已驗證的 +觀看端——所以慢的觀看端是**掉影格**,不會把其他人一起卡住。觀看端送來的輸入是 +JSON,會先比對**動作允許清單**才交給既有的輸入包裝層執行,觀看端無法自己發明 +新的操作。 + +```python +# 讓別人連進來——開一個主機,把 token 與 port 給對方 +from je_auto_control import RemoteDesktopHost +host = RemoteDesktopHost(token="hunter2", bind="127.0.0.1", + port=0, fps=10, quality=70) +host.start() +print("listening on", host.port, "viewers:", host.connected_clients) +``` + +```python +# 控制另一台機器——連上去並送輸入 +from je_auto_control import RemoteDesktopViewer +viewer = RemoteDesktopViewer(host="10.0.0.5", port=51234, token="hunter2", + on_frame=lambda jpeg: ...) +viewer.connect() +viewer.send_input({"action": "mouse_move", "x": 100, "y": 200}) +viewer.disconnect() +``` + +也可以用 IP 允許清單(CIDR 網段或個別位址)限制誰連得進來,清單外的對端在握手 +階段就會被拒絕: + +```python +RemoteDesktopHost(token="tok", ip_allowlist=["10.0.0.0/8", "192.168.1.100"]) +``` + +--- diff --git a/docs/guides/zh-TW/setup.md b/docs/guides/zh-TW/setup.md new file mode 100644 index 000000000..be799a002 --- /dev/null +++ b/docs/guides/zh-TW/setup.md @@ -0,0 +1,294 @@ +# Installation and configuration + +[README](../../../README/README_zh-TW.md) · [Documentation](../../README.md) + +## 安裝 + +```bash +pip install je_auto_control # 核心 +pip install je_auto_control[gui] # 加上 PySide6 桌面應用程式 +``` + +需要時才安裝的選用套件: + +| Extra | 啟用的功能 | +|---|---| +| `gui` | PySide6 桌面應用程式(51 個分頁):左側可搜尋的導覽面板(`Ctrl+K`)依分類列出全部功能,分頁在第一次開啟時才建立,**View → Theme** 切換深色/淺色。窄視窗的內容可捲動;關閉視窗時,主題、字級、導覽面板顯示(`Ctrl+B`)與寬度會存入 `~/.je_auto_control/gui.ini`。主題直接使用 Qt,不需要 `qt-material`。 | +| `webrtc` | WebRTC 遠端桌面、USB 直通(`aiortc`、`av`) | +| `signaling` | 獨立的訊令/rendezvous 伺服器(`fastapi`、`uvicorn`) | +| `discovery` | mDNS / Zeroconf 區網主機探索 | +| `pdf` / `office` | PDF 與 Excel/Word/PowerPoint 讀取 | +| `fuzzy` / `locale` | `rapidfuzz` 模糊比對、`babel` 地區解析 | +| `s3` / `audio` | S3 產出物儲存、系統音量控制 | + +以分頁關閉鈕關閉 factory 建立的功能面板時,下一次 Qt event loop 會釋放 widget、訂閱與計時器;重新開啟會建立新面板。**View → Tabs** 與嵌入用的 `hide_tab` 只隱藏並保留狀態。`tab_registry.open/close` 與 `close_tab` 提供明確的生命週期介面。既有的擁有者表單與 Remote Desktop 在生命週期遷移完成前,關閉後仍保留以供重用。 + +**Windows arm64** 裝得起來也跑得起來,少的是上游在那裡發不出來的那些: +`opencv-python` 與 `cryptography` 都沒發 `win_arm64` wheel。所以 `find_image*`、 +`screenshot()`(OpenCV/BGR 那一支——Pillow 截圖仍可用)、秘密金庫、動作檔加密、 +ACME/TLS 與加密錄影會拋出指名缺哪個 wheel 的錯誤,而不是難以追查的失敗。 +滑鼠、鍵盤、螢幕尺寸、視窗管理、無障礙樹、動作執行器、MCP/REST/TCP 伺服器 +與 GUI 都正常——這是實測的,不是推論的。其他平台不受影響。 + +**系統需求:** Python ≥ 3.11。 +Linux 請先安裝建置前置套件: + +```bash +sudo apt-get install cmake libssl-dev +``` + +OCR、VLM 與 LLM 後端(`pytesseract`、`easyocr`、`paddleocr`、`anthropic`、`openai`) +都是按需載入——只裝你實際會用到的。Tesseract 的部分,`find_tesseract_cmd()` 找出執行檔 +(依序是 `$TESSERACT_CMD`、`PATH`、安裝程式的預設資料夾),`set_tessdata_dir()` 把它指到 +語言資料夾,`ocr_status()`/`ocr_languages()` 在第一次 OCR 之前就說出缺了什麼。 + +**記錄檔:** 函式庫寫到 `~/.je_auto_control/logs/AutoControlGUI.log`,第一筆記錄時 +才建立(只 import 不會寫任何檔),同一個帳號的所有行程共用(附加寫入、每行帶行程 ID, +超過 10 MB 就改名成 `.1`)。要寫到別處就設定 +`JE_AUTOCONTROL_LOG_FILE`,設成 `os.devnull` 則不寫檔。 + +--- + +## 平台支援 + +| 平台 | 後端 | 輸入 | 螢幕擷取 | 錄製 | 視窗管理 | +|---|---|:---:|:---:|:---:|:---:| +| Windows 10 / 11 | Win32 ctypes(可選 Interception 驅動) | ✅ | ✅ | ✅ | ✅ | +| macOS 10.15+ | pyobjc / Quartz | ✅ | ✅ | ✅¹ | ✅ | +| Linux X11 | python-Xlib(可選 `uinput`) | ✅ | ✅ | ✅ | ✅ | +| Linux Wayland | 經桌面 portal 的 libei,或 ydotool/wtype + 擷取工具 | ✅ | ✅ | ❌ | ❌ | +| FreeBSD/OpenBSD/NetBSD | python-Xlib,與 Linux 同一套 X11 後端 | ✅² | ⚠️² | ✅² | ✅² | +| Android | adb + uiautomator2 | ✅ | ✅ | — | — | +| iOS | WebDriverAgent / facebook-wda | ✅ | ✅ | — | — | + +¹ macOS 的錄製走 Quartz event tap,需要**輔助使用**權限 +(系統設定 → 隱私權與安全性 → 輔助使用)。沒有授權時會直接拋出並指名 +缺的是哪個權限,而不是安靜地錄到一個空的 session。 + +² BSD 直接跑同一套 X11 後端——同一個 X server、同一個 `python-Xlib`,而輸入、 +錄製與視窗管理就只相依這一個套件。`freebsd` CI job 在真的 FreeBSD 14 上驅動真的 +輸入,再從 X server 讀回來;OpenBSD 與 NetBSD 走同一條程式路徑,只是沒有 CI +runner。唯一的例外是螢幕擷取,而卡的是打包不是平台:它走 Pillow/mss 與 OpenCV, +而 `opencv-python`、`pillow`、`cryptography` 都沒有發 FreeBSD wheel。從 ports +建起來之後,擷取、影像比對、OCR 與動作加密也都能用——`import je_auto_control` +本身已經不需要它們任何一個。 + +Wayland 的按鍵、按鈕與指標輸入在 `auto` 模式下,僅於選用原生後端缺席時改用 CLI。 +portal 請求開始後,拒絕、逾時、握手失敗、裝置暫停或權限撤銷都會停止輸入, +不會自動切換提供者;重複呼叫保留不含原生資源的失敗狀態,不重開同意對話框。 +`JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND=libei` 強制原生輸入,`=cli` 明確選擇 CLI。 +解決權限問題後,可明確呼叫 `je_auto_control.linux_wayland.libei.reset_default_backend()` +以允許重新請求。原生組合鍵中斷時會在同一後端嘗試釋放所有已按下的按鍵,並保留原始取消。 +此行為不改變明確的 wtype 文字輸入路徑或螢幕擷取選擇。 + +`ydotool` 退路需要 +**ydotool 1.0 以上**。AutoControl 送的每一個參數都是那一版才有的;0.1.x +(Debian bookworm 與目前所有 Ubuntu 仍以這個名字提供,Debian trixie 則根本沒有) +對同一批參數回傳 0 卻不送出任何事件。AutoControl 會偵測並直接拒絕, +而不是為根本沒送出的輸入回報成功。Arch、Fedora 與 Debian unstable 提供的是 1.0。 + +這條退路要能**準確定位**,還有一個前提:合成器的指標加速度必須是關的。 +`ydotool mousemove --absolute` 並不送任何絕對事件——它先把游標推到合成器夾取的 +那個角落,再送相對位移,所以這段位移會被合成器加速。對真的 wlroots session 量到的是: +libinput 的預設 profile 讓游標走的距離正好是要求的兩倍。ydotool 自己的 `--help` +也是這樣寫的;AutoControl 每個行程會記一次警告,而不是安靜地把點擊放到錯的地方。 +請對 ydotoold 的裝置關掉加速度(sway:`input type:pointer accel_profile flat` +加上 `pointer_accel 0`),或是裝上 `liboeffis`,改走協定層本來就是絕對座標的 libei。 + +倍率是合成器自己的設定,用戶端讀不回來,所以只有你知道它關了沒有: +`JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL=flat` 表示已經關掉,移動就不再出聲; +`=strict` 則寧可拒絕這次移動,也不讓點擊落在別的地方;不設定就維持 +「警告一次後照樣移動」的預設。 + +Wayland 的螢幕擷取需要合成器對應的工具,因為沒有單一工具能涵蓋全部:wlroots 系 +(sway、Hyprland、river)用 `grim`,GNOME 用 `gnome-screenshot`,KDE 用 `spectacle`。 +裝好其中一個之後,所有擷取路徑——截圖、影像與錨點定位、OCR、螢幕錄影、遠端桌面——都會 +經由它。三個都沒裝時,內建 D-Bus client 會透過 session bus 嘗試 `xdg-desktop-portal`,第一次可能會跳 +同意對話框。再不行,擷取會帶著安裝提示明確失敗,而不是回傳空白的 XWayland root; +`je_auto_control.api.run_diagnostics()`(以及 GUI 的 Diagnostics 分頁)的 `screen_capture` +檢查會回報目前使用哪一層。 + +原生 Wayland 指標座標在原始座標與版面原點換算後仍不屬於任何授權 EIS 區域時, +會以 `state="failed"` 的 `LibeiUnavailable` 拒絕,停止自動 CLI 備援, +不送出移動、frame 或後續點擊。有效座標、未提供區域的裝置、同一 sender 的後續有效請求, +以及明確選擇 CLI 的既有行為維持不變。 + +**輸入/擷取能力**提供 `je_auto_control.api`(亦由套件根目錄匯出)的 +`BackendContext`、`CapabilityStatus`、`CapabilitySnapshot` 與 `probe_capabilities`。 +呼叫 `probe_capabilities(BackendContext.current()).to_dict()`、無參數的 +`AC_probe_capabilities`/唯讀 `ac_probe_capabilities`,或選擇 +**Diagnostics → Actions → 檢視輸入與擷取能力**;Builder 提供相同無參數指令。 +`python -m examples.capabilities` 顯示本機前置條件與確定性的 XWayland 範圍範例,不操作桌面。 + +輸入項描述按鍵/指標事件;既有 wtype 文字路徑獨立。探測只讀環境、PATH 與不等待鎖的既有原生狀態, +不載入選用原生函式庫、不連線、不讀取事件、不擷取或要求授權。找到工具或 bus 位址只代表 +`unverified`,不等於可用。快取 libei 須完成握手,且鍵盤、絕對指標、按鈕與滾輪事件種類都在運作才回報可用; +部分授權維持未驗證,事件種類暫停或必要裝置移除則回報暫停/撤銷。八種狀態為 `available`、`unverified`、`needs_permission`、 +`needs_dependency`、`unsupported`、`paused`、`revoked`、`failed`。 +`available` 僅是最近的本機觀測,可能過時;實際操作仍重驗權限。XWayland 一律 +`desktop_wide=False`,無法涵蓋原生 Wayland 視窗;其他範圍旗標仍受授權區域限制,不代表已驗證每個螢幕。 + +Context 會複製環境/工具資料,可由擁有者提供無原生物件的輸入/擷取觀測,但不授予權限。 +預設本機結果不含環境值、命令參數、執行檔路徑或原生錯誤文字;AC/MCP 不接受外部提供觀測。 +明確選擇 CLI 與觀測到選用原生依賴缺失後的自動備援分開;拒絕、暫停、撤銷與失敗不表示改走 CLI。 +擷取工具/portal 選擇獨立診斷,重繪與切換語系只使用既有快照。原生 portal 恢復、compositor 重啟、 +擷取結果與 context 的接合,以及原生 session 的重試/取消/停止控制仍列於 `Progress.md`。 + +GUI 工作基礎提供 `gui.task_controller.TaskController`: +`submit(work, owner=widget)` 回傳呼叫者持有的 `TaskHandle`,透過 +`TaskOutcome`/`TaskProgress` 傳遞終態與進度。工作取得不依賴 Qt 的 +`CancellationToken`,提供 checkpoint、有界且可被取消喚醒的等待與進度回報。 +提交時捕捉 context,執行前重讀 store 使用者;工作須持有資料、不引用 widget,並驗證自身操作所需的 capability。 +既有 `DeferredAuthorization.scope()` 維持輸入權限要求,`context_scope()` 僅更新與綁定身分。 + +擁有者、handle 或 controller 銷毀時會要求協作式停止並丟棄延遲結果;每項工作有獨立 ID/token, +回呼在 GUI 執行緒執行。不強制中斷不合作的呼叫,也不把已成功提交的結果改標為取消。 +錯誤與進度使用捕捉的秘密遮罩 scope,終態不保留例外 traceback;執行緒啟動失敗會回復兩層登記並保留原失敗。 +Diagnostics 已接入此共用控制器;其餘面板/backend 遷移與原生 session 操作仍列於 `Progress.md`。 + +主動 **Diagnostics → Actions → 執行診斷** 以共用控制器在 GUI 執行緒外執行。 +**停止診斷** 要求協作式停止;四語狀態區分執行中、清理中、已取消與失敗,並顯示已完成檢查數。 +重複執行不另開工作,關閉後丟棄延遲進度/結果,明確重試會建立新的擁有者工作。 +GUI 以不保留例外 traceback 的 typed outcome 呈現取消;核心/SDK/CLI 與 MCP handler +維持原始直接/包裝取消物件。普通檢查錯誤仍列入報告並繼續其餘項目。 + +兩個 SDK namespace 匯出 `CancellationToken`、`TaskProgress`、`cancellation_scope`。 +使用 `with cancellation_scope(token): report = run_diagnostics()`,擁有者可由另一執行緒呼叫 +`token.cancel()`;既有無參數診斷簽章不變。Scope 不授予權限,`cancellation_scope(None)` +只在有時限的自有資源清理期間暫停取消。`AC_diagnose` 與新增的唯讀 `ac_diagnose` 共用報告; +MCP 不接受參數,使用請求取消/進度,與明確 GUI 操作同樣需要 `read_screen`,拒絕外部 token/授權資料。 +這些是主動檢查,擷取可能要求同意;`ac_probe_capabilities` 維持獨立的被動選項。 + +Scoped Wayland D-Bus 的連線/讀取/部分寫入,以至多 0.1 秒的區間輪詢,維持原本總時限。 +取消時在原 bus 以獨立 0.25 秒預算嘗試 Request.Close,再釋放連線;取消的已回傳圖片會刪除。 +Scoped CLI 擷取會停止並回收自己建立的 helper/process group,清理有時限,pipe close 失敗也不蓋掉原取消, +已回收的數字 PID 不再作為訊號目標。liboeffis 取得 session 時會觀察停止並釋放自身 context。 +不強制中斷不合作或原生呼叫,清理期間 GUI 仍可操作;restore/重啟、原生 session 控制、 +擷取擁有者 metadata 與其餘面板/backend 遷移保留於 `Progress.md`。 + +`python -m examples.cancellable_diagnostics` 預設只做受控取消示範,不呼叫 provider。 +`--active --cancel-after 2` 才明確執行診斷並在兩秒後要求停止;真機/裝置/API 驗收另外列管。 + +開啟 Diagnostics 只顯示已翻譯的「尚未執行」狀態,不執行檢查。 +選擇 **Actions → 執行診斷** 才會啟動既有主動檢查,可能擷取螢幕或需要 portal 同意; +切換語系不啟動檢查。明確的 `run_diagnostics`、`AC_diagnose` 與 MCP 診斷呼叫維持主動行為; +無副作用的能力檢視使用下方獨立操作。 + +未完成的 screenshot portal 請求會在斷開原始 bus 前嘗試 `Request.Close`, +使用獨立的 0.25 秒 D-Bus I/O 預算。伺服器回傳替代 handle 時會跟隨該 handle; +方法回覆不確定時則使用預測 handle,已完成的 Response 不重複關閉。 +一般清理錯誤不覆蓋主要擷取失敗;原始取消與強制中斷物件會穿過包裝及清理繼續傳播。 +D-Bus 寫入與回覆共用呼叫預算,連線建立有明確時限,connect/驗證/Hello 中斷時, +即使 `__enter__` 失敗也會釋放自己擁有的描述元。實際合成器/對話框取消仍待平台驗收。 + +有一件只在 Wayland 出現、需要事先規劃的事:**擷取回來的圖裡可能有滑鼠游標。** +這裡沒有任何一條擷取要求游標,但只要 backend 沒有游標平面(包含任何以 +`WLR_NO_HARDWARE_CURSORS=1` 執行的 session),wlroots 就會畫**軟體游標**並把它 +合成進輸出緩衝區,而擷取交回來的正是那一份。Windows 與 X11 都不含游標,所以 +「定位器、樣板比對或 OCR 在目標中間看到一個游標形狀的洞」只會在這裡發生。 +Wayland 不讓用戶端讀游標位置,所以沒有東西可以可靠地遮或閃避:請在擷取之前 +把指標移離要拍的區域。`screen_capture` 檢查會以 `cursor_may_be_captured` 回報這件事。 + +如果以上都不適用你的環境,可以直接指定自己的指令——它優先於所有偵測,`{output}` 會被 +換成暫存 PNG 路徑: + +```bash +export JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND="mycapture --png {output}" +``` + +Wayland 禁止非特權用戶端進行全域輸入錄製——若要錄製,請設定 +`JE_AUTOCONTROL_LINUX_DISPLAY_SERVER=x11` 並在 X11 session 下執行。視窗管理支援 +Windows、macOS(pyobjc)與 X11(含 XWayland);純 Wayland session 的協定不讓用戶端看到別的程式的視窗, +所以 `list_windows()` 回傳空清單,其餘視窗操作一律拋出帶原因的 `AutoControlUnsupportedOperationException`。對於會忽略合成輸入的應用程式, +可選用驅動層後端(`JE_AUTOCONTROL_WIN32_BACKEND=interception`、 +`JE_AUTOCONTROL_LINUX_BACKEND=uinput`、ViGEm 虛擬手把);驅動未安裝時會自動退回原本行為。 + +--- + +## 設定 + +AutoControl 讀取的每一個環境變數。這裡沒有任何一項是必填的:完全不設定時,AutoControl 會自行選擇平台後端,伺服器只綁定 `127.0.0.1`,所有需要主動開啟的功能(簽章強制、RBAC、USB 直通、工具路徑限制)都是關閉的。[設定參考](https://autocontrol.readthedocs.io/en/latest/Zh/doc/configuration/configuration_doc.html)([原始檔](../../source/Zh/doc/configuration/configuration_doc.rst))列出完整的可接受值,並把每個變數連到說明該功能的頁面;CI 會拿它以及下面的表格和程式碼比對。 + +### 平台後端 + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_WIN32_BACKEND` | `sendinput` | 設成 `interception` 時鍵盤與滑鼠改走 Interception 驅動程式;找不到驅動或 DLL 時會警告並退回 `SendInput`。 | +| `JE_AUTOCONTROL_LINUX_BACKEND` | `x11` | 設成 `uinput` 時直接寫入核心輸入事件;`/dev/uinput` 無法寫入時會警告並退回 XTest。 | +| `JE_AUTOCONTROL_LINUX_DISPLAY_SERVER` | `auto` | 決定載入哪一個 Linux 後端:`auto` 讀取 `XDG_SESSION_TYPE` 與 `WAYLAND_DISPLAY`;`wayland` 或 `x11` 則強制指定(在 Wayland 工作階段設成 `x11` 只能操作 XWayland 視窗)。 | + +### Windows Interception 驅動程式 + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_INTERCEPTION_DLL` | 未設定:先找 `PATH`,再找套件旁邊 | `interception.dll` 的完整路徑。 | +| `JE_AUTOCONTROL_INTERCEPTION_KEYBOARD` | `1` | 鍵盤事件要送往的 Interception 裝置編號(`1`–`10`)。 | +| `JE_AUTOCONTROL_INTERCEPTION_MOUSE` | `11` | 滑鼠事件要送往的 Interception 裝置編號(`11`–`20`)。 | + +### Wayland + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_WAYLAND_INPUT_BACKEND` | `auto` | 設成 `cli` 時透過 `ydotool` 送出輸入,完全不向桌面 portal 提出要求。這是啟動前就做好的選擇:使用者拒絕授權後,AutoControl 不會自行切換過去。 | +| `JE_AUTOCONTROL_WAYLAND_POINTER_ACCEL` | `warn` | 只影響 `ydotool` 路徑的絕對移動(那其實是會被合成器加速的相對位移):`warn` 警告一次後照樣移動,`flat` 表示加速已關閉、不再警告,`strict` 直接拒絕移動。 | +| `JE_AUTOCONTROL_WAYLAND_CAPTURE_COMMAND` | 未設定 | 自訂的截圖指令列,以 `{output}` 表示 PNG 的輸出路徑。優先於 `grim`、`gnome-screenshot`、`spectacle` 與 portal。 | +| `JE_AUTOCONTROL_WAYLAND_RECORD_DEVICES` | 未設定:一個都不讀 | `PhysicalRecorder` 可以讀取的 `/dev/input/event*` 裝置(以逗號分隔);實體輸入錄製必須逐一指定裝置才會啟用。 | + +### MCP 伺服器 + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_MCP_READONLY` | 未設定 | 設成 `1` 時只提供、也只能呼叫標示為唯讀的工具。 | +| `JE_AUTOCONTROL_MCP_TOOL_PROFILE` | 未設定 | `static` 模式的工具清單:以逗號分隔的工具名稱與 `category:<名稱>`。 | +| `JE_AUTOCONTROL_MCP_ALIASES` | `1` | 設成 `0` 時不註冊 `ac_*` 工具之外的簡短別名(`click`、`screenshot` …)。 | +| `JE_AUTOCONTROL_MCP_TOKEN` | 未設定 | HTTP 傳輸的 Bearer 權杖。啟用 RBAC 之後不再接受。 | +| `JE_AUTOCONTROL_MCP_ALLOWED_ORIGINS` | 未設定:只接受本機來源 | HTTP 傳輸額外接受的瀏覽器來源(以逗號分隔,須完全相符,例如 `https://example.test:8443`)。 | +| `JE_AUTOCONTROL_MCP_CONFIRM_DESTRUCTIVE` | 未設定 | 設成 `1` 時具破壞性的工具在執行前先向用戶端要求確認(MCP elicitation)。 | +| `JE_AUTOCONTROL_MCP_PATH_ROOTS` | 未設定:不限制 | 工具的每一個檔案參數都必須落在這些目錄內(以作業系統的路徑分隔字元分隔)。 | +| `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` | 未設定 | 設成 `1` 時同時接受 MCP 用戶端透過 `roots/list` 回報的根目錄。 | +| `JE_AUTOCONTROL_MCP_ENV_REF_ALLOW` | 未設定:不限制 | `ac_resolve_ref` 可以讀取的環境變數名稱(以逗號分隔,可用 `fnmatch` 樣式);設了卻沒有指名任何變數時,一個都不允許。 | +| `JE_AUTOCONTROL_MCP_AUDIT` | 未設定 | JSON-lines 檔案的路徑,每一次 `tools/call` 寫入一筆記錄。 | +| `JE_AUTOCONTROL_MCP_ERROR_SHOTS` | 未設定 | 工具每次失敗時存放截圖的目錄。 | +| `JE_AUTOCONTROL_FAKE_BACKEND` | 未設定 | 設成 `1` 時 MCP 伺服器只在記憶體中記錄滑鼠、鍵盤與剪貼簿呼叫而不實際執行,供沒有顯示器的 CI 使用。 | + +### REST/RBAC 與 chat-ops + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_RBAC_USERS` | 未設定:沿用共用權杖 | 使用者檔案的路徑。設定它就等於為 REST API 與 MCP HTTP 傳輸啟用角色。 | +| `JE_AUTOCONTROL_CHATOPS_SCRIPT_ROOT` | 未設定:`run` 會被拒絕 | chat-ops 的 `run` 指令唯一可以載入動作檔的目錄。 | + +### 執行與簽署動作檔 + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_ALLOWED_PACKAGES` | 未設定:一個都不允許 | `AC_add_package_to_executor` 可以載入的套件(以逗號分隔,含子模組),對所有進入點生效。只在行程啟動時讀取一次。 | +| `JE_AUTOCONTROL_REQUIRE_SIGNED_ACTIONS` | 未設定 | 設成 `1` 時所有會執行動作檔的路徑,都拒絕沒有有效簽章檔的動作檔。 | +| `JE_AUTOCONTROL_ACTION_SIGNING_PRIVATE_KEY` | 未設定 | Ed25519 私鑰(PEM)的路徑。只在負責簽署的機器上設定;設定後簽署會寫出第 2 版的簽章檔。 | +| `JE_AUTOCONTROL_ACTION_SIGNING_PUBLIC_KEY` | 未設定 | 對應公鑰的路徑。在每一台執行端設定:它只能驗證,不能簽署。 | +| `JE_AUTOCONTROL_ACTION_SIGNING_PASSPHRASE` | 未設定 | 私鑰建立時若有設定通行碼,在這裡提供。 | +| `JE_AUTOCONTROL_ACCEPT_LEGACY_ACTION_SIGNATURES` | 未設定 | 設成 `1` 是遷移模式:設定公鑰之後,第 2 版之前寫出的 HMAC 簽章檔會被拒絕,除非設定了這個變數。所有檔案重新簽署後請再關掉。 | + +### 遠端桌面與信令 + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_REMOTE_DOWNLOAD_DIR` | `~/Downloads/AutoControl` | 遠端桌面檢視端存放主機傳來檔案的目錄。收到的路徑一律限制在這個目錄內。 | +| `JE_AUTOCONTROL_USB_PASSTHROUGH` | 未設定 | 設成 `1` 時在遠端桌面通道上啟用 USB 直通指令。 | +| `AC_SIGNALING_SECRET` | 未設定 | 信令/設定同步伺服器的共用密鑰(`X-Signaling-Secret`)。伺服器在沒有 `--shared-secret` 時讀取它。 | + +### GUI + +| 變數 | 預設 | 作用 | +|---|---|---| + +### 記錄檔、資料與測試 + +| 變數 | 預設 | 作用 | +|---|---|---| +| `JE_AUTOCONTROL_LOG_FILE` | `~/.je_auto_control/logs/AutoControlGUI.log` | 記錄檔寫入的位置。指定空裝置(`/dev/null`、`NUL`)即可關閉檔案輸出。在寫入第一筆記錄時才讀取,而不是在 import 時。 | +| `JE_AUTOCONTROL_ENV` | `default` | 資產庫目前使用的環境(`active_environment()`),讓同一份腳本在 `dev` 與 `prod` 讀到不同的值。 | +| `JE_AUTOCONTROL_REDACTION` | `off` | 截圖遮蔽的預設政策:`off`、`moderate` 或 `strict`。未知的名稱會報錯,不會被當成 `off`。 | +| `JE_AUTOCONTROL_PYTEST_ARTIFACTS` | `./autocontrol_screenshots` | 測試沒有使用 `autocontrol_screenshot_dir` fixture 時,pytest 外掛寫入失敗截圖的目錄。 | + +--- diff --git a/docs/guides/zh-TW/usage.md b/docs/guides/zh-TW/usage.md new file mode 100644 index 000000000..9ceb1df77 --- /dev/null +++ b/docs/guides/zh-TW/usage.md @@ -0,0 +1,203 @@ +# Automation usage + +[README](../../../README/README_zh-TW.md) · [Documentation](../../README.md) + +## 為什麼選擇 AutoControl + +- **一套 API,七個平台。** `wrapper/platform_wrapper.py` 在匯入時挑選後端;同一份腳本在 + Windows、macOS、X11 與 Wayland 上都不需要改寫。 +- **不寫 Python 也能腳本化。** 911 個 `AC_*` 指令涵蓋全部功能,因此一個 JSON 檔能做到函式庫 + 能做的任何事——包含迴圈、分支、try/catch、巨集與變數。 +- **預設無頭執行。** `import je_auto_control` 絕不會載入 Qt。GUI 是選用套件,包在同一個無頭核心之外。 + 公開匯出項目在被存取時才載入來源模組。`__all__` 與 `dir()` 可列出名稱,不必載入全部功能; + 萬用字元匯入會要求所有名稱。尚未解析的名稱不會出現在 `vars(je_auto_control)`。 + X11 的一般套件匯入不開啟顯示連線或輸入裝置,也不啟動鍵盤監聽。 + 桌面操作在呼叫時才取得資源。讀取 `keyboard_keys_table` 或呼叫 + `get_keyboard_keys_table()` 會解析實際伺服器鍵碼,因此需要 X 連線。 +- **四種定位方式。** 樣板比對、OCR、無障礙樹、視覺語言模型——可透過錨點定位器與自癒後備串接組合。 +- **相依基線輕薄。** REST 伺服器、JSON Schema 驗證、JWT、TOTP、WebSocket 框架、ACME 用戶端、 + USB/IP 協定與 Prometheus 指標全部以標準庫實作;較重的相依都是選用。 + + +## 如何選擇自動化層 + +AutoControl 不需要取代所有自動化工具;應該選擇最符合介面的那一層: + +| 需求 | 適合工具 | +|---|---| +| 穩定的瀏覽器 DOM/API 自動化 | Playwright/Selenium | +| 簡單的 Python 滑鼠鍵盤腳本 | PyAutoGUI 或 AutoControl | +| 原生桌面應用程式自動化 | **AutoControl** | +| 無障礙樹 GUI 自動化 | **AutoControl** | +| OCR GUI 自動化 | **AutoControl** | +| 截圖/視覺模型 GUI 定位 | **AutoControl** | +| Self-healing 跨平台 GUI locator | **AutoControl** | +| AI agent 操作真實桌面 | **AutoControl + MCP** | +| 確定性的 JSON GUI workflow | **AutoControl** | + +AutoControl 的差異在於把 **真實電腦輸入 + 語意/視覺定位 + self-healing + agent/MCP 整合** 放在同一個跨平台自動化介面。 + + +## 60 秒上手 + +**1. 當成 Python 函式庫** + +```python +import je_auto_control as ac + +ac.set_mouse_position(500, 300) +ac.click_mouse("mouse_left") +ac.write("Hello World") +ac.hotkey(["ctrl_l", "s"]) + +x, y = ac.locate_image_center("save_button.png", detect_threshold=0.9) +ac.click_text("Submit") # OCR +ac.click_accessibility_element(name="OK") # 無障礙樹 +ac.click_by_description("the green Submit button") # 視覺模型 +ac.screenshot("shot.png", screen_region=[0, 0, 800, 600]) +``` + +**2. 當成 JSON 動作檔** — `flow.json` + +```json +[ + ["AC_set_var", {"name": "user", "value": "alice"}], + ["AC_locate_and_click", {"image": "login.png", "mouse_keycode": "mouse_left"}], + ["AC_write", {"write_string": "${user}"}], + ["AC_retry", {"max_attempts": 3, "body": [ + ["AC_wait_text", {"target": "Welcome", "timeout": 10}] + ]}], + ["AC_assert_text", {"text": "Welcome"}], + ["AC_generate_html_report", {"html_name": "report"}] +] +``` + +```bash +je_auto_control run flow.json --var user=bob +je_auto_control run flow.json --dry-run # 只列出步驟,不會真的動滑鼠 +``` + +**3. 當成桌面應用程式** + +```bash +pip install je_auto_control[gui] +python -c "import je_auto_control; je_auto_control.start_autocontrol_gui()" +``` + +錄製一段流程、在視覺化 Script Builder 裡編輯,然後存成 CLI 能直接執行的同一種 JSON 格式。 +(`python -m je_auto_control` 是舊式的動作檔執行器——`-e`、`-d`、`-c`、`--execute_str`——不會開 GUI。) + +--- + +## 能力總覽 + +每一列都能無頭執行。「GUI 分頁」是同一功能在桌面應用中的位置;分頁的指令都放在視窗的 +**Actions** 選單裡。 + +| 能力 | Python API | `AC_*` 指令 | GUI 分頁 | +|---|---|---|---| +| 滑鼠 | `click_mouse`(`clicks=2` 就是雙擊)、`set_mouse_position`、`mouse_scroll`、`tween_drag`/`drag_path`(以 `step_delay_s`、`settle_s` 控制節奏) | `AC_click_mouse`、`AC_tween_drag`、`AC_drag_path` | Auto Click | +| 鍵盤 | `write`、`write_secret`、`hotkey`、`type_keyboard`、`keyboard_key_name`(鍵碼 → 標準鍵名;Windows 也收 `ctrl`、`esc`、`enter` 等別名) | `AC_write`、`AC_write_secret`、`AC_hotkey` | Auto Click | +| 螢幕與像素 | `screenshot`、`screen_size`、`get_pixel` | `AC_screenshot` | Screenshot | +| 影像比對 | `locate_image_center`、`locate_and_click` | `AC_locate_and_click` | Image Detect | +| OCR 文字 | `click_text`、`wait_for_text`、`read_text_in_region`、`ocr_status` | `AC_click_text`、`AC_wait_text`、`AC_ocr_status` | OCR Reader | +| 無障礙樹 | `find_accessibility_element`、`click_accessibility_element` | `AC_a11y_find`、`AC_a11y_click` | Accessibility | +| 視覺模型定位 | `locate_by_description`、`click_by_description` | `AC_vlm_locate`、`AC_vlm_click` | VLM | +| 錨點定位 | — | `AC_anchor_click`、`AC_anchor_locate` | — | +| 自癒定位器 | `self_heal_run`、`self_heal_locate`、`self_heal_click` | `AC_self_heal_click` | Self-Healing | +| 自然語言規劃 | `plan_actions`、`run_from_description` | `AC_llm_plan` | LLM Planner | +| Computer-use agent | `AgentLoop`、`run_agent` | `AC_run_agent` | Computer Use | +| 錄製與重播 | `record`、`stop_record` | `AC_record`、`AC_stop_record` | Record | +| JSON 腳本 | `execute_action`、`execute_files` | 全部 911 個指令 | Script、Script Builder | +| 變數與流程控制 | `execute_action_with_vars` | `AC_set_var`、`AC_loop`、`AC_for_each`、`AC_try`、`AC_retry` | Variables | +| 資料驅動執行 | — | `AC_for_each_row`(CSV/JSON/SQLite/Excel) | Data Sources | +| 斷言 | `assert_text`、`assert_image` | `AC_assert_text` 等 21 個 | Assertions | +| 測試套件 | `run_suite` | `AC_run_suite` | Test Suites | +| 排程(間隔 + cron) | `default_scheduler` | — | Scheduler | +| 全域熱鍵 | `default_hotkey_daemon` | — | Hotkeys | +| 事件觸發 | `default_trigger_engine` | `AC_email_trigger_add` | Triggers、Webhooks、Email | +| 視窗管理 *(Windows、macOS、X11)* | `list_windows`、`focus_window` | `AC_focus_window`、`AC_snap_window` | Window Manager | +| 剪貼簿(文字 + 影像) | `get_clipboard`、`set_clipboard`、`get_clipboard_image`、`set_clipboard_image` | `AC_clipboard_get`、`AC_clipboard_set`、`AC_clipboard_get_image`、`AC_clipboard_set_image` | — | +| 遠端桌面 | `RemoteDesktopHost`、`RemoteDesktopViewer` | `AC_start_remote_host`、`AC_remote_connect` | Remote Desktop | +| USB 列舉與直通 | `list_usb_devices`、`enable_usb_passthrough` | `AC_usb_*`(16 個指令) | USB Devices、USB Share | +| 機密保險庫 | `default_secret_manager` | `AC_secret_set` + `${secrets.NAME}` | Secrets | +| 報表(HTML/JSON/XML) | `generate_html_report` | `AC_generate_html_report` | Report | +| 執行歷史 | `HistoryStore`、`manual_history_scope` | `AC_history_list`、`AC_history_capture` | Run History、Script Executor、Script Builder | +| 動作日誌 | `execute_journal_run`、`inspect_journal` | `AC_journal_capture`、`AC_journal_read` | Run History、Script Builder | +| 指標與追蹤 | `default_metric_registry`、`render_metrics_text` | — | — | +| 系統診斷 | `run_diagnostics` | `AC_diagnose` | Diagnostics | +| 測試碼產生 | `generate_code` | — | — | + +自癒定位器會在後備或點擊前原樣傳遞取消。稽核記錄在寫入或回傳記錄前遮蔽本次執行已解析的秘密值;回傳的定位結果保留原值,讀取時不改寫既有紀錄檔。 + +即時 image/VLM 自癒現在共用一次延遲邏輯截圖及實際裁切原點,兩條路徑的 `screen_region` 均為 `[左, 上, 右, 下]`。Schema-v2 記錄增加 run/step 身份、內容與設定版本、frame hash、策略/截圖耗時及實際 backend/model,仍相容舊記錄。未設定驗證的點擊僅記錄已送出或失敗,驗證維持未知。GUI 提供區域輸入與所選記錄證據,Script Builder 保留結構化區域 JSON。舊 `healed`/`heal_rate` 統計定位候選,獨立的操作指標需要明確驗證。 + +實驗性 `self_heal_run(SelfHealRequest(...))` 預設只定位。明確選擇 `operation="click"`,再透過 `VerificationRequest(verifier=...)`(Python bool callback)或 `VerificationRequest(description=...)`(已設定的 VLM)於輸入送出後驗證條件。VLM 驗證使用新擷取的邏輯影像,可能產生 API 費用。`verified` 分為真、假及未知;`found` 與 `issued` 本身不代表操作通過驗證。例外與取消原樣傳遞,不重試點擊。`AC_self_heal_run` 和 MCP `ac_self_heal_run` 接受巢狀 `request`;明確驗證失敗使指令/CLI 失敗,或回傳含結構化結果的 MCP `isError`。GUI **Self-Healing** 提供選填的操作後條件,Script Builder 可編輯 JSON 請求。獨立 VLM 擷取也改用相同的記憶體邏輯原點/Retina 正規化。Framework assertion 會中止定位後備。 + +已擷取的自癒紀錄新增可選的 `journal_path`,搭配 run/step ID。實驗性 `inspect_heal_source(path, run_id, step_id)`、`AC_self_heal_source` 與 MCP `ac_self_heal_source` 只讀取原始步驟經清理的生命週期快照。在 **Self-Healing** 選取紀錄後,使用 **動作 → 檢視原始步驟** 開啟背景讀取器;切換目標時會等待舊讀取停止並保留請求者脈絡,關閉則取消待處理工作;Run History 讀取器也可選填步驟 ID。先篩選 run/step 再套用輸出上限,整份日誌仍會驗證,進度通知前後重查路徑根目錄,取消不回傳部分結果。舊紀錄或未經動作日誌擷取的操作沒有來源連結;查閱不會重播指令。 + +實驗性因果同步提供 `CausalBucket`、`CausalConfigStore`、`SyncActor`、保留衝突的 entry 版本與持久化本機 `SyncOutbox`。獨立且經驗證的 `GET/PUT /config/{user_id}/causal` 第三版協定,在保存重送收據的同一個 CAS 交易內驗證裝置註冊、確認、退休/完整同步 epoch 與刪除回收。回收後保留永久的最小刪除憑證;舊版寫入不能覆蓋已升級帳號。私有 `AC_config_store_get`/`AC_config_store_commit` 與對應 MCP/Builder 命令可讀取及提交帶明確 `_actor` 的因果 JSON;純資料合併/peer 與私有 outbox 命令仍可使用。明確的 `CausalSyncClient` 與 `AC_config_causal_fetch`、`AC_config_causal_commit`、`AC_sync_outbox_flush`(含 MCP/Builder)已提供第三版 HTTP 投遞:結果不明時重送固定請求,只有明確的過期版本才在有界預算內重合併。`CausalReceipt` 在 outbox 原子確認原收據與最新完整快照;命令憑證使用即時的 `options.secret_env` 參照。`CausalSyncClient.control` 與私有 `AC_sync_peer_control`/`ac_sync_peer_control`/Builder Data 命令可持久化註冊、確認、回收、退休與完整重同步。`SyncControlRequest(operation_id=...)` 讓已完成 RPC 的重試保持冪等;完整重同步須明確提供 `discard_pending=True`,收到收據後才原子採用新世代並封存待送舊編輯。本機 `status` 不讀取憑證或網路。`python -m examples.causal_peer_control` 提供暫存 loopback 工作流;明確的本機資產版本可透過 `AssetManifest`、`DirectoryAssetTransport`、`build_asset_manifest`、`sync_assets` 與私有 `AC_sync_asset_manifest`/`AC_sync_assets`(MCP/Builder)操作。全部資產先暫存並通過 SHA-256/大小驗證,再一次發布完整目錄;受損快取拒絕使用,腳本保持未執行。`python -m examples.sync_assets` 只使用暫存目錄。七種實驗性 adapter 已將明確選定的腳本、locator、熱鍵、觸發器、通訊錄、JSON 設定與已保存的原生 GUI 偏好設定保存為持久化因果 profile。`SyncBindings` 將明確指定的秘密與機器值換成具名參照;`materialize_sync_profile` 發布完整且未啟用的原生格式版本。私有 `AC_sync_adapter_snapshot`、`AC_sync_adapter_apply`、`AC_sync_adapter_resolve`、`AC_sync_profile_materialize` 與對應 MCP/Builder 命令提供相同流程。`python -m examples.sync_adapters` 僅使用暫存檔。私有絕對路徑綁定接受高熵目錄名稱,仍拒絕可辨識的憑證格式。原生數值定義會在儲存前以分類錯誤拒絕超出範圍的值,包含超大 JSON 整數。`WorkspaceSettingsSyncAdapter` 僅讀取原生 GUI INI 的主題、字級、導覽顯示/寬度,並發布未啟用的 `workspace.ini`;明確複製為獨立工作檔後,才能交給新 GUI 使用。`python -m examples.sync_workspace` 不匯入 Qt。`SyncWorkspace` 已整合明確來源、持久離線捕捉、因果 HTTP、精確衝突檢視與完整重同步來源基準。私有 `AC_sync_workspace`/`ac_sync_workspace`/Builder Data 共用 status/capture/sync/review/resolve/preferences/materialize 與明確 peer 控制,全部需要 DRIVE;網路憑證使用 `options.secret_env`。`python -m examples.sync_workspace_http` 以兩組暫存來源與 loopback 示範衝突解決、重啟及退休編輯不重播。接收資料保持未啟用。引用資產傳輸見下方;明確的原生工作副本載入見下方,`ConfigSyncClient` 保留時間戳合併。參閱[因果/outbox 指南](../../source/Zh/doc/causal_sync/causal_sync_doc.rst)與 `python -m examples.causal_sync`。 + +延遲建立的 **工作區同步** 分頁透過 **Actions** 提供本機狀態/擷取、網路同步與裝置控制、精確因果檢視/解決衝突,以及完整未啟用發布。貼上明確的私人工作區設定,憑證只填環境變數名稱。同步不會自動套用收到的偏好設定。選取 `workspace`、檢視目前版本後,再執行「套用已檢視的 GUI 偏好設定」,才會更新目前視窗的主題、字級及導覽面板。`SyncWorkspace.preferences(observed=change_ids)` 與既有 AC/MCP/Builder 的 `preferences` 操作,僅在已檢視版本完全相符且無衝突時回傳四個標準值;缺少或刪除的值採安全預設。Worker 保留呼叫者 context、重驗 DRIVE 權限,支援取消並在關閉後捨棄舊結果。畫面顯示修訂版、待送/衝突/參照數與最近成功同步版本;開啟分頁不會啟動連線。 + +明確的原生載入使用 `load_sync_profile(directory, target_root, expected_digest=...)` 與 `LoadedSyncProfile`,並提供私有 `AC_sync_profile_load`/`ac_sync_profile_load`/Builder Data。以已發布的 `files` 資料夾及精確檢視的 manifest 摘要建立全新可編輯工作區,先驗證全部 bytes、標準原生檔案及封存 heads 一致,再原子發布。載入的熱鍵及每個觸發器節點都是停用的原生物件;定位器與通訊錄 handle 使用工作副本。型別化資產參照及原生熱鍵/觸發器路徑依工作根目錄解析,腳本字面文字保留原意,秘密維持 placeholder。在「工作區同步」發布後,資料夾/摘要欄位會填入結果;選擇工作副本存放資料夾,再執行「載入已檢視的原生 profile」。其他明確 Actions 可檢查所選原生類別、在 Builder 開啟已載入腳本快照,或套用其偏好快照。每次操作都重驗目前呼叫者與擷取擁有者的權限;開啟腳本後仍須明確執行 Run;Builder 將匯入的命令名稱與位置參數顯示為字面文字。`python -m examples.sync_profile_load` 使用七種暫存來源與真實 PNG,不呼叫網路或裝置。 + +資料夾鏡像改以 SHA-256 內容比對,不再依賴修改時間遞增:只改時間不重送,時間相同或較舊的內容修改仍會送出。FolderSyncEngine 重啟時保留待送與離線修改,逐檔檢查停止要求,並持續擁有尚未結束的傳送工作。傳輸擁有者可在發布檔案後明確呼叫 record_received(path),避免回送收到的內容。原生 GUI 的固定內容收據處理見下文。 + +檔案傳送現在會等待每個 DataChannel callback,將緩衝資料限制在 1 MiB,並將通道失敗回報給呼叫端。可選的 `cancelled` 判斷會停止排隊寫入;宣告的位元組數可偵測來源截短或增長。原生資料夾工作綁定授權、引擎、viewer 與 peer connection,擁有權變更時停止。收件匣下載移至事件迴圈之外,透過每個通道最多 32 筆請求的佇列依序傳送。預設手動模式接受資料不代表遠端發布完成;確認模式見下文。GUI 重連交接見下文。 + +原生檔案接收器現在會在關閉、檔案/控制通道關閉、連線進入終止狀態、更換通道或撤銷檔案權限時清除未完成內容。已關閉的接收器拒絕延遲資料;具體 peer/通道與授權檢查會保護替換後的傳輸,也會拒絕 viewer 在驗證前接收檔案。狀態清理先於使用者 callback,避免舊失敗影響 callback 建立的新連線。檔案/稽核/狀態 callback 保留原始取消及強制中斷物件。清理會嘗試關檔及刪除暫存檔,檔案系統失敗寫入日誌。既有 Remote Desktop 控制自動使用此生命週期;已完成的目標與原有線上格式仍可使用。 + +本機 `FileReceiveReceipt(path, sha256, size)` 現在會在原子發布後固定原始接收內容。`FileTransferReceiver.handle_message(on_receipt=...)` 與原生 host/viewer 的 `set_file_receipt_callback()` 提供收據,不必重讀已發布檔案。`FolderSyncEngine.record_receipt()` 避免回送並保留後續本機修改;既有 `record_received(path)` 則明確快照當前內容。GUI 資料夾開關綁定接收收據的引擎及 viewer,並在存取監看目錄前重新驗證原始授權。相對收件匣/監看路徑綁定建立時的工作目錄,既有路徑通知使用絕對路徑。這些本機收據供下文的原生確認模式使用;GUI 重連交接見下文。 + +原生 `FileTransferSender.send`、viewer 的 `send_file` 與 host 的 `push_file` 現在接受僅限關鍵字的 `require_commit=True`。確認模式會先探測已驗證的原生對端,再讀來源中繼資料/內容;以第二版 begin/end 中繼資料傳送,並在原子發布後核對傳輸 ID、不可預測的結束 nonce、SHA-256 及位元組數。相對來源路徑會在交換前固定。每個檔案都重新確認支援與權限,等待有時限;取消、通道/事件迴圈替換或撤銷權限都保留失敗狀態。GUI 資料夾傳送一律要求此模式,因此只接受但遺失的資料不會推進投遞狀態;不確定的傳送會由同一引擎重試。手動傳送仍預設使用原有線上格式。GUI 資料夾投遞要求兩端都支援確認傳輸;不支援時會在送出檔案內容前失敗。GUI 明確重連/恢復見下文。 + +GUI 重連時會為每個面板保留一份記憶體內的資料夾基準。重新連線後再按開始同步:相同的已驗證 host 指紋、絕對監控路徑與本機使用者,會透過新授權的 sender 接續失敗/離線修改。缺少或更換 host 指紋、路徑或使用者時建立新基準;舊工作仍在執行時拒絕交接,待它退出後才能重試。明確關閉資料夾同步會重設基準;停止/重連 viewer 則保留,關閉應用程式後清除。指紋沿用既有已驗證 host 中繼資料的信任模型,沒有新增密碼學身份保證。SDK 可先停止 FolderSyncEngine,待工作確實退出後匯出 checkpoint(),將不可變的 FolderSyncCheckpoint 傳給路徑/遞迴設定相同且 sender 已明確授權的新引擎。基準包含初始略過檔案與收到的內容,並非遠端確認清單。 + +TCP/WebSocket 剪貼簿傳輸沿用明確的 SDK 呼叫與 GUI 推送剪貼簿按鈕。收到的文字/圖片不會自動傳回或廣播;使用者仍可明確重複傳送相同內容。Viewer/host 在讀到緩衝訊息後,會重新檢查原始連線、驗證及完整控制權限,再套用剪貼簿資料。Viewer 會在編碼前固定原通道,拒絕改送至替換後的連線。GUI 排隊中的傳輸保留具體 viewer 與連線發起使用者,寫入本機剪貼簿、明確讀取及送出前都會重新檢查權限與擁有權。過期或撤銷的工作會被略過或回報權限錯誤;一般 provider/callback 錯誤仍受控,原始取消與強制中斷物件繼續傳播。文字/圖片 JSON 格式及既有 API 不變。Callback 註冊只以弱引用綁定一次原始 viewer,避免斷線 viewer 自己保留自己及 Qt 面板直到循環垃圾回收;實際排隊資料仍保留原始 peer 與權限,直到處理或丟棄。受控本機協定、loopback 與 offscreen 測試替換原生剪貼簿 provider;真機與付費 API 驗收仍暫緩。 + +實驗性引用資產使用 `SyncAssetBlob`、`SyncAssetReference`、`SyncAssetStore` 與 `SyncAssetHTTPClient`。明確的 `SyncBindings.assets` 別名將選定檔案封存為不可變 SHA-256 參照;只改資產也會建立新的因果版本。`SyncWorkspace` 在準備新定義請求前上傳已驗證分塊,支援中斷續傳,並在完整且未啟用的發布前下載引用內容。既有私有 AC/MCP/Builder 工作區/profile 命令共用這些欄位。`asset_cache_path` 選取 client cache;signaling 的 `--asset-store`/`AUTOCONTROL_SYNC_ASSET_STORE` 選取獨立 server 資料庫。具驗證的第一版資產路由使用 256-KiB 分塊、每檔 64 MiB 上限,每帳號預設限制 256 MiB、8,192 塊與 4,096 筆 blob 收據。超過配額會明確失敗;不可變歷史不自動回收。原生輸出路徑相對於 generation 根目錄。`python -m examples.sync_referenced_assets` 經暫存 loopback HTTP 傳送真實 PNG 與腳本,不執行腳本或改目前工作區。 + +實驗性持久化設定使用 `ConfigStore.commit(..., base_revision=..., operation_id=...)` 與第二版 signaling PUT envelope。SQLite 交易讓 bucket 與重送收據在重啟後保留;過期版本或 ID 改配其他內容會衝突。`ConfigSyncClient` 預設條件寫入;舊版盲寫須在 client/server 明確開啟。`--config-store` 選取延後開啟的資料庫。私有 `AC_config_store_get`/`AC_config_store_commit` 與對應 MCP 工具共用 Script Builder 的明確 Data 命令。只儲存資料,不執行腳本或啟用觸發器;因果合併與離線 outbox 另行交付。參閱[持久化設定指南](../../source/Zh/doc/config_store/config_store_doc.rst)與 `python -m examples.config_store`。 + +實驗性日誌產碼候選支援 `generate_candidate_from_log(path, run_id=...)`、`AC_generate_candidate_from_log` 與 MCP `ac_generate_candidate_from_log`。它會整合開始/完成快照,保留已記錄的控制來源與重試證據,並將不完整重建標示為已觀察路徑。失敗/未完成呼叫、未知命令及遮罩輸入均列為排除項目,不捏造平行順序。Python/pytest/Robot 產物經靜態、命令及不發送輸入的乾跑檢查。`codegen --from-log run.jsonl --run-id selected` 輸出 JSON 審閱包;`-o review.zip` 或 `write_candidate_archive` 可將程式、動作與來源資訊一起原子匯出。Recording Editor 與 Script Builder 的 **動作 → 審閱日誌候選腳本** 提供程式/差異/來源/警告;Builder 匯入為獨立操作,拒絕覆蓋審閱期間的編輯變更。產生與匯入均不執行候選。參閱[候選指南](../../source/Zh/doc/journal_candidates/journal_candidates_doc.rst)與 `python -m examples.journal_candidates`。 + +實驗性候選樣板版本提供 `create_template_candidate`、`preview_template_candidate`、`verify_template_candidate`、`accept_template_candidate`、`revert_template_candidate`,以及對應 `AC_template_candidate_*`/`ac_template_candidate_*` 操作。新的不可變 JSON 版本包保存原始位元組及依目標 PNG/JPEG/BMP 格式編碼的候選;預覽回傳有界縮圖。驗證在本機資料集比較兩個固定版本;接受須有已標註命中、期望 miss、全部已標註案例正確,並提供已預覽版本的 SHA-256。接受時重驗資料集,只原子替換仍符合的原始內容;回復精確還原原始位元組,拒絕覆蓋後續修改。未知樣本與原生操作結果分開呈現。驗證使用記錄的門檻;啟用影像不修改腳本門檻。**Self-Healing → 候選樣板** 提供五個動作、背景工作、取消與 JSON 證據。執行 `python -m examples.template_candidates` 可跑只使用暫存檔的範例。 + +實驗性固定影像比較支援 `evaluate_locators`、`evaluate_healing_manifest`、`AC_self_heal_evaluate`、MCP `ac_self_heal_evaluate` 與 **Self-Healing → 版本比較**。報告分別呈現已標註正確率、誤判、未知與已驗證恢復,包含 p50/p95 及來源,可由 `write_healing_report` 或 GUI 動作匯出 JSON/HTML。本機資料集入口不會截圖、點擊或自行選擇網路 backend。參閱[資料集、統計母體與限制](../../../benchmarks/self_healing/README.md)。 + +除了這張表,`utils/` 底下還有 311 個無頭套件,涵蓋斷言、韌性、資料品質、i18n 稽核、遮蔽、 +治理、可觀測性等等。完整的逐模組地圖在 **[architecture_explore.md](../../../architecture_explore.md)**。 + +--- + +實驗性的結構化日誌已從 `je_auto_control` 匯出(也可透過 `utils.action_journal` 使用):`journal_scope` 記錄現有 executor 呼叫,`execute_action_with_journal` 隔離一次執行。本機 loop/parallel/DAG 步驟保留 parent ID,並區分失敗、取消與 dry-run。既有 history 擁有者會自動連結明確擷取,包含本機 parallel/DAG worker 開啟的 journal;`HistoryStore.journals_for_run` 可查詢非擁有式連結,清理 history 不會刪除日誌檔。CLI 支援 `run script.json --journal run.jsonl [--journal-run-id ID]` 與 `journal run.jsonl [--run-id ID] [--limit 100]`。查閱會按附加順序顯示遮罩後的生命週期快照,預設最多 100 筆,上限 10,000 筆。`AC_journal_capture` 接受具名參數,在擁有者 executor 上執行巢狀 `body`,保留原變數範圍;`AC_journal_read` 與 CLI、公開的 `inspect_journal` 共用遮罩後的有界查閱。兩個指令皆可在 Script Builder 編輯。擷取會在 history 連結、開檔及動作執行前拒絕含有當次執行已知秘密的識別碼或目的地。MCP 的 `ac_journal_capture` 與 `ac_journal_read` 提供結構化結果、進度與合作式取消。擷取的日誌根目錄限制與 observer 會保留至巢狀擷取及本機 workers;查閱可在逐筆驗證時取消。Python 可透過 `JournalRunOptions` 與 `execute_journal_run` 使用相同控制。 + +手動執行可透過 `manual_history_scope`、`AC_history_capture`、CLI 的 `run --history [--history-db PATH]`,或 Script Executor/Script Builder 的 **記錄至執行歷史** 選用紀錄。GUI 的選填日誌路徑也能獨立使用;GUI/CLI 保留原本的結果 JSON 與變數範圍,指令則回傳 `history_id`、`record`、`failed_actions`。既有與巢狀擷取都會連結到新的手動歷史列。CLI 預覽以 `cli.preview` 標示,一般執行使用 `cli.run`。 + +Run History 提供唯讀日誌檢視。使用 **操作 → 使用所選執行的日誌** 選擇來源連結,或用 **選擇日誌** 指定外部檔案;設定執行 ID 與快照上限後,使用 **讀取日誌**。起始/完成快照保持分離,選取後會顯示完整的遮罩資料。**取消讀取日誌** 與關閉檢視會在逐筆邊界提出取消要求;檔案解析在背景 worker 執行,單純選取連結不會開檔。 + +`${secrets.NAME}` 解析後的值會在 executor 執行期間的應用程式診斷中遮罩,包含巢狀動作及本機 parallel/DAG。CLI/REST/MCP 請求與排程、trigger、hotkey、email 執行會將遮罩保留到錯誤處理及 audit/history 寫入完成;報表紀錄保存遮罩後的快照。DAG 會將擁有者的遮罩保留到 node 診斷完成,包含獨立呼叫與自訂 local runner。watchdog、observer 與 callback executor 會將遮罩保留到最後的錯誤處理;獨立規則彼此隔離。CLI stderr 會遮罩,API 結果、拋出的例外與 CLI 結果資料保留原始值。遮罩於擁有者的請求或執行結束時清除。中止的 history 記為 `error`,journal 步驟維持 `cancelled`,不再擷取錯誤截圖。取消會穿過非嚴格執行、復原/重試、回呼與本機 worker;history 結算失敗也不會取代原始硬中止訊號。 + +## 命令列介面 + +每次 `je_auto_control run`(包括 `--dry-run` 與未帶 `--var`)使用獨立變數範圍。頂層 `run_from_description` 與 `StateMachine.run()` 也會隔離變數,同一次執行內的動作與狀態仍可共享;巢狀呼叫沿用已有的執行範圍。自行建立的 `Executor()` 保留自己的變數。 + +```bash +je_auto_control run script.json [--var name=value] [--dry-run] [--allow-package NAME] +je_auto_control validate script.json # 別名:lint +je_auto_control fmt script.json [--check] +je_auto_control list-commands [--filter mouse] [--json] +je_auto_control record out.json [--duration 5] +je_auto_control codegen script.json --target pytest -o test_flow.py +je_auto_control failure-bundle failure.zip --error "login timed out" +je_auto_control list-jobs +je_auto_control start-server --port 9938 # TCP socket 伺服器 +je_auto_control start-rest --port 9939 # REST API +je_auto_control version +``` + +`--var name=value` 會盡量以 JSON 解析(`count=10` 會變成整數),否則視為字串。 +`run` 只要有任何動作失敗就以 1 結束(仍會跑完整份腳本),CI 步驟會跟著失敗。舊版 `python -m je_auto_control -e file.json` 進入點仍然可用,它的 `-e`、`-d` 與 `--execute_str` 旗標也同樣在有動作失敗時以 1 結束。由 [TestPioneer](https://github.com/Integration-Automation/TestPioneer) 啟動時(它會設定 `TEST_PIONEER_ARTIFACT_DIR`),以相對名稱要求的 HTML、JSON、XML 報告會寫到該目錄底下。 + +--- From 00213878b007581b5abe9ce7e8159ea11f19f93d Mon Sep 17 00:00:00 2001 From: JeffreyChen Date: Tue, 10 Nov 2026 01:14:17 +0800 Subject: [PATCH 2/3] docs: prioritize physical acceptance in progress tracking --- Progress.md | 563 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 363 insertions(+), 200 deletions(-) diff --git a/Progress.md b/Progress.md index 03b970b83..ff62ad5f3 100644 --- a/Progress.md +++ b/Progress.md @@ -1,5 +1,221 @@ # Progress +## 維護規則:實機驗收固定置頂 + +依使用者 2026-11-10 指示,所有實機驗收待辦固定放在本檔上方,先於一般開發規劃、重構與相依套件待辦。 +後續新增或更新原生桌面、實際瀏覽器、實體裝置、真實應用/API、跨主機與長時間驗收時, +一律加入下方「實機驗收與必要前置工作」區,不得散放到一般開發區或在驗收區之前插入開發規劃。 +混合實作與驗收的段落保留必要前置工作及限制;新增段落應把實作待辦和實機驗收分開,互相連結。 +只有原始需求中的驗收條件與實際證據都完成,才能移除待辦;完成紀錄依既有規則寫入 `docs/updates/`。 +本次只調整文件排序,不解除任何暫緩、不啟動驗收,也不把 CI、mock 或隔離測試視為實機通過。 + +## 實機驗收與必要前置工作 + +以下集中列出未完成的實機驗收,以及與驗收不可分的缺口與前置實作。 +各段原有的 `TODO`/`WIP`/`BLOCKED`/`DECIDE` 狀態與暫緩條件維持有效。 +原生桌面、實際瀏覽器、Android/iOS 真機、WebRunner 原生雙向 bridge 與完整 24 小時驗收仍暫緩; +真機與付費 API 驗收須待使用者明確恢復後執行。文件置頂不代表取得執行或付費授權。 + +## 輸入、視窗與擷取修正:還沒在真的桌面與 Jeffrey_RPA 上驗過 + +`TODO` — 原生桌面與正式批次升級前的行為驗收暫緩。 + +- **正式批次升級前的桌面行為驗收**:需核對 `_gui_control.py` 對下列行為的實際依賴: + `write()` 大寫與 `is_shift` 在 Windows/X11 生效、`"\r\n"` 只按一次 Enter、`mouse_scroll` 預設方向改為 `scroll_up` + (X11/Wayland 上 `mouse_scroll(3)` 由往下變往上)、小數座標四捨五入、`focus_window` 在 Windows 沒拿到前景會丟例外、 + `list_windows` 不再列出 DWM cloak 與零面積視窗、`post_key` 對可列印字元只送 `WM_CHAR`。 +- **混合 DPI 座標與樣板**:需實測各螢幕上的舊版座標、`screen_region`、視窗版面與樣板, + 包含縮放不同的副螢幕、負原點與多螢幕排列;必要時重新錄製,不能以推導代替驗收。 +- **舊版存的視窗版面檔要重存**:`save_window_layout` 改存 `GetWindowRect`,舊檔還原會偏右 7 px、縮小 14×7 px。 +- **真的 Win32 行為沒有實測**:`post_key` 在真的編輯框是否只出現一個字、DWM cloak 過濾掉的是哪些視窗、 + `MoveWindow` 對最大化視窗與另一個 DPI 的螢幕是否能原樣還原,都只用假的 `user32` 驗過。 +- **X11/Wayland**:大寫與 Shift 標點的判斷假設 `keysym_to_keycode` 把大寫字母對到小寫的 keycode,沒有對著 X server 跑過。 + +--- + +## Wayland 生命週期與驗收 + +`TODO` — 下列上游行為與原生桌面互動仍需驗證。 + +### 還沒有答案的 + +- **`eis_device_pause()` 在 libeis 1.3.901 對 sender client 沒有送出任何東西。** + 對兩個 live device 呼叫 pause 再 dispatch,client 端的 ei fd 4 秒內完全沒有可讀資料。 + 所以 `LibeiBackend._on_event` 的 `DEVICE_PAUSED`/`DEVICE_REMOVED` 分支**仍然沒有 + peer 可以驅動**。`eis_verify.py` 把這件事寫成「要嘛有反應,要嘛根本沒被通知」, + 若哪天 libeis 開始送了,client 忽略它就會當場失敗。真的合成器上會不會不一樣,未知。 +- **`ei_device_start_emulating()` 的 sequence number 沒有被送到對面。** + 刻意送 4242 過去,server 讀回來是 0。我們這邊的計數本身符合標頭檔的約定 + (每次呼叫至少 +1),所以不影響正確性,只是從對面驗不到。 +- **同意對話框「長什麼樣子、真人要按多久」。** portal 這一層現在驗到的是對話框 + *產生的東西*:准(Response 0)、拒(Response 1)、以及一直不回答。三種我們都在真的 + bus 上跑過,三種都得在自己的時限內收斂。至於真的 mutter 對話框長什麼樣、真人猶豫 + 三十秒會不會撞到別的東西,那是 mutter 的事,CI 裡沒有人可以去按它。 + +## macOS 的修正:CI 驗到一半,其餘要一台真的 Mac + +`TODO` — 要一台真的 Mac(Retina,最好接第二個螢幕) + +還沒驗的: + +- **應用程式是否把 `click_mouse(clicks=2)` 認成雙擊**:只確認了欄位的值,沒有對真的應用程式送事件。 +- **`grab_logical`**(`utils/monitor_layout/macos_frame.py`,點座標、逐螢幕擷取後拼接)完全沒在 macOS 跑過。三個假設要實機確認: + `screencapture -R` 接受含負值的全域點座標、Pillow 的 `scale_down=True` 給出點尺寸的影像、`CGDisplayBounds` 與 Quartz 滑鼠事件同一個座標空間。 + 每一格要為每個螢幕各開一次 `screencapture`。CI 的 runner 是 1x 單螢幕,測不到 Retina 與副螢幕。 +- **`list_windows` 在真的桌面上的成本與誤列**:沒加 AX 逾時,沒回應的 app 會拖慢列出;同一行程裡與最小化視窗同原點或同標題的螢幕外輔助視窗可能被誤列。 + +--- + +## 行動裝置(Android/iOS):完全沒有在裝置上跑過 + +`BLOCKED` — 需要 Android 模擬器或實機、iPhone 與 WebDriverAgent;這台機器連 `adb` 都沒有 + +U-20261009-18 的每一個裝置面呼叫都只對假的 ADB/uiautomator2/WDA 測過。`uiautomator2` 與 `facebook-wda` 沒有安裝在開發環境裡, +方法名稱與參數是憑記憶寫的,第一次接上真的 SDK 很可能要修: + +- uiautomator2:`send_keys`、`drag`、空 selector 的 `gesture(...)`(捏合)、`clipboard`/`set_clipboard`、對話框按鈕的 resource id。 +- facebook-wda:`app_launch`/`app_terminate`/`app_state`、`alert.*`、`set_clipboard`、`status()`、`orientation` 的值、元素的 `pinch`、`screenshot()` 回傳 PIL 影像。 +- 旋轉方向:螢幕截圖以面板自然方向回來時,`landscape_left` 轉 270°、`landscape_right` 轉 90°,是從文件推的,沒看過。 +- Android:`input draganddrop` 是否存在、`monkey` 啟動輸出、`pidof`/`pm path` 的結束碼、`dumpsys activity activities` 的格式、`pkill -INT screenrecord` 能否收尾 MP4。 + ADBKeyBoard 的送達無法由裝置確認,是從 IME 被選取推定的。 +- 已知限制:iOS 捏合忽略 `x`/`y`/`span`;iOS `app_state` 不會回 `not_installed`;iOS 的安裝/檔案/錄影沒有 adapter(只有 `MobileExtension` 協定與註冊點); + Mobile 分頁的 probe/run 會卡住 GUI 執行緒到裝置回應或逾時。`AC_android_shell` 刻意不做成 MCP 工具,**請維護者確認**。 +- 沒有 `examples/` 的實機腳本以外的 smoke;Xcode/WDA 的建置與簽章只寫成前置條件。 + +--- + +## macos-15 上的 TCC 權限還沒被 gate 驗過 + +`TODO` — 2026-11-01 把所有 macOS 方格從 `macos-14` 改成 `macos-15`(U-20261101-02), +`test/verify/macos_verify.py` 的 `EXPECTED` 沿用 2026-08-19 在 macos-14 上的實測(螢幕錄製與輔助使用兩個 +TCC 權限都給)。`platform-smoke.yml` 的 `macos-capabilities` 只在推送到 `main` 與對 `main` 的 PR 上執行,所以下一個 dev→main +PR 才會確認 macos-15 是否給一樣的權限;若不同,依 `--measure` 重新實測後更新 `EXPECTED` 與 +`docs/CAPABILITY_MATRIX.md`,不要直接放寬 gate。 + +--- + +## GUI:留下的缺口 + +`TODO` — U-20261009-27、-28、-34、-36、-38、-40 之後還開著的 + +- **Windows UIA 後端的執行緒模型完全沒對真的 COM 驗過**:現在每個呼叫執行緒各有一個自動化物件(`accessibility/backends/windows_automation.py`; + 主執行緒 STA、其他執行緒進 MTA),Accessibility 分頁與 A11y Audit 已移出 GUI 執行緒。開發環境沒裝 `comtypes`,CI 也沒有同時有 `comtypes` 與桌面的 job, + 測試全是假 COM 物件。未驗證的假設:MTA 工作執行緒上的 UIA 呼叫可用;焦點事件 callback 不需要 message pump; + `import comtypes` 第一次發生在已經是 MTA 的執行緒上會丟 `OSError`(憑記憶,沒處理)。`AC_wait_for_focus_change` 的原生 `Queue.get` 仍不會被 stop 叫醒。 +- **Script Builder 的一次性值**:一次執行最多保留 200 個(`MAX_ONE_TIME_VALUES`,留前面的);`AC_parallel` 分支裡產生的值不經結果掛鉤回報, + 只能從區塊的結果裡取得(標成 `results[0].…`)。結果裡內嵌的動作清單以「參數」規則遮蔽,那些欄位不提供一次性顯示。 + 對話框從未在真的螢幕上顯示過,真的系統剪貼簿(`QClipboard.clear()`/`text()`)在測試裡是假物件。 + `AC_approval_request` 的 `token`(請求編號)在結果畫面保持可見,但在 log 裡仍被遮蔽。 +- **stop 還叫不醒的**:已經進到後端的單一指令(一次影像搜尋、OCR、HTTP 請求、shell 指令)、單一手勢內的節奏 sleep、`AC_wait_for_focus_change`; + MCP 自己的輪詢(`ac_wait_for_image`/`ac_wait_for_pixel`)不在可停止的執行裡。非腳本的分頁工作在後端無法取消,只是結果被丟掉。 + ChatOps 的 Slack bot:`/run` 現在在工作執行緒上跑,`/stop` 的反應受輪詢間隔限制(預設 5 秒);卡在不可中斷的後端呼叫裡的執行仍停不掉,`stop()` 逾時後回 `False`;在輪詢執行緒上的指令 handler 裡呼叫 `stop()` 也會等到逾時。沒對真的 Slack workspace 跑過。 + 新轉成可停止的等待裡,`AC_handle_file_dialog`、`AC_wait_until_app_idle`、`AC_wait_for_composition_commit`、`AC_wait_for_unlock` 與行動裝置的 `wait_for_app` 只對假探針測過。 +- **WebRTC**:`StatsPoller.start()` 會在 GUI 執行緒上最多等 2 秒(`future.result(timeout=2.0)`,是啟動路徑,沒動)。LAN 廣播的註冊與取消已移出 GUI 執行緒, + 但真的 zeroconf 的時間與名稱衝突行為只對假物件測過。 +- **切換主題後那幾個事件迴圈回合內**,以被暫存的頁面為 parent 的 `QMessageBox` 會相對於隱藏的暫存 widget 定位(只影響位置)。 + 系統匣路徑在 offscreen 下沒有 tray,`_on_tray_open` 是直接呼叫測的。基準(`benchmarks/gui_*.py`)CI 仍不設門檻。 +- **把 Python 建的 widget 放進分頁列在結束時崩潰**:已查明觸發條件——分頁列按鈕上接了 Python callable、又有排隊中的 `deleteLater()`、而行程經 `os._exit` 離開; + 先把 deferred delete 沖掉就不會。機制(Qt 在行程結束時釋放那個 slot)是推論,沒有 C 堆疊可看。`_tab_close_icon.py` 沒有改回自訂按鈕。 +- **對真實 Qt 型別的型別檢查**:`test/verify/typing_extras_exempt.txt` 從 70 個模組降到 18 個(11 個 WebRTC 面板 mixin、`navigation`、`step_form_view`、 + `triggers_tab`,與 4 個對 aiortc/av 型別的 `utils/remote_desktop` 模組),只准變少。`QImage.fromData(x, "JPEG")` 的 5 處保留 `# type: ignore[arg-type]`: + stub 要 bytes,實際的 binding 對 bytes 丟 `ValueError`。 +- 遠端桌面的輸入改成佇列送出後,`AC_remote_send_input` 回的 `{"sent": True}` 意思是「已排入」;`SO_SNDTIMEO` 的 POSIX 包法與經 TLS socket 的行為沒在這台機器上驗過。 +- 沒在 macOS/Linux 上看過新的關閉鈕、捲動與重設樣式;沒在真的多螢幕桌面試過視窗位置還原;PyBreeze 沒有對這一版跑過;各語系新增的字串(日文、簡體中文)沒有母語者看過。 + +--- + +## 這一輪修正留下的後續 + +`TODO` — 下列整合、安全與平台驗證仍未完成。 + +- **Intel Mac 安裝要編譯 `cryptography`**:下限拉到 50 之後 `macosx_10_9_x86_64` 沒有 wheel(探測:最新只到 48.0.1), + `pip install je_auto_control` 在 Intel Mac 需要 Rust 工具鏈。沒有在 Intel Mac 上實際編過。 +- **簽章分離擋不住能寫檔的人**:能執行寫檔指令(shell、檔案類指令)的人仍能換掉公鑰檔本身,保護那個檔是作業系統權限的事; + 私鑰是未加密的 PEM(0600,Windows 上沒驗權限位元),沒有通行碼選項;遷移模式開著時 HMAC 簽章會被接受。 + 強制簽章經 socket/REST/MCP 的端到端沒有跑過,覆蓋的是共用的 `read_executable_action_json` 與指令本身。 +- **RBAC**(`JE_AUTOCONTROL_RBAC_USERS`,預設關閉): + - 使用者只能用 Python 管(`UserStore.add_user/set_role/rotate_token/remove_user`),沒有 `AC_*`、CLI 或 GUI;`Capability.MANAGE_USERS` 因此沒有任何路由或工具對應。 + - viewer 的其餘影像檔案型、mobile 與外掛唯讀工具仍需全面盤點 capability;自製工具仍依提示採預設分類。 + - 沒對真的 client(Claude Desktop、VS Code、內建 dashboard)試過;SSE、無狀態與 `subscriptions/listen` 路徑、TLS 加 RBAC 沒有測試。 +- **MCP 路徑根目錄**(`JE_AUTOCONTROL_MCP_PATH_ROOTS`,預設關閉)管不到的參數:執行動作清單的工具、 + 有時才是路徑的參數(`ac_open_path`/`ac_plan_open`/`ac_file_association`/`ac_act_in_view` 的 `target`,`ac_launch_process`/`ac_shell` 的 `argv`/`command`)、 + `ac_handle_file_dialog` 的 `path`、自由格式物件裡的路徑(`ac_run_suite` 的 `spec`、`ac_run_dag` 的 `definition`、`ac_assert_all` 的 `specs`)、沒標註的外掛工具。 + 檔案 symlink 的跳脫在這台機器上建不出來(只跑了目錄 junction);POSIX 的 `:` 分隔與 `~` 沒在 Linux/macOS 跑。 + `roots/list` 來的根目錄要另外開 `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` 才算數——這是實作時定的,請維護者確認。 +- **USB passthrough**:client 仍在 `reply_timeout_s`(10 秒)放棄,即使呼叫端要的 `timeout_ms` 更長(host 接受到 60 秒); + 對新 host 逾時已經無害,對舊 host 正常使用就會進入「需重連」。通道層的 ERROR(passthrough 關閉、bad frame、host 沒有 session)在 session 之前送出、不帶請求編號, + 呼叫仍是等到逾時。沒對真的舊版 host、真的 WebRTC 通道或真的 USB 裝置跑過。 +- **變數範圍**:free-threaded 原生執行緒繼承與同時存取範圍的行為尚未實測。 +- **遠端桌面的擁有者模型**:Quick Connect 沒有狀態列,它的連線被取代時視窗只是關掉;主機的 Stop 會停任何擁有者開的 host(刻意的); + 只用假的 viewer/host 測過,真的 viewer 被擠掉時會不會觸發 `on_error` 而多跳一個警告框,沒看過。 +- **套件閘門**:`execute_action` 會先驗完所有指令名稱才執行,所以「載入套件」與「用它的指令」寫在同一份清單裡會以 unknown command 失敗,與閘門無關(既有限制)。 + repo 根目錄的舊範例 `AutoControl/keyword/keyword1.json` 載入 `time`,現在預設會被拒絕。 +- **`pytest --cov` 沒有重新量過**:進入點搬到 `je_auto_control_pytest` 之後,它是否還少算,未知;規則仍是 `coverage run -m pytest`。 +- **快到 750 行上限的檔案**:`utils/usb/passthrough/viewer_client.py`(748)、`gui/remote_desktop/connection_screen.py`(729)、 + `utils/mcp_server/server.py`(734)、`utils/mcp_server/http_transport.py`(727)、`utils/agent/backends/anthropic_computer_use.py`(723)——下一次要加東西就得先拆。 + +--- + +## 雜項 + +`TODO` — 小項目,各自獨立 + +- **本機的共用 `.venv` 裝著 `je_auto_control_dev 0.0.136`**,它的 `pytest11` 進入點還是舊的重量級路徑;重裝即可,不影響 CI。 +- **free-threaded**:呼叫者身分、綁定的裝置、自愈的執行標記與 stop token 都改成只在設定它的執行緒上有效(`utils/thread_bound.py`)。 + 這台機器沒有 free-threaded 直譯器:驗證用的是模擬繼承與真的 `-X thread_inherit_context=1`(3.14.7,GIL 開著);`free-threaded-scope` job(3.14t)是第一次真的跑。 +- **能力探測**:Windows 的鎖定工作站、session 0、低完整性與擷取失敗分支只用假資料判斷;macOS 的三個 preflight 呼叫只對假物件跑過, + pyobjc 的 `Quartz` 有沒有 `CGPreflightListenEventAccess` 未知(沒有的話 `recording`/`stop_shortcut` 回 `unknown`)。 +- **Windows 的版面鍵名**(`slash` 等 8 個)只在美式配置上實際呼叫過。 +- **狀態機 `on_enter` 的單一動作寫法**以前一直被拒絕、從沒執行過(已修,U-20261009-24):依賴「它不會跑」的既有狀態機現在會跑它。 + +--- + +## Computer use 的預設還是 beta 的 `computer_20251124` + +`TODO` — 在 `claude-opus-5`(兩種形式都接受)上實測 GA toolset 後,把它設成所有模型的預設 + +驗收入口:`utils/agent/backends/anthropic_computer_use.py` 與 `_computer_toolset.py`。 +需驗證多呼叫回覆、toolset 名稱、截圖尺寸、座標換算與 zoom;未取得真實 API 證據前, +其他模型的預設切換仍待完成。 + +--- + +## Agent 的歷史壓縮還沒對真的 API 跑過 + +`TODO` — 需要付費實機跑一次多步驟任務;離線測試只驗得到請求的形狀 + +需驗證 `utils/agent/backends/anthropic.py`、`anthropic_computer_use.py` 的 beta/GA 路徑, +以及 OpenAI 歷史剪裁在真實 API 上的行為: + +- 重開的歷史在強制 thinking 綁定的帳號(Opus 5.5/Fable 5.1)上是否被接受。 +- 模型只憑摘要能不能接著做——上限是 3,大約每 3 張截圖就壓縮一次,摘要最多列最新 60 個動作、每個截到 240 字元。 +- 真的桌面 PNG 的請求大小離 32 MB 多遠。 +- 兩個後端都沒送 `cache_control`,所以現在本來就沒有 prompt cache;要開的話是另一個請求形狀的改動。 + +--- + +## libei 半開交握的資源隔離尚未完成 + +`TODO` — D2 helper 隔離;不能直接移除 `linux_wayland/libei.py::_teardown` 的半開保護。 + +需依 D2 計畫把原生配置、portal/交握、事件送出與 teardown 放進擁有的 helper, +補上有界 IPC、request ID、逾時與取消,以及 parent close/reap。 +半開交握失敗仍會留下 context/fd;直接重複建立 backend 可能重複累積, +需驗證 helper 結束後資源可回收,且取消不影響其他擁有者。 +`docker/libei_verify.py` 與 `docker/eis_verify.py` 保留原生故障/成功邊界檢查; +裝置暫停與序號回讀、真實合成器權限流程仍待對應環境驗證。 + +--- + +## `test_usb_acl_prompt.py` 讓 Python 3.10 的 headless 測試間歇 segfault + +`TODO` — `test/unit_test/headless/test_usb_acl_prompt.py::test_bridge_remember_persists_acl_rule` +在 Python 3.10 的 Linux/macOS `coverage run -m pytest` 中仍有間歇 SIGSEGV(exit 139)紀錄。 +需在對應環境開啟 `faulthandler` 重跑並定位原生呼叫;單次重跑通過不足以證明已修復。 +2026-11-02 起不再支援 Python 3.10,CI 不再跑 3.10;同一機制(分配時觸發循環回收)在 3.11 也存在,改看 3.11 的方格。 + +--- + ## Agent 電腦接管與任務自動化 `WIP` — **依使用者恢復目標繼續交付;個別原生/真機/24 小時驗收仍暫緩。** @@ -324,6 +540,153 @@ D2 仍缺 helper 隔離與半開交握資源回收;D3 的錄製/全域停止 --- + +## 一般開發規劃與相依問題 + +實機驗收新增項目請放在上方驗收區;下列規劃中的驗證條件尚不代表功能已交付。 + +## 下一步擴充:以記憶體觀察支援 UI、作業系統與應用程式背景操控 + +`TODO / 規劃` — 2026-11-01 使用者要求。此節只制定擴充順序,尚未實作或完成驗收; +不解除下列既有原生/真機/24 小時驗收暫緩,也不啟動服務、改動正式環境或讀取現有應用程式記憶體。 + +### 目標與可交付範圍 + +讓 agent 能取得指定程式的內部狀態,結合 UI、OS 與應用程式介面完成 +「觀察 → 判斷 → 背景操作 → 獨立讀回」的完整任務。先以 Windows 為第一個實作平台, +逐一擴充應用與操作覆蓋;「整個電腦」是覆蓋目標,不能宣稱任意程式都能靠讀記憶體直接操控。 +讀取位元組不會執行操作,也不會自動產生按鈕、文件、工作流程等語意;每種程式仍需已知資料格式或正式介面。 + +將三種資料來源明確分開:OS 公開查詢取得程序/視窗/服務資訊;UIA、DOM、應用程式 API +取得語意狀態;跨行程記憶體讀取補足前兩者沒有提供的特定欄位。現有 +`utils/agent_memory/agent_memory.py` 是 SQLite 任務經驗記憶,不是行程記憶體讀取器。 + +全程背景是硬條件:不切換前景、不移動使用者滑鼠、不注入桌面鍵盤/滑鼠事件; +UIA 僅作必要唯讀觀測,不以 Invoke、SetValue、選單或焦點切換代替背景操作。 +瀏覽器沿用 WebRunner 的專用持久登入設定檔、螢幕外瀏覽器與 DOM 操作。 +沒有符合條件的命令介面時回報不支援,保留缺口;不自動退回桌面輸入。 + +### 現有架構與擴充位置 + +下表的程式路徑均相對於 `je_auto_control/`;新模組名稱為提案,尚不存在。 + +| 責任 | 現況/預計接點 | 擴充內容 | +| --- | --- | --- | +| 任務與資源所有權 | `utils/agent_runtime/target_config.py`、`target_factory.py`、`native_target.py` | 沿用 profile、工具範圍、helper 與取消生命週期;新增受管觀察/背景操作能力,不另建繞過 policy 的總控入口。 | +| UI 觀察 | `utils/agent_runtime/targets.py`、`utils/accessibility/` | 現有 DesktopTarget 以指定前景應用為範圍;新增明確 PID/視窗身分的唯讀觀察,不直接放寬現有前景輸入檢查。 | +| 瀏覽器 | `utils/agent_runtime/browser_target.py`、`browser_commands.py` | 沿用受管 WebRunner session、來源限制與 DOM 驗證,不以掃描瀏覽器記憶體取代。 | +| 記憶體觀察 | 新增 `utils/process_memory/` | 擁有唯讀行程 handle、區段查詢、受限讀取與版本化解碼;原始位址及 bytes 不流入 agent 公開工具。 | +| OS/應用背景命令 | 在 `utils/agent_runtime/` 接入專用 adapter | 使用正式 API、受限 CLI、IPC/COM 等支援介面;每個動作列明資源範圍、背景副作用與完成條件。 | +| 能力診斷 | `wrapper/capabilities.py` 與 runtime profile | 現有 capability 主要為 input/capture;擴充時保留「能力存在不等於已授權」語意,按平台/程式/操作分別回報。 | + +執行資料流:既有 runtime 檢查任務與 profile → adapter 讀取受限狀態 → 產生有來源及版本的觀察 +→ runtime 再驗目標與命令範圍 → 背景命令 → 重新取得完成證據。 +記憶體 reader 只擁有讀取資源,既有 runtime 仍是任務、操作 journal 與取消的唯一擁有者。 + +### 呼叫方式與介面草圖 + +以下是待實作的契約草圖,不是現在可呼叫的 API。應用呼叫者只指定目標、欄位及目的; +位址、版本配置與 OS handle 留在 adapter 內部。 + +```python +view = await target.observe(StateQuery(fields=("document_id", "job_status"))) +receipt = await target.perform( + BackgroundCommand("export_document", document_id=view.fields["document_id"]), + expected=view.ref, +) +proof = await target.verify(receipt, CompletionQuery("export_file_matches")) +``` + +另外兩個使用情境:OS adapter 讀取指定服務狀態後執行該服務支援的管理操作,並重新查詢; +browser adapter 從受管頁面取得欄位、透過 DOM 提交,再驗證新回應或產物。 +兩者都不必知道記憶體位址,也不能只靠命令回傳成功判定完成。 + +- `TargetIdentity`:主機/登入 session、PID、程序建立時間、執行檔身分與架構;視窗/文件/瀏覽器 + context 另帶各自身分。PID 或 HWND 相同不能單獨證明還是同一目標。 +- `ObservationRef`/`Observation`:目標、adapter 與 schema 版本、觀察序號、擷取起訖時間、 + 來源、欄位、完整度/截斷及一致性結果。過期、部分讀取、未知與權限拒絕不能表示成空值或正常狀態。 +- `MemoryProbe`:profile 中登記的 probe ID、版本化 schema、欄位清單、位元組/區段/時間上限; + 內部 `read(probe, identity, deadline, cancellation) -> ProbeResult`,沒有寫入或任意執行介面。 +- `observe(query) -> Observation | ObservationFailure`:僅回傳有界、經欄位白名單篩選的語意資料。 + `perform(command, expected) -> Receipt | Refused | EffectUnknown`:操作前重驗身分與必要狀態; + 不能原子比較並執行的介面必須揭露競態,不能把舊快照當作鎖。 +- `verify(receipt, query) -> Verified | NotSatisfied | Unknown`:以新讀取、服務回應或產物驗證; + `EffectUnknown` 先查明結果,不盲目重送。reader 的觀察不授予任何操作權限。 + +### 實作順序與各階段完成條件 + +1. **M0:能力盤點與範圍契約。** 先列 Windows 的 UI/OS/應用操作矩陣,每項記錄 + 讀取來源、執行介面、權限、是否全背景、支援版本、驗證方式與不支援原因。 + 第一個目標採自有 fixture 程序,之後選一個提供正式背景介面的應用;不能先承諾任意軟體。 + 完成條件:profile、上述結果型別及禁用桌面輸入的路由規則具體可審閱,既有桌面路徑不被暗中改寫。 +2. **M1:Windows 唯讀記憶體 reader。** 實作明確型別的原生呼叫、handle 所有權、 + `VirtualQueryEx` 區段檢查及 `ReadProcessMemory` 有界讀取;僅取得必要的查詢/讀取權限。 + 限定已選程序和已知欄位,不做全機掃描或任意位址的 MCP 工具。處理 32/64 位架構、ASLR、 + guard/不可讀頁、短讀、讀取期間程序退出或區段變更;未知架構/版本回報不支援。 + 完成條件:fixture 公布的已知 buffer 能精確讀回;非法範圍、PID 重用、權限拒絕、逾時/取消 + 都有可區分結果,handle 與 helper 可確認回收。原生 fixture 驗收仍受既有暫緩約束。 +3. **M2:版本化語意解碼。** 每個 probe 綁定程式版本/模組識別與資料結構,不保存跨重啟絕對位址。 + 用目標提供的序號/快照協定驗一致性;無此機制時只能標示 best-effort,重複讀到同值不代表原子快照。 + 把 probe、UIA 唯讀及 DOM 結果整理為上述 Observation,保留來源衝突與部分缺失。 + 完成條件:版本變更、錯誤長度/指標、混合世代及未知欄位被拒絕;解碼器不能把錯誤 bytes 當成成功狀態。 +4. **M3:接入受管 runtime 與診斷。** 將讀取能力接到 profile、helper、取消、稽核與既有工具註冊; + 先在已支援 target 下附加 reader,只有不同資源所有權確實需要時才新增 target kind。 + 每次讀取有上限,原始記憶體不寫入 AgentMemory、一般日誌或模型上下文;只輸出允許的語意欄位。 + 完成條件:撤權、過期觀察、目標重啟、helper 崩潰、並行 session 不串資料;所有公開入口使用相同契約, + 關閉功能後既有任務仍可運作。 +5. **M4:UI/OS/應用背景操作。** UI 先完成必要唯讀結構/欄位觀察;網頁操作用既有 DOM。 + OS 從指定程序/檔案/服務的正式管理介面開始;應用從讀文件、設定指定欄位、儲存/匯出等 + 可確認全背景的 API/IPC 操作開始。各動作沿用 runtime policy,不透過任意 shell 或記憶體寫入繞過。 + 完成條件:每類各有一條「讀狀態 → 操作 → 獨立驗證」流程,重試不重複副作用; + 即使 API 呼叫成功,仍須另驗未改變使用者前景/焦點/滑鼠及未注入桌面輸入。 + 不符背景條件的操作維持不支援,不能只因名稱叫 API/COM 就列為已支援。 +6. **M5:跨應用任務閉環。** 接回既有四條工作流程:查詢/下載/歸檔、CSV/Excel 填表、 + 跨應用欄位轉移、工作區準備。先完成來源讀取、轉換、目的地操作、產物比對的窄流程; + 工作區準備中會搶前景或排列使用者視窗的部分維持停用。 + 完成條件:目標在觀察後被使用者修改、未知對話框、取消發生於提交期間、回覆遺失與重啟, + 均能保留已完成效果並明確區分失敗/待確認;任務結束與背景不干擾各有證據。 +7. **M6:擴充平台與交付。** Windows 的垂直流程通過後,再盤點 macOS/Linux 的合法讀取來源、 + 權限與應用介面,按能力回報 supported/unsupported/unverified;不把 Windows 的實作當成跨平台保證。 + 完成支援矩陣、操作文件、資源限額與長時間 handle/記憶體成長觀測、停用及版本回復方案; + 真機/24 小時驗收解除暫緩前,這些欄位保持未驗證。 + +**第一個可交付增量:M0 契約+M1 reader 與自有 fixture 的驗證設計。** +先完成 headless 解碼/政策測試與原生驗收腳本,原生執行另依既有暫緩安排; +不先整合所有應用、不更動正式服務。速度與記憶體預算先量測再訂門檻,不能預填改善比例。 + +### 驗收矩陣與已知邊界 + +| 面向 | 必須保留的證據 | +| --- | --- | +| 正確性 | 自有 fixture 的期望值、實際讀回、版本及身分;過期/部分讀取明確失敗;實際效果另有讀回。 | +| 全背景 | 實際 DOM/API 完成證據,另列前景視窗/焦點/滑鼠/輸入事件觀測;前後座標相同不足以排除期間干擾。 | +| 故障與生命週期 | 退出、重啟、撤權、取消、區段變更、逾時與 helper 崩潰;關閉完成須驗資源退場,未知狀態不重送操作。 | +| 資料範圍 | 只解碼 profile 指定欄位;不擷取密碼、登入 token 或跨應用資料;錯誤與紀錄不得帶出 raw bytes。 | +| 覆蓋 | 每個 OS/程式版本/操作獨立記錄已實作、已測、尚未驗收及不支援;不可由一個 fixture 推論整台電腦。 | + +讀取受 OS 權限與程序保護限制;不把需要管理權限當成預設提升理由,也不納入核心驅動、 +任意記憶體寫入、DLL 注入或繞過保護的通用控制方案。UI 語意缺失、程式私有結構改版及純影像介面 +都可能留下覆蓋缺口;需增加正式應用 adapter 或維持不支援。 + +設計取捨:比較「記憶體 reader 統一解碼所有程式」與「受管語意 adapter 搭配限定記憶體 probe」。 +採後者,讓呼叫者不必了解指標、版本及原生 handle,並沿用既有操作所有權;採納前者的 +嚴格身分、版本化解碼與資源限額。接受逐程式接合成本,換取可驗證的背景行為與失敗邊界。 +不另建全機狀態資料庫、第二套任務排程器或通用 UIA 操作入口。實作若改變上述結果契約, +須同步更新此節,不以新行為反推原規劃已完成。 + +本次規劃核對:兩個候選均收斂到限定 reader 與獨立背景操作;另經獨立交叉審閱,未發現需修正的重大問題。 +文件差異檢查通過,原有進度段落保留;此結果只驗證規劃文件,不代表功能或原生驗收通過。 + +技術依據(2026-11-01 核對):Microsoft 的 +[ReadProcessMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory)、 +[VirtualQueryEx](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualqueryex) +與 [Process Security and Access Rights](https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights) +分別定義讀取、區段查詢及程序權限; +[UI Automation Control Patterns](https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-controlpatternsoverview) +說明 UI 語意介面。這些 API 的存在不代表目標程式已支援、已授權或已通過本專案背景驗收。 + +--- + ## 750 行上限的既有豁免清單 `CLAUDE.md` §Size and complexity limits 規定:超標檔案只能列在這裡,列不進來的就是缺陷。 @@ -375,206 +738,6 @@ pip install --dry-run --only-binary=:all: --platform win_arm64 --python-version 套件依舊會被要求)。能驗的是兩件事:直接評估 marker(上面那支測試在做的), 以及 `windows-11-arm` 那一格自己綠。 -## Wayland 生命週期與驗收 - -`TODO` — 下列上游行為與原生桌面互動仍需驗證。 - -### 還沒有答案的 - -- **`eis_device_pause()` 在 libeis 1.3.901 對 sender client 沒有送出任何東西。** - 對兩個 live device 呼叫 pause 再 dispatch,client 端的 ei fd 4 秒內完全沒有可讀資料。 - 所以 `LibeiBackend._on_event` 的 `DEVICE_PAUSED`/`DEVICE_REMOVED` 分支**仍然沒有 - peer 可以驅動**。`eis_verify.py` 把這件事寫成「要嘛有反應,要嘛根本沒被通知」, - 若哪天 libeis 開始送了,client 忽略它就會當場失敗。真的合成器上會不會不一樣,未知。 -- **`ei_device_start_emulating()` 的 sequence number 沒有被送到對面。** - 刻意送 4242 過去,server 讀回來是 0。我們這邊的計數本身符合標頭檔的約定 - (每次呼叫至少 +1),所以不影響正確性,只是從對面驗不到。 -- **同意對話框「長什麼樣子、真人要按多久」。** portal 這一層現在驗到的是對話框 - *產生的東西*:准(Response 0)、拒(Response 1)、以及一直不回答。三種我們都在真的 - bus 上跑過,三種都得在自己的時限內收斂。至於真的 mutter 對話框長什麼樣、真人猶豫 - 三十秒會不會撞到別的東西,那是 mutter 的事,CI 裡沒有人可以去按它。 - -## 輸入、視窗與擷取修正:還沒在真的桌面與 Jeffrey_RPA 上驗過 - -`TODO` — 原生桌面與正式批次升級前的行為驗收暫緩。 - -- **正式批次升級前的桌面行為驗收**:需核對 `_gui_control.py` 對下列行為的實際依賴: - `write()` 大寫與 `is_shift` 在 Windows/X11 生效、`"\r\n"` 只按一次 Enter、`mouse_scroll` 預設方向改為 `scroll_up` - (X11/Wayland 上 `mouse_scroll(3)` 由往下變往上)、小數座標四捨五入、`focus_window` 在 Windows 沒拿到前景會丟例外、 - `list_windows` 不再列出 DWM cloak 與零面積視窗、`post_key` 對可列印字元只送 `WM_CHAR`。 -- **混合 DPI 座標與樣板**:需實測各螢幕上的舊版座標、`screen_region`、視窗版面與樣板, - 包含縮放不同的副螢幕、負原點與多螢幕排列;必要時重新錄製,不能以推導代替驗收。 -- **舊版存的視窗版面檔要重存**:`save_window_layout` 改存 `GetWindowRect`,舊檔還原會偏右 7 px、縮小 14×7 px。 -- **真的 Win32 行為沒有實測**:`post_key` 在真的編輯框是否只出現一個字、DWM cloak 過濾掉的是哪些視窗、 - `MoveWindow` 對最大化視窗與另一個 DPI 的螢幕是否能原樣還原,都只用假的 `user32` 驗過。 -- **X11/Wayland**:大寫與 Shift 標點的判斷假設 `keysym_to_keycode` 把大寫字母對到小寫的 keycode,沒有對著 X server 跑過。 - ---- - -## macOS 的修正:CI 驗到一半,其餘要一台真的 Mac - -`TODO` — 要一台真的 Mac(Retina,最好接第二個螢幕) - -還沒驗的: - -- **應用程式是否把 `click_mouse(clicks=2)` 認成雙擊**:只確認了欄位的值,沒有對真的應用程式送事件。 -- **`grab_logical`**(`utils/monitor_layout/macos_frame.py`,點座標、逐螢幕擷取後拼接)完全沒在 macOS 跑過。三個假設要實機確認: - `screencapture -R` 接受含負值的全域點座標、Pillow 的 `scale_down=True` 給出點尺寸的影像、`CGDisplayBounds` 與 Quartz 滑鼠事件同一個座標空間。 - 每一格要為每個螢幕各開一次 `screencapture`。CI 的 runner 是 1x 單螢幕,測不到 Retina 與副螢幕。 -- **`list_windows` 在真的桌面上的成本與誤列**:沒加 AX 逾時,沒回應的 app 會拖慢列出;同一行程裡與最小化視窗同原點或同標題的螢幕外輔助視窗可能被誤列。 - ---- - -## 這一輪修正留下的後續 - -`TODO` — 下列整合、安全與平台驗證仍未完成。 - -- **Intel Mac 安裝要編譯 `cryptography`**:下限拉到 50 之後 `macosx_10_9_x86_64` 沒有 wheel(探測:最新只到 48.0.1), - `pip install je_auto_control` 在 Intel Mac 需要 Rust 工具鏈。沒有在 Intel Mac 上實際編過。 -- **簽章分離擋不住能寫檔的人**:能執行寫檔指令(shell、檔案類指令)的人仍能換掉公鑰檔本身,保護那個檔是作業系統權限的事; - 私鑰是未加密的 PEM(0600,Windows 上沒驗權限位元),沒有通行碼選項;遷移模式開著時 HMAC 簽章會被接受。 - 強制簽章經 socket/REST/MCP 的端到端沒有跑過,覆蓋的是共用的 `read_executable_action_json` 與指令本身。 -- **RBAC**(`JE_AUTOCONTROL_RBAC_USERS`,預設關閉): - - 使用者只能用 Python 管(`UserStore.add_user/set_role/rotate_token/remove_user`),沒有 `AC_*`、CLI 或 GUI;`Capability.MANAGE_USERS` 因此沒有任何路由或工具對應。 - - viewer 的其餘影像檔案型、mobile 與外掛唯讀工具仍需全面盤點 capability;自製工具仍依提示採預設分類。 - - 沒對真的 client(Claude Desktop、VS Code、內建 dashboard)試過;SSE、無狀態與 `subscriptions/listen` 路徑、TLS 加 RBAC 沒有測試。 -- **MCP 路徑根目錄**(`JE_AUTOCONTROL_MCP_PATH_ROOTS`,預設關閉)管不到的參數:執行動作清單的工具、 - 有時才是路徑的參數(`ac_open_path`/`ac_plan_open`/`ac_file_association`/`ac_act_in_view` 的 `target`,`ac_launch_process`/`ac_shell` 的 `argv`/`command`)、 - `ac_handle_file_dialog` 的 `path`、自由格式物件裡的路徑(`ac_run_suite` 的 `spec`、`ac_run_dag` 的 `definition`、`ac_assert_all` 的 `specs`)、沒標註的外掛工具。 - 檔案 symlink 的跳脫在這台機器上建不出來(只跑了目錄 junction);POSIX 的 `:` 分隔與 `~` 沒在 Linux/macOS 跑。 - `roots/list` 來的根目錄要另外開 `JE_AUTOCONTROL_MCP_PATH_ROOTS_FROM_CLIENT` 才算數——這是實作時定的,請維護者確認。 -- **USB passthrough**:client 仍在 `reply_timeout_s`(10 秒)放棄,即使呼叫端要的 `timeout_ms` 更長(host 接受到 60 秒); - 對新 host 逾時已經無害,對舊 host 正常使用就會進入「需重連」。通道層的 ERROR(passthrough 關閉、bad frame、host 沒有 session)在 session 之前送出、不帶請求編號, - 呼叫仍是等到逾時。沒對真的舊版 host、真的 WebRTC 通道或真的 USB 裝置跑過。 -- **變數範圍**:free-threaded 原生執行緒繼承與同時存取範圍的行為尚未實測。 -- **遠端桌面的擁有者模型**:Quick Connect 沒有狀態列,它的連線被取代時視窗只是關掉;主機的 Stop 會停任何擁有者開的 host(刻意的); - 只用假的 viewer/host 測過,真的 viewer 被擠掉時會不會觸發 `on_error` 而多跳一個警告框,沒看過。 -- **套件閘門**:`execute_action` 會先驗完所有指令名稱才執行,所以「載入套件」與「用它的指令」寫在同一份清單裡會以 unknown command 失敗,與閘門無關(既有限制)。 - repo 根目錄的舊範例 `AutoControl/keyword/keyword1.json` 載入 `time`,現在預設會被拒絕。 -- **`pytest --cov` 沒有重新量過**:進入點搬到 `je_auto_control_pytest` 之後,它是否還少算,未知;規則仍是 `coverage run -m pytest`。 -- **快到 750 行上限的檔案**:`utils/usb/passthrough/viewer_client.py`(748)、`gui/remote_desktop/connection_screen.py`(729)、 - `utils/mcp_server/server.py`(734)、`utils/mcp_server/http_transport.py`(727)、`utils/agent/backends/anthropic_computer_use.py`(723)——下一次要加東西就得先拆。 - ---- - -## 行動裝置(Android/iOS):完全沒有在裝置上跑過 - -`BLOCKED` — 需要 Android 模擬器或實機、iPhone 與 WebDriverAgent;這台機器連 `adb` 都沒有 - -U-20261009-18 的每一個裝置面呼叫都只對假的 ADB/uiautomator2/WDA 測過。`uiautomator2` 與 `facebook-wda` 沒有安裝在開發環境裡, -方法名稱與參數是憑記憶寫的,第一次接上真的 SDK 很可能要修: - -- uiautomator2:`send_keys`、`drag`、空 selector 的 `gesture(...)`(捏合)、`clipboard`/`set_clipboard`、對話框按鈕的 resource id。 -- facebook-wda:`app_launch`/`app_terminate`/`app_state`、`alert.*`、`set_clipboard`、`status()`、`orientation` 的值、元素的 `pinch`、`screenshot()` 回傳 PIL 影像。 -- 旋轉方向:螢幕截圖以面板自然方向回來時,`landscape_left` 轉 270°、`landscape_right` 轉 90°,是從文件推的,沒看過。 -- Android:`input draganddrop` 是否存在、`monkey` 啟動輸出、`pidof`/`pm path` 的結束碼、`dumpsys activity activities` 的格式、`pkill -INT screenrecord` 能否收尾 MP4。 - ADBKeyBoard 的送達無法由裝置確認,是從 IME 被選取推定的。 -- 已知限制:iOS 捏合忽略 `x`/`y`/`span`;iOS `app_state` 不會回 `not_installed`;iOS 的安裝/檔案/錄影沒有 adapter(只有 `MobileExtension` 協定與註冊點); - Mobile 分頁的 probe/run 會卡住 GUI 執行緒到裝置回應或逾時。`AC_android_shell` 刻意不做成 MCP 工具,**請維護者確認**。 -- 沒有 `examples/` 的實機腳本以外的 smoke;Xcode/WDA 的建置與簽章只寫成前置條件。 - ---- - -## GUI:留下的缺口 - -`TODO` — U-20261009-27、-28、-34、-36、-38、-40 之後還開著的 - -- **Windows UIA 後端的執行緒模型完全沒對真的 COM 驗過**:現在每個呼叫執行緒各有一個自動化物件(`accessibility/backends/windows_automation.py`; - 主執行緒 STA、其他執行緒進 MTA),Accessibility 分頁與 A11y Audit 已移出 GUI 執行緒。開發環境沒裝 `comtypes`,CI 也沒有同時有 `comtypes` 與桌面的 job, - 測試全是假 COM 物件。未驗證的假設:MTA 工作執行緒上的 UIA 呼叫可用;焦點事件 callback 不需要 message pump; - `import comtypes` 第一次發生在已經是 MTA 的執行緒上會丟 `OSError`(憑記憶,沒處理)。`AC_wait_for_focus_change` 的原生 `Queue.get` 仍不會被 stop 叫醒。 -- **Script Builder 的一次性值**:一次執行最多保留 200 個(`MAX_ONE_TIME_VALUES`,留前面的);`AC_parallel` 分支裡產生的值不經結果掛鉤回報, - 只能從區塊的結果裡取得(標成 `results[0].…`)。結果裡內嵌的動作清單以「參數」規則遮蔽,那些欄位不提供一次性顯示。 - 對話框從未在真的螢幕上顯示過,真的系統剪貼簿(`QClipboard.clear()`/`text()`)在測試裡是假物件。 - `AC_approval_request` 的 `token`(請求編號)在結果畫面保持可見,但在 log 裡仍被遮蔽。 -- **stop 還叫不醒的**:已經進到後端的單一指令(一次影像搜尋、OCR、HTTP 請求、shell 指令)、單一手勢內的節奏 sleep、`AC_wait_for_focus_change`; - MCP 自己的輪詢(`ac_wait_for_image`/`ac_wait_for_pixel`)不在可停止的執行裡。非腳本的分頁工作在後端無法取消,只是結果被丟掉。 - ChatOps 的 Slack bot:`/run` 現在在工作執行緒上跑,`/stop` 的反應受輪詢間隔限制(預設 5 秒);卡在不可中斷的後端呼叫裡的執行仍停不掉,`stop()` 逾時後回 `False`;在輪詢執行緒上的指令 handler 裡呼叫 `stop()` 也會等到逾時。沒對真的 Slack workspace 跑過。 - 新轉成可停止的等待裡,`AC_handle_file_dialog`、`AC_wait_until_app_idle`、`AC_wait_for_composition_commit`、`AC_wait_for_unlock` 與行動裝置的 `wait_for_app` 只對假探針測過。 -- **WebRTC**:`StatsPoller.start()` 會在 GUI 執行緒上最多等 2 秒(`future.result(timeout=2.0)`,是啟動路徑,沒動)。LAN 廣播的註冊與取消已移出 GUI 執行緒, - 但真的 zeroconf 的時間與名稱衝突行為只對假物件測過。 -- **切換主題後那幾個事件迴圈回合內**,以被暫存的頁面為 parent 的 `QMessageBox` 會相對於隱藏的暫存 widget 定位(只影響位置)。 - 系統匣路徑在 offscreen 下沒有 tray,`_on_tray_open` 是直接呼叫測的。基準(`benchmarks/gui_*.py`)CI 仍不設門檻。 -- **把 Python 建的 widget 放進分頁列在結束時崩潰**:已查明觸發條件——分頁列按鈕上接了 Python callable、又有排隊中的 `deleteLater()`、而行程經 `os._exit` 離開; - 先把 deferred delete 沖掉就不會。機制(Qt 在行程結束時釋放那個 slot)是推論,沒有 C 堆疊可看。`_tab_close_icon.py` 沒有改回自訂按鈕。 -- **對真實 Qt 型別的型別檢查**:`test/verify/typing_extras_exempt.txt` 從 70 個模組降到 18 個(11 個 WebRTC 面板 mixin、`navigation`、`step_form_view`、 - `triggers_tab`,與 4 個對 aiortc/av 型別的 `utils/remote_desktop` 模組),只准變少。`QImage.fromData(x, "JPEG")` 的 5 處保留 `# type: ignore[arg-type]`: - stub 要 bytes,實際的 binding 對 bytes 丟 `ValueError`。 -- 遠端桌面的輸入改成佇列送出後,`AC_remote_send_input` 回的 `{"sent": True}` 意思是「已排入」;`SO_SNDTIMEO` 的 POSIX 包法與經 TLS socket 的行為沒在這台機器上驗過。 -- 沒在 macOS/Linux 上看過新的關閉鈕、捲動與重設樣式;沒在真的多螢幕桌面試過視窗位置還原;PyBreeze 沒有對這一版跑過;各語系新增的字串(日文、簡體中文)沒有母語者看過。 - ---- - -## 雜項 - -`TODO` — 小項目,各自獨立 - -- **本機的共用 `.venv` 裝著 `je_auto_control_dev 0.0.136`**,它的 `pytest11` 進入點還是舊的重量級路徑;重裝即可,不影響 CI。 -- **free-threaded**:呼叫者身分、綁定的裝置、自愈的執行標記與 stop token 都改成只在設定它的執行緒上有效(`utils/thread_bound.py`)。 - 這台機器沒有 free-threaded 直譯器:驗證用的是模擬繼承與真的 `-X thread_inherit_context=1`(3.14.7,GIL 開著);`free-threaded-scope` job(3.14t)是第一次真的跑。 -- **能力探測**:Windows 的鎖定工作站、session 0、低完整性與擷取失敗分支只用假資料判斷;macOS 的三個 preflight 呼叫只對假物件跑過, - pyobjc 的 `Quartz` 有沒有 `CGPreflightListenEventAccess` 未知(沒有的話 `recording`/`stop_shortcut` 回 `unknown`)。 -- **Windows 的版面鍵名**(`slash` 等 8 個)只在美式配置上實際呼叫過。 -- **狀態機 `on_enter` 的單一動作寫法**以前一直被拒絕、從沒執行過(已修,U-20261009-24):依賴「它不會跑」的既有狀態機現在會跑它。 - ---- - -## Computer use 的預設還是 beta 的 `computer_20251124` - -`TODO` — 在 `claude-opus-5`(兩種形式都接受)上實測 GA toolset 後,把它設成所有模型的預設 - -驗收入口:`utils/agent/backends/anthropic_computer_use.py` 與 `_computer_toolset.py`。 -需驗證多呼叫回覆、toolset 名稱、截圖尺寸、座標換算與 zoom;未取得真實 API 證據前, -其他模型的預設切換仍待完成。 - ---- - -## libei 半開交握的資源隔離尚未完成 - -`TODO` — D2 helper 隔離;不能直接移除 `linux_wayland/libei.py::_teardown` 的半開保護。 - -需依 D2 計畫把原生配置、portal/交握、事件送出與 teardown 放進擁有的 helper, -補上有界 IPC、request ID、逾時與取消,以及 parent close/reap。 -半開交握失敗仍會留下 context/fd;直接重複建立 backend 可能重複累積, -需驗證 helper 結束後資源可回收,且取消不影響其他擁有者。 -`docker/libei_verify.py` 與 `docker/eis_verify.py` 保留原生故障/成功邊界檢查; -裝置暫停與序號回讀、真實合成器權限流程仍待對應環境驗證。 - ---- - -## Agent 的歷史壓縮還沒對真的 API 跑過 - -`TODO` — 需要付費實機跑一次多步驟任務;離線測試只驗得到請求的形狀 - -需驗證 `utils/agent/backends/anthropic.py`、`anthropic_computer_use.py` 的 beta/GA 路徑, -以及 OpenAI 歷史剪裁在真實 API 上的行為: - -- 重開的歷史在強制 thinking 綁定的帳號(Opus 5.5/Fable 5.1)上是否被接受。 -- 模型只憑摘要能不能接著做——上限是 3,大約每 3 張截圖就壓縮一次,摘要最多列最新 60 個動作、每個截到 240 字元。 -- 真的桌面 PNG 的請求大小離 32 MB 多遠。 -- 兩個後端都沒送 `cache_control`,所以現在本來就沒有 prompt cache;要開的話是另一個請求形狀的改動。 - ---- - -## `test_usb_acl_prompt.py` 讓 Python 3.10 的 headless 測試間歇 segfault - -`TODO` — `test/unit_test/headless/test_usb_acl_prompt.py::test_bridge_remember_persists_acl_rule` -在 Python 3.10 的 Linux/macOS `coverage run -m pytest` 中仍有間歇 SIGSEGV(exit 139)紀錄。 -需在對應環境開啟 `faulthandler` 重跑並定位原生呼叫;單次重跑通過不足以證明已修復。 -2026-11-02 起不再支援 Python 3.10,CI 不再跑 3.10;同一機制(分配時觸發循環回收)在 3.11 也存在,改看 3.11 的方格。 - ---- - -## macos-15 上的 TCC 權限還沒被 gate 驗過 - -`TODO` — 2026-11-01 把所有 macOS 方格從 `macos-14` 改成 `macos-15`(U-20261101-02), -`test/verify/macos_verify.py` 的 `EXPECTED` 沿用 2026-08-19 在 macos-14 上的實測(螢幕錄製與輔助使用兩個 -TCC 權限都給)。`platform-smoke.yml` 的 `macos-capabilities` 只在推送到 `main` 與對 `main` 的 PR 上執行,所以下一個 dev→main -PR 才會確認 macos-15 是否給一樣的權限;若不同,依 `--measure` 重新實測後更新 `EXPECTED` 與 -`docs/CAPABILITY_MATRIX.md`,不要直接放寬 gate。 - ---- - ## minimatch 11 在 VS Code 擴充套件 `BLOCKED` — `autocontrol-lsp/vscode/package-lock.json` 的 `minimatch` 5.1.9 有 Dependabot 警示 From 34929b12af0c3ce2861b78d3a7b8d00254c21cc6 Mon Sep 17 00:00:00 2001 From: JeffreyChen Date: Tue, 10 Nov 2026 01:54:44 +0800 Subject: [PATCH 3/3] test: follow documentation counts into migrated guides --- .../headless/test_actions_menu_gui.py | 8 ++-- test/unit_test/headless/test_doc_counts.py | 41 ++++++++----------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/test/unit_test/headless/test_actions_menu_gui.py b/test/unit_test/headless/test_actions_menu_gui.py index 3663f2aa1..a525d6d3f 100644 --- a/test/unit_test/headless/test_actions_menu_gui.py +++ b/test/unit_test/headless/test_actions_menu_gui.py @@ -144,9 +144,9 @@ def test_diagnostic_run_stop_and_passive_inspection_reach_the_window_actions_men TAB_CITATIONS = ( ("architecture_explore.md", r"GUI 分頁數(`main_widget` 註冊) \| (\d+)"), ("architecture_explore.md", r"#### (\d+) 個分頁"), - ("README.md", r"\((\d+) tabs\)"), - ("README/README_zh-CN.md", r"((\d+) 个标签页)"), - ("README/README_zh-TW.md", r"((\d+) 個分頁)"), + ("docs/guides/en/setup.md", r"\((\d+) tabs\)"), + ("docs/guides/zh-CN/setup.md", r"((\d+) 个标签页)"), + ("docs/guides/zh-TW/setup.md", r"((\d+) 個分頁)"), ) @@ -163,5 +163,5 @@ def test_documented_tab_count_matches_the_widget(report, doc, pattern): for quoted in found: assert int(quoted) == report["tab_count"], ( f"{doc} says {quoted} GUI tabs, the widget builds " - f"{report['tab_count']}. Update all three READMEs." + f"{report['tab_count']}. Update the installation guides in all three languages." ) diff --git a/test/unit_test/headless/test_doc_counts.py b/test/unit_test/headless/test_doc_counts.py index 00bbf6cec..50988bbb1 100644 --- a/test/unit_test/headless/test_doc_counts.py +++ b/test/unit_test/headless/test_doc_counts.py @@ -1,14 +1,9 @@ -"""The counts quoted in the docs must match the tree. No Qt. +"""Check documented counts against the implementation. -CLAUDE.md requires `architecture_explore.md` and the three READMEs to be -updated with every change, and says every count in them is measured. Nothing -enforced it, and it drifted in practice: wiring `utils/url_canon` added three -commands and three MCP tools while every document kept quoting the old totals. -That was caught by hand afterwards, not by any check. - -A mismatch here means one of two things, and the message says which: -the number moved and the docs were not updated, or the sentence holding the -number was reworded and this test's pattern needs to follow it. +Detailed counts live in architecture_explore.md and the language-specific +usage, integration, development and installation guides under docs/guides/. +Missing quotations fail as well as incorrect totals, so moving or rewording +these documents requires updating the citation paths or patterns here. """ import pathlib import re @@ -98,22 +93,22 @@ def _typing_exemptions() -> int: ("architecture_explore.md", r"`test/verify/typing_contract_exempt\.txt`(只准變少,目前 \*\*(\d+)\*\* 個", "mypy exemptions", _typing_exemptions), - ("README.md", r"(\d+) `AC_\*` commands", "AC_* commands", _commands), - ("README.md", r"all (\d+) commands", "AC_* commands", _commands), - ("README.md", r"(\d+) tools for", "MCP tools", _mcp_tools), - ("README.md", r"(\d+) self-contained scripts", "examples", _examples), + ("docs/guides/en/usage.md", r"(\d+) `AC_\*` commands", "AC_* commands", _commands), + ("docs/guides/en/usage.md", r"all (\d+) commands", "AC_* commands", _commands), + ("docs/guides/en/integrations.md", r"(\d+) tools for", "MCP tools", _mcp_tools), + ("docs/guides/en/development.md", r"(\d+) self-contained scripts", "examples", _examples), ("architecture_explore.md", r"範例腳本 \| (\d+) \|", "examples", _examples), ("architecture_explore.md", r"`examples/` \| (\d+) 個腳本", "examples", _examples), - ("README/README_zh-CN.md", r"(\d+) 个自包含脚本", "examples", _examples), - ("README/README_zh-TW.md", r"(\d+) 個自足腳本", "examples", _examples), - ("README/README_zh-CN.md", r"(\d+) 个 `AC_\*` 命令", + ("docs/guides/zh-CN/development.md", r"(\d+) 个自包含脚本", "examples", _examples), + ("docs/guides/zh-TW/development.md", r"(\d+) 個自足腳本", "examples", _examples), + ("docs/guides/zh-CN/usage.md", r"(\d+) 个 `AC_\*` 命令", "AC_* commands", _commands), - ("README/README_zh-CN.md", r"全部 (\d+) 个命令", "AC_* commands", _commands), - ("README/README_zh-CN.md", r"(\d+) 个工具", "MCP tools", _mcp_tools), - ("README/README_zh-TW.md", r"(\d+) 個 `AC_\*` 指令", + ("docs/guides/zh-CN/usage.md", r"全部 (\d+) 个命令", "AC_* commands", _commands), + ("docs/guides/zh-CN/integrations.md", r"(\d+) 个工具", "MCP tools", _mcp_tools), + ("docs/guides/zh-TW/usage.md", r"(\d+) 個 `AC_\*` 指令", "AC_* commands", _commands), - ("README/README_zh-TW.md", r"全部 (\d+) 個指令", "AC_* commands", _commands), - ("README/README_zh-TW.md", r"(\d+) 個工具", "MCP tools", _mcp_tools), + ("docs/guides/zh-TW/usage.md", r"全部 (\d+) 個指令", "AC_* commands", _commands), + ("docs/guides/zh-TW/integrations.md", r"(\d+) 個工具", "MCP tools", _mcp_tools), ("CLAUDE.md", r"(\d+) `utils/` subpackages", "utils/ subpackages", _utils_subpackages), ("CLAUDE.md", r"\((\d+) headless subpackages\)", @@ -138,7 +133,7 @@ def test_quoted_count_matches_the_tree(doc, pattern, label, measure): assert int(quoted.replace(",", "")) == actual, ( f"{doc} says {quoted} {label}, the tree has {actual}. " f"Re-measure and update every document that quotes it " - f"(architecture_explore.md, README.md and both translations)." + f"(architecture_explore.md and the guides under docs/guides/)." )