@ai-agent-forge/plugin-desktop-windows-input 0.88.10 → 0.88.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MANUAL.md +5 -3
- package/README.md +1 -1
- package/agent-forge.json +1 -1
- package/dist/capability.d.ts +6 -3
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +42 -10
- package/dist/capability.js.map +1 -1
- package/dist/windows-uia-adapter.d.ts.map +1 -1
- package/dist/windows-uia-adapter.js +48 -3
- package/dist/windows-uia-adapter.js.map +1 -1
- package/package.json +5 -4
- package/plugin.json +1 -1
package/MANUAL.md
CHANGED
|
@@ -4,7 +4,7 @@ Windows 桌面真实输入:定向控件动作 + 真实输入队列的坐标鼠
|
|
|
4
4
|
|
|
5
5
|
## 工具
|
|
6
6
|
|
|
7
|
-
`desktop_execute`:一次动作 + 可选动作后自动 reobserve(`reobserveAfterAction: true`)
|
|
7
|
+
`desktop_execute`:一次动作 + 可选动作后自动 reobserve(`reobserveAfterAction: true`)。`type`/`key` 的 target 可选:省略 target 时输入直达当前前台焦点(UIA 不可见面的唯一通道);`focus`/`click`/`scroll` 仍必须给 target。`desktop_replay` 的录制条目同样接受无 target 的 `type`/`key`。
|
|
8
8
|
|
|
9
9
|
## 动作语义与真实度(重要)
|
|
10
10
|
|
|
@@ -13,10 +13,12 @@ Windows 桌面真实输入:定向控件动作 + 真实输入队列的坐标鼠
|
|
|
13
13
|
| click(target=control) | UIA InvokePattern → 失败回落坐标点击 | API 调用优先;**需要真实用户手势的场景(如浏览器 file input 弹原生对话框)必须用 coordinates 点击** |
|
|
14
14
|
| click(target=coordinates) | SetCursorPos + mouse_event | **真实输入队列**,与物理鼠标同级 |
|
|
15
15
|
| type(target=control) | ValuePattern/WM_SETTEXT | 值设置,非键入;浏览器表单可靠 |
|
|
16
|
-
| type(无 target) |
|
|
17
|
-
| key | keybd_event(命名键 VK/修饰组合) | 真实键盘队列;`Enter`/`Tab`/`Escape`/`Ctrl+a` 等 |
|
|
16
|
+
| type(无 target) | SendInput KEYEVENTF_UNICODE 逐码元 | **真实键盘队列,直达前台焦点**——原生对话框文件名框唯一通道;支持中文/emoji 等全部 Unicode 字符 |
|
|
17
|
+
| key | keybd_event(命名键 VK/修饰组合);无 target 时直达前台焦点队列 | 真实键盘队列;`Enter`/`Tab`/`Escape`/`Ctrl+a` 等 |
|
|
18
18
|
| scroll | mouse_event 滚轮 | 真实队列;方向格式 `down:5` |
|
|
19
19
|
|
|
20
|
+
后置条件:无 target 的 `type`/`key` 不能配 `property-equals`(它断言某个具体 target 的属性,而动作没有 target);`window-exists`/`control-exists`/`focused` 等全局检查可用,也可以不带后置条件。
|
|
21
|
+
|
|
20
22
|
## 关键坑(全部真实踩过)
|
|
21
23
|
|
|
22
24
|
1. **原生文件选择对话框**:UIA 看不到它。动线 = 坐标点击触发按钮(真实手势,InvokePattern 不算手势不弹窗)→ 前台 type 无 target 输入完整路径 → key `Enter`。开始前先 `focus` 目标窗口保证前台。
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ tools report an explicit `unsupported` result instead of probing or falling back
|
|
|
15
15
|
agent-forge plugin install ./plugins/desktop-windows-input
|
|
16
16
|
|
|
17
17
|
# from npm
|
|
18
|
-
agent-forge plugin install @agent-forge/plugin-desktop-windows-input
|
|
18
|
+
agent-forge plugin install @ai-agent-forge/plugin-desktop-windows-input
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
The package ships two manifests: `agent-forge.json` (ecosystem manifest for the deterministic plugin resolver, `platform.os: ["windows"]`) and
|
package/agent-forge.json
CHANGED
package/dist/capability.d.ts
CHANGED
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
* - The factory type is the public `CapabilityPluginSyncFactory` from the
|
|
7
7
|
* plugin SDK instead of the host-internal `BuiltinCapabilityPlugin`.
|
|
8
8
|
* - Projection helpers live in `projection.ts`, input helpers in `shared.ts`.
|
|
9
|
-
* Tool names,
|
|
10
|
-
*
|
|
11
|
-
* registration when the runtime exposes a replay method.
|
|
9
|
+
* Tool names, budgets and result shapes are unchanged, including the
|
|
10
|
+
* readonly-mode refusal to register input tools and the optional replay
|
|
11
|
+
* registration when the runtime exposes a replay method. Since the 2026-10-13
|
|
12
|
+
* product decision, type/key actions may omit the target: the request is routed
|
|
13
|
+
* to the driver's foreground keyboard-queue injection instead of being rejected
|
|
14
|
+
* (user ruling: "AI 操作需要的是任何情况下都能操作,和人一样操作电脑").
|
|
12
15
|
*/
|
|
13
16
|
import type { CapabilityPluginSyncFactory } from "@agent-forge/plugin-sdk";
|
|
14
17
|
import type { DesktopFullControlAdapterV1 } from "./types.ts";
|
package/dist/capability.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAc3E,OAAO,KAAK,EACX,2BAA2B,EAI3B,MAAM,YAAY,CAAC;AA4TpB,wBAAgB,qCAAqC,CACpD,OAAO,EAAE,2BAA2B,GAClC,2BAA2B,CAoN7B","sourcesContent":["/**\n * Bounded desktop input and replay capability factory, migrated from\n * agent-forge `src/profile/runtime-capabilities-desktop-input.ts`\n * (`desktopInputFactory`, D-075 S3 extraction). Differences from the host\n * original:\n * - The factory type is the public `CapabilityPluginSyncFactory` from the\n * plugin SDK instead of the host-internal `BuiltinCapabilityPlugin`.\n * - Projection helpers live in `projection.ts`, input helpers in `shared.ts`.\n * Tool names, parameters, budgets and result shapes are unchanged, including\n * the readonly-mode refusal to register input tools and the optional replay\n * registration when the runtime exposes a replay method.\n */\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\tDESKTOP_MAX_POSTCONDITIONS_V1,\n\tDESKTOP_MAX_REPLAY_ACTIONS_V1,\n\tDESKTOP_MAX_STRING_CHARS_V1,\n\tDESKTOP_MAX_TYPE_TEXT_CHARS_V1,\n\tdesktopBoundedString,\n\tdesktopFailure,\n\tdesktopRequiredString,\n\tdesktopResultWithinBudget,\n\tprojectDesktopObservation,\n} from \"./projection.ts\";\nimport { signalFrom, toolInvocation } from \"./shared.ts\";\nimport type {\n\tDesktopFullControlAdapterV1,\n\tDesktopOperationRequestV1,\n\tDesktopPostconditionV1,\n\tDesktopReplayRequestV1,\n} from \"./types.ts\";\n\nfunction desktopTarget(input: unknown, allowCoordinates: boolean): DesktopOperationRequestV1[\"action\"][\"target\"] {\n\tif (input === null || typeof input !== \"object\" || Array.isArray(input)) throw new Error(\"desktop-target-invalid\");\n\tconst target = input as Record<string, unknown>;\n\tif (target.kind === \"window\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"windowId\"]);\n\t\treturn { kind: \"window\", windowId: desktopRequiredString(target.windowId, \"windowId\") };\n\t}\n\tif (target.kind === \"control\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"controlId\", \"windowId\"]);\n\t\treturn {\n\t\t\tkind: \"control\",\n\t\t\tcontrolId: desktopRequiredString(target.controlId, \"controlId\"),\n\t\t\t...(target.windowId === undefined ? {} : { windowId: desktopRequiredString(target.windowId, \"windowId\") }),\n\t\t};\n\t}\n\t// Raw screen-pixel coordinates are accepted for click actions only; the\n\t// schema union cannot express that condition, so this validator rejects it.\n\tif (target.kind === \"coordinates\") {\n\t\tif (!allowCoordinates) throw new Error(\"desktop-target-invalid\");\n\t\tdesktopExactKeys(target, [\"kind\", \"x\", \"y\"]);\n\t\tif (\n\t\t\ttypeof target.x !== \"number\" ||\n\t\t\t!Number.isInteger(target.x) ||\n\t\t\ttarget.x < 0 ||\n\t\t\ttypeof target.y !== \"number\" ||\n\t\t\t!Number.isInteger(target.y) ||\n\t\t\ttarget.y < 0\n\t\t)\n\t\t\tthrow new Error(\"desktop-target-invalid\");\n\t\treturn { kind: \"coordinates\", x: target.x, y: target.y };\n\t}\n\tthrow new Error(\"desktop-target-invalid\");\n}\n\nfunction desktopExactKeys(value: Record<string, unknown>, allowed: readonly string[]): void {\n\tif (Object.keys(value).some((key) => !allowed.includes(key))) throw new Error(\"desktop-input-invalid\");\n}\n\nfunction desktopPostconditions(input: unknown): readonly DesktopPostconditionV1[] | undefined {\n\tif (input === undefined) return undefined;\n\tif (!Array.isArray(input) || input.length > DESKTOP_MAX_POSTCONDITIONS_V1)\n\t\tthrow new Error(\"desktop-postconditions-invalid\");\n\treturn input.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\tconst value = entry as Record<string, unknown>;\n\t\tif (value.kind === \"window-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"windowId\"]);\n\t\t\treturn { kind: \"window-exists\", windowId: desktopRequiredString(value.windowId, \"windowId\") } as const;\n\t\t}\n\t\tif (value.kind === \"control-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"control-exists\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"focused\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"focused\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"property-equals\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"target\", \"property\", \"expected\"]);\n\t\t\tif (value.property !== \"enabled\" && value.property !== \"value\" && value.property !== \"name\")\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\tif (\n\t\t\t\t(value.property === \"enabled\" && typeof value.expected !== \"boolean\") ||\n\t\t\t\t(value.property !== \"enabled\" && typeof value.expected !== \"string\")\n\t\t\t)\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\treturn {\n\t\t\t\tkind: \"property-equals\",\n\t\t\t\ttarget: desktopTarget(value.target, false),\n\t\t\t\tproperty: value.property,\n\t\t\t\texpected:\n\t\t\t\t\ttypeof value.expected === \"string\"\n\t\t\t\t\t\t? desktopBoundedString(value.expected, \"postcondition expected\")\n\t\t\t\t\t\t: value.expected,\n\t\t\t} as DesktopPostconditionV1;\n\t\t}\n\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t});\n}\n\nfunction desktopExecuteRequest(input: Record<string, unknown>, operationId: string): DesktopOperationRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"action\", \"postconditions\"]);\n\tconst actionInput = input.action;\n\tif (actionInput === null || typeof actionInput !== \"object\" || Array.isArray(actionInput))\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst action = actionInput as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst target = desktopTarget(action.target, action.kind === \"click\");\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst postconditions = desktopPostconditions(input.postconditions);\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tsessionId: desktopRequiredString(input.sessionId, \"sessionId\"),\n\t\taction: {\n\t\t\tversion: 1,\n\t\t\tkind: action.kind,\n\t\t\ttarget,\n\t\t\t...(text === undefined ? {} : { text }),\n\t\t\t...(key === undefined ? {} : { key }),\n\t\t},\n\t\t...(postconditions === undefined ? {} : { postconditions }),\n\t\t// Input plugin operations always request a fresh observation; callers may\n\t\t// not turn this off because target identity otherwise goes stale.\n\t\treobserveAfterAction: true,\n\t};\n}\n\nfunction desktopVerification(\n\tvalue: unknown,\n): { readonly status: \"passed\" | \"failed\" | \"unknown\"; readonly checks: readonly string[] } | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst verification = value as Record<string, unknown>;\n\tif (\n\t\t(verification.status !== \"passed\" && verification.status !== \"failed\" && verification.status !== \"unknown\") ||\n\t\t!Array.isArray(verification.checks) ||\n\t\tverification.checks.length > DESKTOP_MAX_POSTCONDITIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\treturn {\n\t\tstatus: verification.status,\n\t\tchecks: verification.checks.map((check) => desktopBoundedString(check, \"verification check\")),\n\t};\n}\n\nfunction desktopExecuteResult(value: unknown, request: DesktopOperationRequestV1) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== request.operationId ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\" &&\n\t\t\tresult.status !== \"unsupported\")\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst observation = result.observation === undefined ? undefined : projectDesktopObservation(result.observation);\n\tif (\n\t\tresult.status === \"succeeded\" &&\n\t\t(observation === undefined || observation.observation.sessionId !== request.sessionId)\n\t) {\n\t\treturn desktopFailure(\n\t\t\trequest.operationId,\n\t\t\t\"verification_unavailable\",\n\t\t\t\"Desktop action did not produce a fresh observation\",\n\t\t);\n\t}\n\tconst base = {\n\t\tversion: 1 as const,\n\t\toperationId: request.operationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop action completed\" : \"Desktop action could not be completed\",\n\t\t...(observation === undefined ? {} : observation),\n\t\t...(desktopVerification(result.verification) === undefined\n\t\t\t? {}\n\t\t\t: { verification: desktopVerification(result.verification) }),\n\t};\n\tif (result.status === \"succeeded\") return desktopResultWithinBudget(base);\n\tconst error = result.error;\n\tif (error === null || typeof error !== \"object\" || Array.isArray(error)) throw new Error(\"desktop-result-invalid\");\n\tconst errorValue = error as Record<string, unknown>;\n\tconst causeCode =\n\t\tresult.status === \"needs_user\" && typeof errorValue.causeCode === \"string\"\n\t\t\t? desktopBoundedString(errorValue.causeCode, \"error causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\t...base,\n\t\terror: {\n\t\t\tversion: 1 as const,\n\t\t\tcode: result.status === \"needs_user\" ? \"needs_user\" : \"desktop_action_failed\",\n\t\t\tmessage: result.status === \"needs_user\" ? \"Desktop action requires user action\" : \"Desktop action failed\",\n\t\t\t...(causeCode === undefined ? {} : { causeCode }),\n\t\t},\n\t});\n}\n\nfunction desktopReplayActionInput(raw: unknown): DesktopOperationRequestV1[\"action\"] {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) throw new Error(\"desktop-action-invalid\");\n\tconst action = raw as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\t// Replay stays anchored to observed identities; coordinates are execute-only.\n\tconst target = desktopTarget(action.target, false);\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\treturn {\n\t\tversion: 1,\n\t\tkind: action.kind,\n\t\ttarget,\n\t\t...(text === undefined ? {} : { text }),\n\t\t...(key === undefined ? {} : { key }),\n\t};\n}\n\nfunction desktopReplayRequest(input: Record<string, unknown>, operationId: string): DesktopReplayRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"actions\", \"stopOnFailure\"]);\n\tif (\n\t\t!Array.isArray(input.actions) ||\n\t\tinput.actions.length === 0 ||\n\t\tinput.actions.length > DESKTOP_MAX_REPLAY_ACTIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-replay-actions-invalid\");\n\tconst sessionId = desktopRequiredString(input.sessionId, \"sessionId\");\n\tconst operations = input.actions.map((raw, index) => {\n\t\tconst action = desktopReplayActionInput(raw);\n\t\treturn {\n\t\t\tversion: 1 as const,\n\t\t\toperationId: `${operationId}-${index}`,\n\t\t\tsessionId,\n\t\t\taction,\n\t\t\t// Replay always re-observes so per-action results carry fresh state.\n\t\t\treobserveAfterAction: true,\n\t\t} satisfies DesktopOperationRequestV1;\n\t});\n\treturn {\n\t\tversion: 1,\n\t\tsessionId,\n\t\toperations,\n\t\tstopOnFailure: input.stopOnFailure === undefined ? true : input.stopOnFailure === true,\n\t};\n}\n\nfunction desktopReplayResult(value: unknown, operationId: string): unknown {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\") ||\n\t\t!Array.isArray(result.results)\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst results = result.results.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (\n\t\t\trecord.version !== 1 ||\n\t\t\ttypeof record.operationId !== \"string\" ||\n\t\t\t(record.status !== \"succeeded\" &&\n\t\t\t\trecord.status !== \"failed\" &&\n\t\t\t\trecord.status !== \"cancelled\" &&\n\t\t\t\trecord.status !== \"needs_user\" &&\n\t\t\t\trecord.status !== \"unsupported\")\n\t\t)\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\treturn {\n\t\t\toperationId: desktopBoundedString(record.operationId, \"replay operationId\"),\n\t\t\tstatus: record.status,\n\t\t\tsummary: desktopBoundedString(record.summary, \"replay summary\"),\n\t\t};\n\t});\n\tconst last = result.results[result.results.length - 1] as Record<string, unknown> | undefined;\n\tconst observation =\n\t\tlast?.observation === undefined ? undefined : projectDesktopObservation(last.observation).observation;\n\tconst needsUser = result.results.find((entry) => (entry as Record<string, unknown>).status === \"needs_user\") as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\tconst causeCode =\n\t\tneedsUser !== undefined &&\n\t\tneedsUser.error !== null &&\n\t\ttypeof needsUser.error === \"object\" &&\n\t\t\"causeCode\" in needsUser.error &&\n\t\ttypeof (needsUser.error as Record<string, unknown>).causeCode === \"string\"\n\t\t\t? desktopBoundedString((needsUser.error as Record<string, unknown>).causeCode, \"replay causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop replay completed\" : \"Desktop replay stopped before completion\",\n\t\tresults,\n\t\t...(observation === undefined ? {} : { observation }),\n\t\t...(result.status === \"needs_user\" && causeCode !== undefined\n\t\t\t? {\n\t\t\t\t\terror: {\n\t\t\t\t\t\tversion: 1 as const,\n\t\t\t\t\t\tcode: \"needs_user\",\n\t\t\t\t\t\tmessage: \"Desktop replay requires user action\",\n\t\t\t\t\t\tcauseCode,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t});\n}\n\nexport function createDesktopInputCapabilityFactoryV1(\n\truntime: DesktopFullControlAdapterV1,\n): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_execute\",\n\t\t\tlabel: \"Execute desktop action\",\n\t\t\tdescription:\n\t\t\t\t\"Execute one bounded UI Automation focus, click, type, key, or scroll action against an observed target and return a fresh bounded observation\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\taction: Type.Object(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t// Raw screen pixels; click-only. The conditional click-only rule\n\t\t\t\t\t\t\t\t// is enforced by desktopExecuteRequest, not by this schema.\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"coordinates\"),\n\t\t\t\t\t\t\t\t\t\tx: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t\ty: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t),\n\t\t\t\t\tpostconditions: Type.Optional(\n\t\t\t\t\t\tType.Array(\n\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window-exists\"),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control-exists\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"focused\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"property-equals\"),\n\t\t\t\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\tproperty: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"enabled\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"value\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"name\"),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\texpected: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Boolean(),\n\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t{ maxItems: DESKTOP_MAX_POSTCONDITIONS_V1 },\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopOperationRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopExecuteRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop action input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = runtime.execute(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopExecuteResult(result, request);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tconst replay = runtime.replay;\n\t\tif (replay === undefined) return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_replay\",\n\t\t\tlabel: \"Replay desktop actions\",\n\t\t\tdescription:\n\t\t\t\t\"Replay a bounded sequence of desktop actions against one session; stops at the first failure, cancellation, or user-confirmation pause by default\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\tactions: Type.Array(\n\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{ minItems: 1, maxItems: DESKTOP_MAX_REPLAY_ACTIONS_V1 },\n\t\t\t\t\t),\n\t\t\t\t\tstopOnFailure: Type.Optional(Type.Boolean()),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopReplayRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopReplayRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop replay input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = replay(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopReplayResult(result, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAc3E,OAAO,KAAK,EACX,2BAA2B,EAI3B,MAAM,YAAY,CAAC;AAyVpB,wBAAgB,qCAAqC,CACpD,OAAO,EAAE,2BAA2B,GAClC,2BAA2B,CA8N7B","sourcesContent":["/**\n * Bounded desktop input and replay capability factory, migrated from\n * agent-forge `src/profile/runtime-capabilities-desktop-input.ts`\n * (`desktopInputFactory`, D-075 S3 extraction). Differences from the host\n * original:\n * - The factory type is the public `CapabilityPluginSyncFactory` from the\n * plugin SDK instead of the host-internal `BuiltinCapabilityPlugin`.\n * - Projection helpers live in `projection.ts`, input helpers in `shared.ts`.\n * Tool names, budgets and result shapes are unchanged, including the\n * readonly-mode refusal to register input tools and the optional replay\n * registration when the runtime exposes a replay method. Since the 2026-10-13\n * product decision, type/key actions may omit the target: the request is routed\n * to the driver's foreground keyboard-queue injection instead of being rejected\n * (user ruling: \"AI 操作需要的是任何情况下都能操作,和人一样操作电脑\").\n */\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\tDESKTOP_MAX_POSTCONDITIONS_V1,\n\tDESKTOP_MAX_REPLAY_ACTIONS_V1,\n\tDESKTOP_MAX_STRING_CHARS_V1,\n\tDESKTOP_MAX_TYPE_TEXT_CHARS_V1,\n\tdesktopBoundedString,\n\tdesktopFailure,\n\tdesktopRequiredString,\n\tdesktopResultWithinBudget,\n\tprojectDesktopObservation,\n} from \"./projection.ts\";\nimport { signalFrom, toolInvocation } from \"./shared.ts\";\nimport type {\n\tDesktopFullControlAdapterV1,\n\tDesktopOperationRequestV1,\n\tDesktopPostconditionV1,\n\tDesktopReplayRequestV1,\n} from \"./types.ts\";\n\nfunction desktopTarget(input: unknown, allowCoordinates: boolean): DesktopOperationRequestV1[\"action\"][\"target\"] {\n\tif (input === null || typeof input !== \"object\" || Array.isArray(input)) throw new Error(\"desktop-target-invalid\");\n\tconst target = input as Record<string, unknown>;\n\tif (target.kind === \"window\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"windowId\"]);\n\t\treturn { kind: \"window\", windowId: desktopRequiredString(target.windowId, \"windowId\") };\n\t}\n\tif (target.kind === \"control\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"controlId\", \"windowId\"]);\n\t\treturn {\n\t\t\tkind: \"control\",\n\t\t\tcontrolId: desktopRequiredString(target.controlId, \"controlId\"),\n\t\t\t...(target.windowId === undefined ? {} : { windowId: desktopRequiredString(target.windowId, \"windowId\") }),\n\t\t};\n\t}\n\t// Raw screen-pixel coordinates are accepted for click actions only; the\n\t// schema union cannot express that condition, so this validator rejects it.\n\tif (target.kind === \"coordinates\") {\n\t\tif (!allowCoordinates) throw new Error(\"desktop-target-invalid\");\n\t\tdesktopExactKeys(target, [\"kind\", \"x\", \"y\"]);\n\t\tif (\n\t\t\ttypeof target.x !== \"number\" ||\n\t\t\t!Number.isInteger(target.x) ||\n\t\t\ttarget.x < 0 ||\n\t\t\ttypeof target.y !== \"number\" ||\n\t\t\t!Number.isInteger(target.y) ||\n\t\t\ttarget.y < 0\n\t\t)\n\t\t\tthrow new Error(\"desktop-target-invalid\");\n\t\treturn { kind: \"coordinates\", x: target.x, y: target.y };\n\t}\n\tthrow new Error(\"desktop-target-invalid\");\n}\n\nfunction desktopExactKeys(value: Record<string, unknown>, allowed: readonly string[]): void {\n\tif (Object.keys(value).some((key) => !allowed.includes(key))) throw new Error(\"desktop-input-invalid\");\n}\n\n/**\n * Target validation with the foreground-input exception: type and key may omit\n * the target entirely. A target-less type/key is routed by the driver to the\n * real keyboard queue at the current focus (FOREGROUND_INPUT_SCRIPT) — the only\n * path that reaches UIA-invisible surfaces such as the native file dialog's\n * name box. Every other kind still requires an observed identity: a focus,\n * click or scroll without a target has no addressable subject.\n */\nfunction desktopActionTarget(\n\tinput: unknown,\n\tkind: DesktopOperationRequestV1[\"action\"][\"kind\"],\n): DesktopOperationRequestV1[\"action\"][\"target\"] | undefined {\n\tif (input === undefined) {\n\t\tif (kind === \"type\" || kind === \"key\") return undefined;\n\t\tthrow new Error(\"desktop-target-required\");\n\t}\n\treturn desktopTarget(input, kind === \"click\");\n}\n\nfunction desktopPostconditions(input: unknown): readonly DesktopPostconditionV1[] | undefined {\n\tif (input === undefined) return undefined;\n\tif (!Array.isArray(input) || input.length > DESKTOP_MAX_POSTCONDITIONS_V1)\n\t\tthrow new Error(\"desktop-postconditions-invalid\");\n\treturn input.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\tconst value = entry as Record<string, unknown>;\n\t\tif (value.kind === \"window-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"windowId\"]);\n\t\t\treturn { kind: \"window-exists\", windowId: desktopRequiredString(value.windowId, \"windowId\") } as const;\n\t\t}\n\t\tif (value.kind === \"control-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"control-exists\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"focused\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"focused\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"property-equals\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"target\", \"property\", \"expected\"]);\n\t\t\tif (value.property !== \"enabled\" && value.property !== \"value\" && value.property !== \"name\")\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\tif (\n\t\t\t\t(value.property === \"enabled\" && typeof value.expected !== \"boolean\") ||\n\t\t\t\t(value.property !== \"enabled\" && typeof value.expected !== \"string\")\n\t\t\t)\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\treturn {\n\t\t\t\tkind: \"property-equals\",\n\t\t\t\ttarget: desktopTarget(value.target, false),\n\t\t\t\tproperty: value.property,\n\t\t\t\texpected:\n\t\t\t\t\ttypeof value.expected === \"string\"\n\t\t\t\t\t\t? desktopBoundedString(value.expected, \"postcondition expected\")\n\t\t\t\t\t\t: value.expected,\n\t\t\t} as DesktopPostconditionV1;\n\t\t}\n\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t});\n}\n\nfunction desktopExecuteRequest(input: Record<string, unknown>, operationId: string): DesktopOperationRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"action\", \"postconditions\"]);\n\tconst actionInput = input.action;\n\tif (actionInput === null || typeof actionInput !== \"object\" || Array.isArray(actionInput))\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst action = actionInput as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst target = desktopActionTarget(action.target, action.kind);\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst postconditions = desktopPostconditions(input.postconditions);\n\t// Postcondition scoping for foreground actions: a target-less type/key has no\n\t// action target, so a target-level postcondition cannot describe its effect.\n\t// `property-equals` is the only kind that carries a target; pair it with a\n\t// target-less action and the check would silently assert state the action\n\t// never addressed. Global session-state checks (window-exists,\n\t// control-exists, focused) and the no-postcondition case stay allowed.\n\tif (target === undefined && postconditions?.some((condition) => condition.kind === \"property-equals\"))\n\t\tthrow new Error(\"desktop-postcondition-target-without-action-target\");\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tsessionId: desktopRequiredString(input.sessionId, \"sessionId\"),\n\t\taction: {\n\t\t\tversion: 1,\n\t\t\tkind: action.kind,\n\t\t\t...(target === undefined ? {} : { target }),\n\t\t\t...(text === undefined ? {} : { text }),\n\t\t\t...(key === undefined ? {} : { key }),\n\t\t},\n\t\t...(postconditions === undefined ? {} : { postconditions }),\n\t\t// Input plugin operations always request a fresh observation; callers may\n\t\t// not turn this off because target identity otherwise goes stale.\n\t\treobserveAfterAction: true,\n\t};\n}\n\nfunction desktopVerification(\n\tvalue: unknown,\n): { readonly status: \"passed\" | \"failed\" | \"unknown\"; readonly checks: readonly string[] } | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst verification = value as Record<string, unknown>;\n\tif (\n\t\t(verification.status !== \"passed\" && verification.status !== \"failed\" && verification.status !== \"unknown\") ||\n\t\t!Array.isArray(verification.checks) ||\n\t\tverification.checks.length > DESKTOP_MAX_POSTCONDITIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\treturn {\n\t\tstatus: verification.status,\n\t\tchecks: verification.checks.map((check) => desktopBoundedString(check, \"verification check\")),\n\t};\n}\n\nfunction desktopExecuteResult(value: unknown, request: DesktopOperationRequestV1) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== request.operationId ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\" &&\n\t\t\tresult.status !== \"unsupported\")\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst observation = result.observation === undefined ? undefined : projectDesktopObservation(result.observation);\n\tif (\n\t\tresult.status === \"succeeded\" &&\n\t\t(observation === undefined || observation.observation.sessionId !== request.sessionId)\n\t) {\n\t\treturn desktopFailure(\n\t\t\trequest.operationId,\n\t\t\t\"verification_unavailable\",\n\t\t\t\"Desktop action did not produce a fresh observation\",\n\t\t);\n\t}\n\tconst base = {\n\t\tversion: 1 as const,\n\t\toperationId: request.operationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop action completed\" : \"Desktop action could not be completed\",\n\t\t...(observation === undefined ? {} : observation),\n\t\t...(desktopVerification(result.verification) === undefined\n\t\t\t? {}\n\t\t\t: { verification: desktopVerification(result.verification) }),\n\t};\n\tif (result.status === \"succeeded\") return desktopResultWithinBudget(base);\n\tconst error = result.error;\n\tif (error === null || typeof error !== \"object\" || Array.isArray(error)) throw new Error(\"desktop-result-invalid\");\n\tconst errorValue = error as Record<string, unknown>;\n\tconst causeCode =\n\t\tresult.status === \"needs_user\" && typeof errorValue.causeCode === \"string\"\n\t\t\t? desktopBoundedString(errorValue.causeCode, \"error causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\t...base,\n\t\terror: {\n\t\t\tversion: 1 as const,\n\t\t\tcode: result.status === \"needs_user\" ? \"needs_user\" : \"desktop_action_failed\",\n\t\t\tmessage: result.status === \"needs_user\" ? \"Desktop action requires user action\" : \"Desktop action failed\",\n\t\t\t...(causeCode === undefined ? {} : { causeCode }),\n\t\t},\n\t});\n}\n\nfunction desktopReplayActionInput(raw: unknown): DesktopOperationRequestV1[\"action\"] {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) throw new Error(\"desktop-action-invalid\");\n\tconst action = raw as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\t// Replay stays anchored to observed identities; coordinates are execute-only.\n\t// Recorded foreground type/key entries (no target) replay through the same\n\t// driver foreground-injection path as desktop_execute.\n\tconst target = desktopActionTarget(action.target, action.kind);\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\treturn {\n\t\tversion: 1,\n\t\tkind: action.kind,\n\t\t...(target === undefined ? {} : { target }),\n\t\t...(text === undefined ? {} : { text }),\n\t\t...(key === undefined ? {} : { key }),\n\t};\n}\n\nfunction desktopReplayRequest(input: Record<string, unknown>, operationId: string): DesktopReplayRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"actions\", \"stopOnFailure\"]);\n\tif (\n\t\t!Array.isArray(input.actions) ||\n\t\tinput.actions.length === 0 ||\n\t\tinput.actions.length > DESKTOP_MAX_REPLAY_ACTIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-replay-actions-invalid\");\n\tconst sessionId = desktopRequiredString(input.sessionId, \"sessionId\");\n\tconst operations = input.actions.map((raw, index) => {\n\t\tconst action = desktopReplayActionInput(raw);\n\t\treturn {\n\t\t\tversion: 1 as const,\n\t\t\toperationId: `${operationId}-${index}`,\n\t\t\tsessionId,\n\t\t\taction,\n\t\t\t// Replay always re-observes so per-action results carry fresh state.\n\t\t\treobserveAfterAction: true,\n\t\t} satisfies DesktopOperationRequestV1;\n\t});\n\treturn {\n\t\tversion: 1,\n\t\tsessionId,\n\t\toperations,\n\t\tstopOnFailure: input.stopOnFailure === undefined ? true : input.stopOnFailure === true,\n\t};\n}\n\nfunction desktopReplayResult(value: unknown, operationId: string): unknown {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\") ||\n\t\t!Array.isArray(result.results)\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst results = result.results.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (\n\t\t\trecord.version !== 1 ||\n\t\t\ttypeof record.operationId !== \"string\" ||\n\t\t\t(record.status !== \"succeeded\" &&\n\t\t\t\trecord.status !== \"failed\" &&\n\t\t\t\trecord.status !== \"cancelled\" &&\n\t\t\t\trecord.status !== \"needs_user\" &&\n\t\t\t\trecord.status !== \"unsupported\")\n\t\t)\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\treturn {\n\t\t\toperationId: desktopBoundedString(record.operationId, \"replay operationId\"),\n\t\t\tstatus: record.status,\n\t\t\tsummary: desktopBoundedString(record.summary, \"replay summary\"),\n\t\t};\n\t});\n\tconst last = result.results[result.results.length - 1] as Record<string, unknown> | undefined;\n\tconst observation =\n\t\tlast?.observation === undefined ? undefined : projectDesktopObservation(last.observation).observation;\n\tconst needsUser = result.results.find((entry) => (entry as Record<string, unknown>).status === \"needs_user\") as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\tconst causeCode =\n\t\tneedsUser !== undefined &&\n\t\tneedsUser.error !== null &&\n\t\ttypeof needsUser.error === \"object\" &&\n\t\t\"causeCode\" in needsUser.error &&\n\t\ttypeof (needsUser.error as Record<string, unknown>).causeCode === \"string\"\n\t\t\t? desktopBoundedString((needsUser.error as Record<string, unknown>).causeCode, \"replay causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop replay completed\" : \"Desktop replay stopped before completion\",\n\t\tresults,\n\t\t...(observation === undefined ? {} : { observation }),\n\t\t...(result.status === \"needs_user\" && causeCode !== undefined\n\t\t\t? {\n\t\t\t\t\terror: {\n\t\t\t\t\t\tversion: 1 as const,\n\t\t\t\t\t\tcode: \"needs_user\",\n\t\t\t\t\t\tmessage: \"Desktop replay requires user action\",\n\t\t\t\t\t\tcauseCode,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t});\n}\n\nexport function createDesktopInputCapabilityFactoryV1(\n\truntime: DesktopFullControlAdapterV1,\n): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_execute\",\n\t\t\tlabel: \"Execute desktop action\",\n\t\t\tdescription:\n\t\t\t\t\"Execute one bounded UI Automation focus, click, type, key, or scroll action and return a fresh bounded observation; type and key may omit the target to send real keyboard input to the current foreground focus (native dialogs invisible to UI Automation)\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\taction: Type.Object(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t// Observed identities; optional for type/key so they can address the\n\t\t\t\t\t\t\t// foreground focus instead. The conditional rules (target required\n\t\t\t\t\t\t\t// for focus/click/scroll, coordinates click-only) are enforced by\n\t\t\t\t\t\t\t// desktopExecuteRequest, not by this schema.\n\t\t\t\t\t\t\ttarget: Type.Optional(\n\t\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t// Raw screen pixels; click-only. The conditional click-only rule\n\t\t\t\t\t\t\t\t\t// is enforced by desktopExecuteRequest, not by this schema.\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"coordinates\"),\n\t\t\t\t\t\t\t\t\t\t\tx: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t\t\ty: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t),\n\t\t\t\t\tpostconditions: Type.Optional(\n\t\t\t\t\t\tType.Array(\n\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window-exists\"),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control-exists\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"focused\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"property-equals\"),\n\t\t\t\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\tproperty: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"enabled\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"value\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"name\"),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\texpected: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Boolean(),\n\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t{ maxItems: DESKTOP_MAX_POSTCONDITIONS_V1 },\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopOperationRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopExecuteRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop action input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = runtime.execute(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopExecuteResult(result, request);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tconst replay = runtime.replay;\n\t\tif (replay === undefined) return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_replay\",\n\t\t\tlabel: \"Replay desktop actions\",\n\t\t\tdescription:\n\t\t\t\t\"Replay a bounded sequence of desktop actions against one session; stops at the first failure, cancellation, or user-confirmation pause by default. Recorded foreground type/key entries may omit the target\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\tactions: Type.Array(\n\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t// Optional for type/key (foreground replay entries); the per-kind\n\t\t\t\t\t\t\t\t// rule is enforced by desktopReplayActionInput, not by this schema.\n\t\t\t\t\t\t\t\ttarget: Type.Optional(\n\t\t\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{ minItems: 1, maxItems: DESKTOP_MAX_REPLAY_ACTIONS_V1 },\n\t\t\t\t\t),\n\t\t\t\t\tstopOnFailure: Type.Optional(Type.Boolean()),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopReplayRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopReplayRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop replay input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = replay(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopReplayResult(result, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
|
package/dist/capability.js
CHANGED
|
@@ -38,6 +38,22 @@ function desktopExactKeys(value, allowed) {
|
|
|
38
38
|
if (Object.keys(value).some((key) => !allowed.includes(key)))
|
|
39
39
|
throw new Error("desktop-input-invalid");
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Target validation with the foreground-input exception: type and key may omit
|
|
43
|
+
* the target entirely. A target-less type/key is routed by the driver to the
|
|
44
|
+
* real keyboard queue at the current focus (FOREGROUND_INPUT_SCRIPT) — the only
|
|
45
|
+
* path that reaches UIA-invisible surfaces such as the native file dialog's
|
|
46
|
+
* name box. Every other kind still requires an observed identity: a focus,
|
|
47
|
+
* click or scroll without a target has no addressable subject.
|
|
48
|
+
*/
|
|
49
|
+
function desktopActionTarget(input, kind) {
|
|
50
|
+
if (input === undefined) {
|
|
51
|
+
if (kind === "type" || kind === "key")
|
|
52
|
+
return undefined;
|
|
53
|
+
throw new Error("desktop-target-required");
|
|
54
|
+
}
|
|
55
|
+
return desktopTarget(input, kind === "click");
|
|
56
|
+
}
|
|
41
57
|
function desktopPostconditions(input) {
|
|
42
58
|
if (input === undefined)
|
|
43
59
|
return undefined;
|
|
@@ -91,7 +107,7 @@ function desktopExecuteRequest(input, operationId) {
|
|
|
91
107
|
action.kind !== "key" &&
|
|
92
108
|
action.kind !== "scroll")
|
|
93
109
|
throw new Error("desktop-action-invalid");
|
|
94
|
-
const target =
|
|
110
|
+
const target = desktopActionTarget(action.target, action.kind);
|
|
95
111
|
const text = action.kind === "type" || action.kind === "scroll" ? desktopBoundedString(action.text, "text") : undefined;
|
|
96
112
|
if (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1)
|
|
97
113
|
throw new Error("desktop-type-text-budget");
|
|
@@ -99,6 +115,14 @@ function desktopExecuteRequest(input, operationId) {
|
|
|
99
115
|
if (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1)
|
|
100
116
|
throw new Error("desktop-type-text-budget");
|
|
101
117
|
const postconditions = desktopPostconditions(input.postconditions);
|
|
118
|
+
// Postcondition scoping for foreground actions: a target-less type/key has no
|
|
119
|
+
// action target, so a target-level postcondition cannot describe its effect.
|
|
120
|
+
// `property-equals` is the only kind that carries a target; pair it with a
|
|
121
|
+
// target-less action and the check would silently assert state the action
|
|
122
|
+
// never addressed. Global session-state checks (window-exists,
|
|
123
|
+
// control-exists, focused) and the no-postcondition case stay allowed.
|
|
124
|
+
if (target === undefined && postconditions?.some((condition) => condition.kind === "property-equals"))
|
|
125
|
+
throw new Error("desktop-postcondition-target-without-action-target");
|
|
102
126
|
return {
|
|
103
127
|
version: 1,
|
|
104
128
|
operationId,
|
|
@@ -106,7 +130,7 @@ function desktopExecuteRequest(input, operationId) {
|
|
|
106
130
|
action: {
|
|
107
131
|
version: 1,
|
|
108
132
|
kind: action.kind,
|
|
109
|
-
target,
|
|
133
|
+
...(target === undefined ? {} : { target }),
|
|
110
134
|
...(text === undefined ? {} : { text }),
|
|
111
135
|
...(key === undefined ? {} : { key }),
|
|
112
136
|
},
|
|
@@ -189,7 +213,9 @@ function desktopReplayActionInput(raw) {
|
|
|
189
213
|
action.kind !== "scroll")
|
|
190
214
|
throw new Error("desktop-action-invalid");
|
|
191
215
|
// Replay stays anchored to observed identities; coordinates are execute-only.
|
|
192
|
-
|
|
216
|
+
// Recorded foreground type/key entries (no target) replay through the same
|
|
217
|
+
// driver foreground-injection path as desktop_execute.
|
|
218
|
+
const target = desktopActionTarget(action.target, action.kind);
|
|
193
219
|
const text = action.kind === "type" || action.kind === "scroll" ? desktopBoundedString(action.text, "text") : undefined;
|
|
194
220
|
if (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1)
|
|
195
221
|
throw new Error("desktop-type-text-budget");
|
|
@@ -199,7 +225,7 @@ function desktopReplayActionInput(raw) {
|
|
|
199
225
|
return {
|
|
200
226
|
version: 1,
|
|
201
227
|
kind: action.kind,
|
|
202
|
-
target,
|
|
228
|
+
...(target === undefined ? {} : { target }),
|
|
203
229
|
...(text === undefined ? {} : { text }),
|
|
204
230
|
...(key === undefined ? {} : { key }),
|
|
205
231
|
};
|
|
@@ -294,7 +320,7 @@ export function createDesktopInputCapabilityFactoryV1(runtime) {
|
|
|
294
320
|
api.registerTool({
|
|
295
321
|
name: "desktop_execute",
|
|
296
322
|
label: "Execute desktop action",
|
|
297
|
-
description: "Execute one bounded UI Automation focus, click, type, key, or scroll action
|
|
323
|
+
description: "Execute one bounded UI Automation focus, click, type, key, or scroll action and return a fresh bounded observation; type and key may omit the target to send real keyboard input to the current foreground focus (native dialogs invisible to UI Automation)",
|
|
298
324
|
parameters: Type.Object({
|
|
299
325
|
sessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),
|
|
300
326
|
action: Type.Object({
|
|
@@ -305,7 +331,11 @@ export function createDesktopInputCapabilityFactoryV1(runtime) {
|
|
|
305
331
|
Type.Literal("key"),
|
|
306
332
|
Type.Literal("scroll"),
|
|
307
333
|
]),
|
|
308
|
-
|
|
334
|
+
// Observed identities; optional for type/key so they can address the
|
|
335
|
+
// foreground focus instead. The conditional rules (target required
|
|
336
|
+
// for focus/click/scroll, coordinates click-only) are enforced by
|
|
337
|
+
// desktopExecuteRequest, not by this schema.
|
|
338
|
+
target: Type.Optional(Type.Union([
|
|
309
339
|
Type.Object({
|
|
310
340
|
kind: Type.Literal("window"),
|
|
311
341
|
windowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),
|
|
@@ -322,7 +352,7 @@ export function createDesktopInputCapabilityFactoryV1(runtime) {
|
|
|
322
352
|
x: Type.Integer({ minimum: 0 }),
|
|
323
353
|
y: Type.Integer({ minimum: 0 }),
|
|
324
354
|
}, { additionalProperties: false }),
|
|
325
|
-
]),
|
|
355
|
+
])),
|
|
326
356
|
text: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),
|
|
327
357
|
key: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),
|
|
328
358
|
}, { additionalProperties: false }),
|
|
@@ -393,7 +423,7 @@ export function createDesktopInputCapabilityFactoryV1(runtime) {
|
|
|
393
423
|
api.registerTool({
|
|
394
424
|
name: "desktop_replay",
|
|
395
425
|
label: "Replay desktop actions",
|
|
396
|
-
description: "Replay a bounded sequence of desktop actions against one session; stops at the first failure, cancellation, or user-confirmation pause by default",
|
|
426
|
+
description: "Replay a bounded sequence of desktop actions against one session; stops at the first failure, cancellation, or user-confirmation pause by default. Recorded foreground type/key entries may omit the target",
|
|
397
427
|
parameters: Type.Object({
|
|
398
428
|
sessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),
|
|
399
429
|
actions: Type.Array(Type.Object({
|
|
@@ -404,7 +434,9 @@ export function createDesktopInputCapabilityFactoryV1(runtime) {
|
|
|
404
434
|
Type.Literal("key"),
|
|
405
435
|
Type.Literal("scroll"),
|
|
406
436
|
]),
|
|
407
|
-
|
|
437
|
+
// Optional for type/key (foreground replay entries); the per-kind
|
|
438
|
+
// rule is enforced by desktopReplayActionInput, not by this schema.
|
|
439
|
+
target: Type.Optional(Type.Union([
|
|
408
440
|
Type.Object({
|
|
409
441
|
kind: Type.Literal("window"),
|
|
410
442
|
windowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),
|
|
@@ -414,7 +446,7 @@ export function createDesktopInputCapabilityFactoryV1(runtime) {
|
|
|
414
446
|
controlId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),
|
|
415
447
|
windowId: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 })),
|
|
416
448
|
}, { additionalProperties: false }),
|
|
417
|
-
]),
|
|
449
|
+
])),
|
|
418
450
|
text: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),
|
|
419
451
|
key: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),
|
|
420
452
|
}, { additionalProperties: false }), { minItems: 1, maxItems: DESKTOP_MAX_REPLAY_ACTIONS_V1 }),
|
package/dist/capability.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bounded desktop input and replay capability factory, migrated from\n * agent-forge `src/profile/runtime-capabilities-desktop-input.ts`\n * (`desktopInputFactory`, D-075 S3 extraction). Differences from the host\n * original:\n * - The factory type is the public `CapabilityPluginSyncFactory` from the\n * plugin SDK instead of the host-internal `BuiltinCapabilityPlugin`.\n * - Projection helpers live in `projection.ts`, input helpers in `shared.ts`.\n * Tool names, parameters, budgets and result shapes are unchanged, including\n * the readonly-mode refusal to register input tools and the optional replay\n * registration when the runtime exposes a replay method.\n */\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\tDESKTOP_MAX_POSTCONDITIONS_V1,\n\tDESKTOP_MAX_REPLAY_ACTIONS_V1,\n\tDESKTOP_MAX_STRING_CHARS_V1,\n\tDESKTOP_MAX_TYPE_TEXT_CHARS_V1,\n\tdesktopBoundedString,\n\tdesktopFailure,\n\tdesktopRequiredString,\n\tdesktopResultWithinBudget,\n\tprojectDesktopObservation,\n} from \"./projection.ts\";\nimport { signalFrom, toolInvocation } from \"./shared.ts\";\nimport type {\n\tDesktopFullControlAdapterV1,\n\tDesktopOperationRequestV1,\n\tDesktopPostconditionV1,\n\tDesktopReplayRequestV1,\n} from \"./types.ts\";\n\nfunction desktopTarget(input: unknown, allowCoordinates: boolean): DesktopOperationRequestV1[\"action\"][\"target\"] {\n\tif (input === null || typeof input !== \"object\" || Array.isArray(input)) throw new Error(\"desktop-target-invalid\");\n\tconst target = input as Record<string, unknown>;\n\tif (target.kind === \"window\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"windowId\"]);\n\t\treturn { kind: \"window\", windowId: desktopRequiredString(target.windowId, \"windowId\") };\n\t}\n\tif (target.kind === \"control\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"controlId\", \"windowId\"]);\n\t\treturn {\n\t\t\tkind: \"control\",\n\t\t\tcontrolId: desktopRequiredString(target.controlId, \"controlId\"),\n\t\t\t...(target.windowId === undefined ? {} : { windowId: desktopRequiredString(target.windowId, \"windowId\") }),\n\t\t};\n\t}\n\t// Raw screen-pixel coordinates are accepted for click actions only; the\n\t// schema union cannot express that condition, so this validator rejects it.\n\tif (target.kind === \"coordinates\") {\n\t\tif (!allowCoordinates) throw new Error(\"desktop-target-invalid\");\n\t\tdesktopExactKeys(target, [\"kind\", \"x\", \"y\"]);\n\t\tif (\n\t\t\ttypeof target.x !== \"number\" ||\n\t\t\t!Number.isInteger(target.x) ||\n\t\t\ttarget.x < 0 ||\n\t\t\ttypeof target.y !== \"number\" ||\n\t\t\t!Number.isInteger(target.y) ||\n\t\t\ttarget.y < 0\n\t\t)\n\t\t\tthrow new Error(\"desktop-target-invalid\");\n\t\treturn { kind: \"coordinates\", x: target.x, y: target.y };\n\t}\n\tthrow new Error(\"desktop-target-invalid\");\n}\n\nfunction desktopExactKeys(value: Record<string, unknown>, allowed: readonly string[]): void {\n\tif (Object.keys(value).some((key) => !allowed.includes(key))) throw new Error(\"desktop-input-invalid\");\n}\n\nfunction desktopPostconditions(input: unknown): readonly DesktopPostconditionV1[] | undefined {\n\tif (input === undefined) return undefined;\n\tif (!Array.isArray(input) || input.length > DESKTOP_MAX_POSTCONDITIONS_V1)\n\t\tthrow new Error(\"desktop-postconditions-invalid\");\n\treturn input.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\tconst value = entry as Record<string, unknown>;\n\t\tif (value.kind === \"window-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"windowId\"]);\n\t\t\treturn { kind: \"window-exists\", windowId: desktopRequiredString(value.windowId, \"windowId\") } as const;\n\t\t}\n\t\tif (value.kind === \"control-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"control-exists\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"focused\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"focused\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"property-equals\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"target\", \"property\", \"expected\"]);\n\t\t\tif (value.property !== \"enabled\" && value.property !== \"value\" && value.property !== \"name\")\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\tif (\n\t\t\t\t(value.property === \"enabled\" && typeof value.expected !== \"boolean\") ||\n\t\t\t\t(value.property !== \"enabled\" && typeof value.expected !== \"string\")\n\t\t\t)\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\treturn {\n\t\t\t\tkind: \"property-equals\",\n\t\t\t\ttarget: desktopTarget(value.target, false),\n\t\t\t\tproperty: value.property,\n\t\t\t\texpected:\n\t\t\t\t\ttypeof value.expected === \"string\"\n\t\t\t\t\t\t? desktopBoundedString(value.expected, \"postcondition expected\")\n\t\t\t\t\t\t: value.expected,\n\t\t\t} as DesktopPostconditionV1;\n\t\t}\n\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t});\n}\n\nfunction desktopExecuteRequest(input: Record<string, unknown>, operationId: string): DesktopOperationRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"action\", \"postconditions\"]);\n\tconst actionInput = input.action;\n\tif (actionInput === null || typeof actionInput !== \"object\" || Array.isArray(actionInput))\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst action = actionInput as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst target = desktopTarget(action.target, action.kind === \"click\");\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst postconditions = desktopPostconditions(input.postconditions);\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tsessionId: desktopRequiredString(input.sessionId, \"sessionId\"),\n\t\taction: {\n\t\t\tversion: 1,\n\t\t\tkind: action.kind,\n\t\t\ttarget,\n\t\t\t...(text === undefined ? {} : { text }),\n\t\t\t...(key === undefined ? {} : { key }),\n\t\t},\n\t\t...(postconditions === undefined ? {} : { postconditions }),\n\t\t// Input plugin operations always request a fresh observation; callers may\n\t\t// not turn this off because target identity otherwise goes stale.\n\t\treobserveAfterAction: true,\n\t};\n}\n\nfunction desktopVerification(\n\tvalue: unknown,\n): { readonly status: \"passed\" | \"failed\" | \"unknown\"; readonly checks: readonly string[] } | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst verification = value as Record<string, unknown>;\n\tif (\n\t\t(verification.status !== \"passed\" && verification.status !== \"failed\" && verification.status !== \"unknown\") ||\n\t\t!Array.isArray(verification.checks) ||\n\t\tverification.checks.length > DESKTOP_MAX_POSTCONDITIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\treturn {\n\t\tstatus: verification.status,\n\t\tchecks: verification.checks.map((check) => desktopBoundedString(check, \"verification check\")),\n\t};\n}\n\nfunction desktopExecuteResult(value: unknown, request: DesktopOperationRequestV1) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== request.operationId ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\" &&\n\t\t\tresult.status !== \"unsupported\")\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst observation = result.observation === undefined ? undefined : projectDesktopObservation(result.observation);\n\tif (\n\t\tresult.status === \"succeeded\" &&\n\t\t(observation === undefined || observation.observation.sessionId !== request.sessionId)\n\t) {\n\t\treturn desktopFailure(\n\t\t\trequest.operationId,\n\t\t\t\"verification_unavailable\",\n\t\t\t\"Desktop action did not produce a fresh observation\",\n\t\t);\n\t}\n\tconst base = {\n\t\tversion: 1 as const,\n\t\toperationId: request.operationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop action completed\" : \"Desktop action could not be completed\",\n\t\t...(observation === undefined ? {} : observation),\n\t\t...(desktopVerification(result.verification) === undefined\n\t\t\t? {}\n\t\t\t: { verification: desktopVerification(result.verification) }),\n\t};\n\tif (result.status === \"succeeded\") return desktopResultWithinBudget(base);\n\tconst error = result.error;\n\tif (error === null || typeof error !== \"object\" || Array.isArray(error)) throw new Error(\"desktop-result-invalid\");\n\tconst errorValue = error as Record<string, unknown>;\n\tconst causeCode =\n\t\tresult.status === \"needs_user\" && typeof errorValue.causeCode === \"string\"\n\t\t\t? desktopBoundedString(errorValue.causeCode, \"error causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\t...base,\n\t\terror: {\n\t\t\tversion: 1 as const,\n\t\t\tcode: result.status === \"needs_user\" ? \"needs_user\" : \"desktop_action_failed\",\n\t\t\tmessage: result.status === \"needs_user\" ? \"Desktop action requires user action\" : \"Desktop action failed\",\n\t\t\t...(causeCode === undefined ? {} : { causeCode }),\n\t\t},\n\t});\n}\n\nfunction desktopReplayActionInput(raw: unknown): DesktopOperationRequestV1[\"action\"] {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) throw new Error(\"desktop-action-invalid\");\n\tconst action = raw as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\t// Replay stays anchored to observed identities; coordinates are execute-only.\n\tconst target = desktopTarget(action.target, false);\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\treturn {\n\t\tversion: 1,\n\t\tkind: action.kind,\n\t\ttarget,\n\t\t...(text === undefined ? {} : { text }),\n\t\t...(key === undefined ? {} : { key }),\n\t};\n}\n\nfunction desktopReplayRequest(input: Record<string, unknown>, operationId: string): DesktopReplayRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"actions\", \"stopOnFailure\"]);\n\tif (\n\t\t!Array.isArray(input.actions) ||\n\t\tinput.actions.length === 0 ||\n\t\tinput.actions.length > DESKTOP_MAX_REPLAY_ACTIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-replay-actions-invalid\");\n\tconst sessionId = desktopRequiredString(input.sessionId, \"sessionId\");\n\tconst operations = input.actions.map((raw, index) => {\n\t\tconst action = desktopReplayActionInput(raw);\n\t\treturn {\n\t\t\tversion: 1 as const,\n\t\t\toperationId: `${operationId}-${index}`,\n\t\t\tsessionId,\n\t\t\taction,\n\t\t\t// Replay always re-observes so per-action results carry fresh state.\n\t\t\treobserveAfterAction: true,\n\t\t} satisfies DesktopOperationRequestV1;\n\t});\n\treturn {\n\t\tversion: 1,\n\t\tsessionId,\n\t\toperations,\n\t\tstopOnFailure: input.stopOnFailure === undefined ? true : input.stopOnFailure === true,\n\t};\n}\n\nfunction desktopReplayResult(value: unknown, operationId: string): unknown {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\") ||\n\t\t!Array.isArray(result.results)\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst results = result.results.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (\n\t\t\trecord.version !== 1 ||\n\t\t\ttypeof record.operationId !== \"string\" ||\n\t\t\t(record.status !== \"succeeded\" &&\n\t\t\t\trecord.status !== \"failed\" &&\n\t\t\t\trecord.status !== \"cancelled\" &&\n\t\t\t\trecord.status !== \"needs_user\" &&\n\t\t\t\trecord.status !== \"unsupported\")\n\t\t)\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\treturn {\n\t\t\toperationId: desktopBoundedString(record.operationId, \"replay operationId\"),\n\t\t\tstatus: record.status,\n\t\t\tsummary: desktopBoundedString(record.summary, \"replay summary\"),\n\t\t};\n\t});\n\tconst last = result.results[result.results.length - 1] as Record<string, unknown> | undefined;\n\tconst observation =\n\t\tlast?.observation === undefined ? undefined : projectDesktopObservation(last.observation).observation;\n\tconst needsUser = result.results.find((entry) => (entry as Record<string, unknown>).status === \"needs_user\") as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\tconst causeCode =\n\t\tneedsUser !== undefined &&\n\t\tneedsUser.error !== null &&\n\t\ttypeof needsUser.error === \"object\" &&\n\t\t\"causeCode\" in needsUser.error &&\n\t\ttypeof (needsUser.error as Record<string, unknown>).causeCode === \"string\"\n\t\t\t? desktopBoundedString((needsUser.error as Record<string, unknown>).causeCode, \"replay causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop replay completed\" : \"Desktop replay stopped before completion\",\n\t\tresults,\n\t\t...(observation === undefined ? {} : { observation }),\n\t\t...(result.status === \"needs_user\" && causeCode !== undefined\n\t\t\t? {\n\t\t\t\t\terror: {\n\t\t\t\t\t\tversion: 1 as const,\n\t\t\t\t\t\tcode: \"needs_user\",\n\t\t\t\t\t\tmessage: \"Desktop replay requires user action\",\n\t\t\t\t\t\tcauseCode,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t});\n}\n\nexport function createDesktopInputCapabilityFactoryV1(\n\truntime: DesktopFullControlAdapterV1,\n): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_execute\",\n\t\t\tlabel: \"Execute desktop action\",\n\t\t\tdescription:\n\t\t\t\t\"Execute one bounded UI Automation focus, click, type, key, or scroll action against an observed target and return a fresh bounded observation\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\taction: Type.Object(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t// Raw screen pixels; click-only. The conditional click-only rule\n\t\t\t\t\t\t\t\t// is enforced by desktopExecuteRequest, not by this schema.\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"coordinates\"),\n\t\t\t\t\t\t\t\t\t\tx: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t\ty: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t),\n\t\t\t\t\tpostconditions: Type.Optional(\n\t\t\t\t\t\tType.Array(\n\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window-exists\"),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control-exists\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"focused\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"property-equals\"),\n\t\t\t\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\tproperty: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"enabled\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"value\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"name\"),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\texpected: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Boolean(),\n\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t{ maxItems: DESKTOP_MAX_POSTCONDITIONS_V1 },\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopOperationRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopExecuteRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop action input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = runtime.execute(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopExecuteResult(result, request);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tconst replay = runtime.replay;\n\t\tif (replay === undefined) return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_replay\",\n\t\t\tlabel: \"Replay desktop actions\",\n\t\t\tdescription:\n\t\t\t\t\"Replay a bounded sequence of desktop actions against one session; stops at the first failure, cancellation, or user-confirmation pause by default\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\tactions: Type.Array(\n\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{ minItems: 1, maxItems: DESKTOP_MAX_REPLAY_ACTIONS_V1 },\n\t\t\t\t\t),\n\t\t\t\t\tstopOnFailure: Type.Optional(Type.Boolean()),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopReplayRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopReplayRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop replay input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = replay(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopReplayResult(result, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bounded desktop input and replay capability factory, migrated from\n * agent-forge `src/profile/runtime-capabilities-desktop-input.ts`\n * (`desktopInputFactory`, D-075 S3 extraction). Differences from the host\n * original:\n * - The factory type is the public `CapabilityPluginSyncFactory` from the\n * plugin SDK instead of the host-internal `BuiltinCapabilityPlugin`.\n * - Projection helpers live in `projection.ts`, input helpers in `shared.ts`.\n * Tool names, budgets and result shapes are unchanged, including the\n * readonly-mode refusal to register input tools and the optional replay\n * registration when the runtime exposes a replay method. Since the 2026-10-13\n * product decision, type/key actions may omit the target: the request is routed\n * to the driver's foreground keyboard-queue injection instead of being rejected\n * (user ruling: \"AI 操作需要的是任何情况下都能操作,和人一样操作电脑\").\n */\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\tDESKTOP_MAX_POSTCONDITIONS_V1,\n\tDESKTOP_MAX_REPLAY_ACTIONS_V1,\n\tDESKTOP_MAX_STRING_CHARS_V1,\n\tDESKTOP_MAX_TYPE_TEXT_CHARS_V1,\n\tdesktopBoundedString,\n\tdesktopFailure,\n\tdesktopRequiredString,\n\tdesktopResultWithinBudget,\n\tprojectDesktopObservation,\n} from \"./projection.ts\";\nimport { signalFrom, toolInvocation } from \"./shared.ts\";\nimport type {\n\tDesktopFullControlAdapterV1,\n\tDesktopOperationRequestV1,\n\tDesktopPostconditionV1,\n\tDesktopReplayRequestV1,\n} from \"./types.ts\";\n\nfunction desktopTarget(input: unknown, allowCoordinates: boolean): DesktopOperationRequestV1[\"action\"][\"target\"] {\n\tif (input === null || typeof input !== \"object\" || Array.isArray(input)) throw new Error(\"desktop-target-invalid\");\n\tconst target = input as Record<string, unknown>;\n\tif (target.kind === \"window\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"windowId\"]);\n\t\treturn { kind: \"window\", windowId: desktopRequiredString(target.windowId, \"windowId\") };\n\t}\n\tif (target.kind === \"control\") {\n\t\tdesktopExactKeys(target, [\"kind\", \"controlId\", \"windowId\"]);\n\t\treturn {\n\t\t\tkind: \"control\",\n\t\t\tcontrolId: desktopRequiredString(target.controlId, \"controlId\"),\n\t\t\t...(target.windowId === undefined ? {} : { windowId: desktopRequiredString(target.windowId, \"windowId\") }),\n\t\t};\n\t}\n\t// Raw screen-pixel coordinates are accepted for click actions only; the\n\t// schema union cannot express that condition, so this validator rejects it.\n\tif (target.kind === \"coordinates\") {\n\t\tif (!allowCoordinates) throw new Error(\"desktop-target-invalid\");\n\t\tdesktopExactKeys(target, [\"kind\", \"x\", \"y\"]);\n\t\tif (\n\t\t\ttypeof target.x !== \"number\" ||\n\t\t\t!Number.isInteger(target.x) ||\n\t\t\ttarget.x < 0 ||\n\t\t\ttypeof target.y !== \"number\" ||\n\t\t\t!Number.isInteger(target.y) ||\n\t\t\ttarget.y < 0\n\t\t)\n\t\t\tthrow new Error(\"desktop-target-invalid\");\n\t\treturn { kind: \"coordinates\", x: target.x, y: target.y };\n\t}\n\tthrow new Error(\"desktop-target-invalid\");\n}\n\nfunction desktopExactKeys(value: Record<string, unknown>, allowed: readonly string[]): void {\n\tif (Object.keys(value).some((key) => !allowed.includes(key))) throw new Error(\"desktop-input-invalid\");\n}\n\n/**\n * Target validation with the foreground-input exception: type and key may omit\n * the target entirely. A target-less type/key is routed by the driver to the\n * real keyboard queue at the current focus (FOREGROUND_INPUT_SCRIPT) — the only\n * path that reaches UIA-invisible surfaces such as the native file dialog's\n * name box. Every other kind still requires an observed identity: a focus,\n * click or scroll without a target has no addressable subject.\n */\nfunction desktopActionTarget(\n\tinput: unknown,\n\tkind: DesktopOperationRequestV1[\"action\"][\"kind\"],\n): DesktopOperationRequestV1[\"action\"][\"target\"] | undefined {\n\tif (input === undefined) {\n\t\tif (kind === \"type\" || kind === \"key\") return undefined;\n\t\tthrow new Error(\"desktop-target-required\");\n\t}\n\treturn desktopTarget(input, kind === \"click\");\n}\n\nfunction desktopPostconditions(input: unknown): readonly DesktopPostconditionV1[] | undefined {\n\tif (input === undefined) return undefined;\n\tif (!Array.isArray(input) || input.length > DESKTOP_MAX_POSTCONDITIONS_V1)\n\t\tthrow new Error(\"desktop-postconditions-invalid\");\n\treturn input.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\tconst value = entry as Record<string, unknown>;\n\t\tif (value.kind === \"window-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"windowId\"]);\n\t\t\treturn { kind: \"window-exists\", windowId: desktopRequiredString(value.windowId, \"windowId\") } as const;\n\t\t}\n\t\tif (value.kind === \"control-exists\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"control-exists\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"focused\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"controlId\"]);\n\t\t\treturn { kind: \"focused\", controlId: desktopRequiredString(value.controlId, \"controlId\") } as const;\n\t\t}\n\t\tif (value.kind === \"property-equals\") {\n\t\t\tdesktopExactKeys(value, [\"kind\", \"target\", \"property\", \"expected\"]);\n\t\t\tif (value.property !== \"enabled\" && value.property !== \"value\" && value.property !== \"name\")\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\tif (\n\t\t\t\t(value.property === \"enabled\" && typeof value.expected !== \"boolean\") ||\n\t\t\t\t(value.property !== \"enabled\" && typeof value.expected !== \"string\")\n\t\t\t)\n\t\t\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t\t\treturn {\n\t\t\t\tkind: \"property-equals\",\n\t\t\t\ttarget: desktopTarget(value.target, false),\n\t\t\t\tproperty: value.property,\n\t\t\t\texpected:\n\t\t\t\t\ttypeof value.expected === \"string\"\n\t\t\t\t\t\t? desktopBoundedString(value.expected, \"postcondition expected\")\n\t\t\t\t\t\t: value.expected,\n\t\t\t} as DesktopPostconditionV1;\n\t\t}\n\t\tthrow new Error(\"desktop-postcondition-invalid\");\n\t});\n}\n\nfunction desktopExecuteRequest(input: Record<string, unknown>, operationId: string): DesktopOperationRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"action\", \"postconditions\"]);\n\tconst actionInput = input.action;\n\tif (actionInput === null || typeof actionInput !== \"object\" || Array.isArray(actionInput))\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst action = actionInput as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\tconst target = desktopActionTarget(action.target, action.kind);\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst postconditions = desktopPostconditions(input.postconditions);\n\t// Postcondition scoping for foreground actions: a target-less type/key has no\n\t// action target, so a target-level postcondition cannot describe its effect.\n\t// `property-equals` is the only kind that carries a target; pair it with a\n\t// target-less action and the check would silently assert state the action\n\t// never addressed. Global session-state checks (window-exists,\n\t// control-exists, focused) and the no-postcondition case stay allowed.\n\tif (target === undefined && postconditions?.some((condition) => condition.kind === \"property-equals\"))\n\t\tthrow new Error(\"desktop-postcondition-target-without-action-target\");\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tsessionId: desktopRequiredString(input.sessionId, \"sessionId\"),\n\t\taction: {\n\t\t\tversion: 1,\n\t\t\tkind: action.kind,\n\t\t\t...(target === undefined ? {} : { target }),\n\t\t\t...(text === undefined ? {} : { text }),\n\t\t\t...(key === undefined ? {} : { key }),\n\t\t},\n\t\t...(postconditions === undefined ? {} : { postconditions }),\n\t\t// Input plugin operations always request a fresh observation; callers may\n\t\t// not turn this off because target identity otherwise goes stale.\n\t\treobserveAfterAction: true,\n\t};\n}\n\nfunction desktopVerification(\n\tvalue: unknown,\n): { readonly status: \"passed\" | \"failed\" | \"unknown\"; readonly checks: readonly string[] } | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst verification = value as Record<string, unknown>;\n\tif (\n\t\t(verification.status !== \"passed\" && verification.status !== \"failed\" && verification.status !== \"unknown\") ||\n\t\t!Array.isArray(verification.checks) ||\n\t\tverification.checks.length > DESKTOP_MAX_POSTCONDITIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\treturn {\n\t\tstatus: verification.status,\n\t\tchecks: verification.checks.map((check) => desktopBoundedString(check, \"verification check\")),\n\t};\n}\n\nfunction desktopExecuteResult(value: unknown, request: DesktopOperationRequestV1) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== request.operationId ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\" &&\n\t\t\tresult.status !== \"unsupported\")\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst observation = result.observation === undefined ? undefined : projectDesktopObservation(result.observation);\n\tif (\n\t\tresult.status === \"succeeded\" &&\n\t\t(observation === undefined || observation.observation.sessionId !== request.sessionId)\n\t) {\n\t\treturn desktopFailure(\n\t\t\trequest.operationId,\n\t\t\t\"verification_unavailable\",\n\t\t\t\"Desktop action did not produce a fresh observation\",\n\t\t);\n\t}\n\tconst base = {\n\t\tversion: 1 as const,\n\t\toperationId: request.operationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop action completed\" : \"Desktop action could not be completed\",\n\t\t...(observation === undefined ? {} : observation),\n\t\t...(desktopVerification(result.verification) === undefined\n\t\t\t? {}\n\t\t\t: { verification: desktopVerification(result.verification) }),\n\t};\n\tif (result.status === \"succeeded\") return desktopResultWithinBudget(base);\n\tconst error = result.error;\n\tif (error === null || typeof error !== \"object\" || Array.isArray(error)) throw new Error(\"desktop-result-invalid\");\n\tconst errorValue = error as Record<string, unknown>;\n\tconst causeCode =\n\t\tresult.status === \"needs_user\" && typeof errorValue.causeCode === \"string\"\n\t\t\t? desktopBoundedString(errorValue.causeCode, \"error causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\t...base,\n\t\terror: {\n\t\t\tversion: 1 as const,\n\t\t\tcode: result.status === \"needs_user\" ? \"needs_user\" : \"desktop_action_failed\",\n\t\t\tmessage: result.status === \"needs_user\" ? \"Desktop action requires user action\" : \"Desktop action failed\",\n\t\t\t...(causeCode === undefined ? {} : { causeCode }),\n\t\t},\n\t});\n}\n\nfunction desktopReplayActionInput(raw: unknown): DesktopOperationRequestV1[\"action\"] {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) throw new Error(\"desktop-action-invalid\");\n\tconst action = raw as Record<string, unknown>;\n\tdesktopExactKeys(action, [\"kind\", \"target\", \"text\", \"key\"]);\n\tif (\n\t\taction.kind !== \"focus\" &&\n\t\taction.kind !== \"click\" &&\n\t\taction.kind !== \"type\" &&\n\t\taction.kind !== \"key\" &&\n\t\taction.kind !== \"scroll\"\n\t)\n\t\tthrow new Error(\"desktop-action-invalid\");\n\t// Replay stays anchored to observed identities; coordinates are execute-only.\n\t// Recorded foreground type/key entries (no target) replay through the same\n\t// driver foreground-injection path as desktop_execute.\n\tconst target = desktopActionTarget(action.target, action.kind);\n\tconst text =\n\t\taction.kind === \"type\" || action.kind === \"scroll\" ? desktopBoundedString(action.text, \"text\") : undefined;\n\tif (text !== undefined && text.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\tconst key = action.kind === \"key\" ? desktopBoundedString(action.key, \"key\") : undefined;\n\tif (key !== undefined && key.length > DESKTOP_MAX_TYPE_TEXT_CHARS_V1) throw new Error(\"desktop-type-text-budget\");\n\treturn {\n\t\tversion: 1,\n\t\tkind: action.kind,\n\t\t...(target === undefined ? {} : { target }),\n\t\t...(text === undefined ? {} : { text }),\n\t\t...(key === undefined ? {} : { key }),\n\t};\n}\n\nfunction desktopReplayRequest(input: Record<string, unknown>, operationId: string): DesktopReplayRequestV1 {\n\tdesktopExactKeys(input, [\"sessionId\", \"actions\", \"stopOnFailure\"]);\n\tif (\n\t\t!Array.isArray(input.actions) ||\n\t\tinput.actions.length === 0 ||\n\t\tinput.actions.length > DESKTOP_MAX_REPLAY_ACTIONS_V1\n\t)\n\t\tthrow new Error(\"desktop-replay-actions-invalid\");\n\tconst sessionId = desktopRequiredString(input.sessionId, \"sessionId\");\n\tconst operations = input.actions.map((raw, index) => {\n\t\tconst action = desktopReplayActionInput(raw);\n\t\treturn {\n\t\t\tversion: 1 as const,\n\t\t\toperationId: `${operationId}-${index}`,\n\t\t\tsessionId,\n\t\t\taction,\n\t\t\t// Replay always re-observes so per-action results carry fresh state.\n\t\t\treobserveAfterAction: true,\n\t\t} satisfies DesktopOperationRequestV1;\n\t});\n\treturn {\n\t\tversion: 1,\n\t\tsessionId,\n\t\toperations,\n\t\tstopOnFailure: input.stopOnFailure === undefined ? true : input.stopOnFailure === true,\n\t};\n}\n\nfunction desktopReplayResult(value: unknown, operationId: string): unknown {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"desktop-result-invalid\");\n\tconst result = value as Record<string, unknown>;\n\tif (\n\t\tresult.version !== 1 ||\n\t\t(result.status !== \"succeeded\" &&\n\t\t\tresult.status !== \"failed\" &&\n\t\t\tresult.status !== \"cancelled\" &&\n\t\t\tresult.status !== \"needs_user\") ||\n\t\t!Array.isArray(result.results)\n\t)\n\t\tthrow new Error(\"desktop-result-invalid\");\n\tconst results = result.results.map((entry) => {\n\t\tif (entry === null || typeof entry !== \"object\" || Array.isArray(entry))\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (\n\t\t\trecord.version !== 1 ||\n\t\t\ttypeof record.operationId !== \"string\" ||\n\t\t\t(record.status !== \"succeeded\" &&\n\t\t\t\trecord.status !== \"failed\" &&\n\t\t\t\trecord.status !== \"cancelled\" &&\n\t\t\t\trecord.status !== \"needs_user\" &&\n\t\t\t\trecord.status !== \"unsupported\")\n\t\t)\n\t\t\tthrow new Error(\"desktop-result-invalid\");\n\t\treturn {\n\t\t\toperationId: desktopBoundedString(record.operationId, \"replay operationId\"),\n\t\t\tstatus: record.status,\n\t\t\tsummary: desktopBoundedString(record.summary, \"replay summary\"),\n\t\t};\n\t});\n\tconst last = result.results[result.results.length - 1] as Record<string, unknown> | undefined;\n\tconst observation =\n\t\tlast?.observation === undefined ? undefined : projectDesktopObservation(last.observation).observation;\n\tconst needsUser = result.results.find((entry) => (entry as Record<string, unknown>).status === \"needs_user\") as\n\t\t| Record<string, unknown>\n\t\t| undefined;\n\tconst causeCode =\n\t\tneedsUser !== undefined &&\n\t\tneedsUser.error !== null &&\n\t\ttypeof needsUser.error === \"object\" &&\n\t\t\"causeCode\" in needsUser.error &&\n\t\ttypeof (needsUser.error as Record<string, unknown>).causeCode === \"string\"\n\t\t\t? desktopBoundedString((needsUser.error as Record<string, unknown>).causeCode, \"replay causeCode\")\n\t\t\t: undefined;\n\treturn desktopResultWithinBudget({\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: result.status,\n\t\tsummary: result.status === \"succeeded\" ? \"Desktop replay completed\" : \"Desktop replay stopped before completion\",\n\t\tresults,\n\t\t...(observation === undefined ? {} : { observation }),\n\t\t...(result.status === \"needs_user\" && causeCode !== undefined\n\t\t\t? {\n\t\t\t\t\terror: {\n\t\t\t\t\t\tversion: 1 as const,\n\t\t\t\t\t\tcode: \"needs_user\",\n\t\t\t\t\t\tmessage: \"Desktop replay requires user action\",\n\t\t\t\t\t\tcauseCode,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t});\n}\n\nexport function createDesktopInputCapabilityFactoryV1(\n\truntime: DesktopFullControlAdapterV1,\n): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_execute\",\n\t\t\tlabel: \"Execute desktop action\",\n\t\t\tdescription:\n\t\t\t\t\"Execute one bounded UI Automation focus, click, type, key, or scroll action and return a fresh bounded observation; type and key may omit the target to send real keyboard input to the current foreground focus (native dialogs invisible to UI Automation)\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\taction: Type.Object(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t// Observed identities; optional for type/key so they can address the\n\t\t\t\t\t\t\t// foreground focus instead. The conditional rules (target required\n\t\t\t\t\t\t\t// for focus/click/scroll, coordinates click-only) are enforced by\n\t\t\t\t\t\t\t// desktopExecuteRequest, not by this schema.\n\t\t\t\t\t\t\ttarget: Type.Optional(\n\t\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t// Raw screen pixels; click-only. The conditional click-only rule\n\t\t\t\t\t\t\t\t\t// is enforced by desktopExecuteRequest, not by this schema.\n\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"coordinates\"),\n\t\t\t\t\t\t\t\t\t\t\tx: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t\t\ty: Type.Integer({ minimum: 0 }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t),\n\t\t\t\t\tpostconditions: Type.Optional(\n\t\t\t\t\t\tType.Array(\n\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window-exists\"),\n\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control-exists\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"focused\"),\n\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"property-equals\"),\n\t\t\t\t\t\t\t\t\t\ttarget: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\tproperty: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"enabled\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"value\"),\n\t\t\t\t\t\t\t\t\t\t\tType.Literal(\"name\"),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\texpected: Type.Union([\n\t\t\t\t\t\t\t\t\t\t\tType.Boolean(),\n\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t{ maxItems: DESKTOP_MAX_POSTCONDITIONS_V1 },\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopOperationRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopExecuteRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop action input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = runtime.execute(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopExecuteResult(result, request);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tconst replay = runtime.replay;\n\t\tif (replay === undefined) return;\n\t\tapi.registerTool({\n\t\t\tname: \"desktop_replay\",\n\t\t\tlabel: \"Replay desktop actions\",\n\t\t\tdescription:\n\t\t\t\t\"Replay a bounded sequence of desktop actions against one session; stops at the first failure, cancellation, or user-confirmation pause by default. Recorded foreground type/key entries may omit the target\",\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tsessionId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\tactions: Type.Array(\n\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: Type.Union([\n\t\t\t\t\t\t\t\t\tType.Literal(\"focus\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"click\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"type\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"key\"),\n\t\t\t\t\t\t\t\t\tType.Literal(\"scroll\"),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t// Optional for type/key (foreground replay entries); the per-kind\n\t\t\t\t\t\t\t\t// rule is enforced by desktopReplayActionInput, not by this schema.\n\t\t\t\t\t\t\t\ttarget: Type.Optional(\n\t\t\t\t\t\t\t\t\tType.Union([\n\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"window\"),\n\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tType.Object(\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tkind: Type.Literal(\"control\"),\n\t\t\t\t\t\t\t\t\t\t\t\tcontrolId: Type.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\twindowId: Type.Optional(\n\t\t\t\t\t\t\t\t\t\t\t\t\tType.String({ minLength: 1, maxLength: DESKTOP_MAX_STRING_CHARS_V1 }),\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\ttext: Type.Optional(Type.String({ maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t\tkey: Type.Optional(Type.String({ minLength: 1, maxLength: DESKTOP_MAX_TYPE_TEXT_CHARS_V1 })),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ additionalProperties: false },\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{ minItems: 1, maxItems: DESKTOP_MAX_REPLAY_ACTIONS_V1 },\n\t\t\t\t\t),\n\t\t\t\t\tstopOnFailure: Type.Optional(Type.Boolean()),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tconst { input, operationId } = toolInvocation(first, second);\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted)\n\t\t\t\t\treturn desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\");\n\t\t\t\tlet request: DesktopReplayRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\trequest = desktopReplayRequest(input, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_input_invalid\", \"Desktop replay input is invalid\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst result = replay(request);\n\t\t\t\t\treturn signal?.aborted\n\t\t\t\t\t\t? desktopFailure(operationId, \"cancelled\", \"Desktop operation was cancelled\", \"cancelled\")\n\t\t\t\t\t\t: desktopReplayResult(result, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn desktopFailure(operationId, \"desktop_adapter_failed\", \"The selected desktop adapter failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
|