@testin-official/xagent 0.3.7

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.
Files changed (212) hide show
  1. package/README.md +157 -0
  2. package/dist/action/client.d.ts +13 -0
  3. package/dist/action/client.d.ts.map +1 -0
  4. package/dist/action/client.js +28 -0
  5. package/dist/action/client.js.map +1 -0
  6. package/dist/action/mcp-content.d.ts +2 -0
  7. package/dist/action/mcp-content.d.ts.map +1 -0
  8. package/dist/action/mcp-content.js +116 -0
  9. package/dist/action/mcp-content.js.map +1 -0
  10. package/dist/action/protocol.d.ts +36 -0
  11. package/dist/action/protocol.d.ts.map +1 -0
  12. package/dist/action/protocol.js +29 -0
  13. package/dist/action/protocol.js.map +1 -0
  14. package/dist/assets/contracts/app-list.schema.json +31 -0
  15. package/dist/assets/contracts/app-upload.schema.json +45 -0
  16. package/dist/assets/contracts/app.schema.json +18 -0
  17. package/dist/assets/contracts/authoring-attempt-create.schema.json +12 -0
  18. package/dist/assets/contracts/authoring-attempt.schema.json +56 -0
  19. package/dist/assets/contracts/authoring-complete.schema.json +13 -0
  20. package/dist/assets/contracts/authoring-draft-attempt-create.schema.json +12 -0
  21. package/dist/assets/contracts/authoring-observation.schema.json +28 -0
  22. package/dist/assets/contracts/authoring-revision-create.schema.json +13 -0
  23. package/dist/assets/contracts/authoring-revision.schema.json +19 -0
  24. package/dist/assets/contracts/authoring-session-create.schema.json +11 -0
  25. package/dist/assets/contracts/authoring-session.schema.json +54 -0
  26. package/dist/assets/contracts/canonical-script.schema.json +219 -0
  27. package/dist/assets/contracts/compat-script.schema.json +380 -0
  28. package/dist/assets/contracts/device-list.schema.json +19 -0
  29. package/dist/assets/contracts/error.schema.json +47 -0
  30. package/dist/assets/contracts/execution-target.schema.json +55 -0
  31. package/dist/assets/contracts/fixtures/authoring-attempt-create.valid.json +4 -0
  32. package/dist/assets/contracts/fixtures/authoring-attempt.passed.json +16 -0
  33. package/dist/assets/contracts/fixtures/authoring-draft-attempt-create.valid.json +10 -0
  34. package/dist/assets/contracts/fixtures/authoring-observation.valid.json +7 -0
  35. package/dist/assets/contracts/fixtures/authoring-revision.valid.json +16 -0
  36. package/dist/assets/contracts/fixtures/authoring-session.active.json +12 -0
  37. package/dist/assets/contracts/fixtures/canonical-script.valid.json +17 -0
  38. package/dist/assets/contracts/fixtures/ci-exit-status-cases.json +44 -0
  39. package/dist/assets/contracts/fixtures/command-mutual-exclusion-cases.json +20 -0
  40. package/dist/assets/contracts/fixtures/compat-script.all-platform-actions.yaml +227 -0
  41. package/dist/assets/contracts/fixtures/execution-target.both.invalid.json +7 -0
  42. package/dist/assets/contracts/fixtures/execution-target.concurrency-two.invalid.json +4 -0
  43. package/dist/assets/contracts/fixtures/execution-target.count-two.invalid.json +6 -0
  44. package/dist/assets/contracts/fixtures/execution-target.dynamic.valid.json +12 -0
  45. package/dist/assets/contracts/fixtures/execution-target.fixed.valid.json +4 -0
  46. package/dist/assets/contracts/fixtures/execution-target.multiple-devices.invalid.json +4 -0
  47. package/dist/assets/contracts/fixtures/execution-target.multiple-filters.invalid.json +7 -0
  48. package/dist/assets/contracts/fixtures/execution-target.strategy-all.invalid.json +6 -0
  49. package/dist/assets/contracts/fixtures/idempotency.conflict.json +26 -0
  50. package/dist/assets/contracts/fixtures/idempotency.same-request.json +26 -0
  51. package/dist/assets/contracts/fixtures/principal.personal.json +23 -0
  52. package/dist/assets/contracts/fixtures/principal.project-ci.json +20 -0
  53. package/dist/assets/contracts/fixtures/project-config.no-default.valid.json +9 -0
  54. package/dist/assets/contracts/fixtures/project-config.secret.invalid.json +10 -0
  55. package/dist/assets/contracts/fixtures/project-config.target-name.invalid.json +10 -0
  56. package/dist/assets/contracts/fixtures/project-config.valid.json +22 -0
  57. package/dist/assets/contracts/fixtures/public-script.all-cli-actions.yaml +39 -0
  58. package/dist/assets/contracts/fixtures/public-script.invalid.json +8 -0
  59. package/dist/assets/contracts/fixtures/public-script.valid.json +17 -0
  60. package/dist/assets/contracts/fixtures/run-create-v2.device-id.invalid.json +16 -0
  61. package/dist/assets/contracts/fixtures/run-create.personal-upload.valid.json +20 -0
  62. package/dist/assets/contracts/fixtures/run-create.single-device.json +19 -0
  63. package/dist/assets/contracts/fixtures/run-create.target.valid.json +22 -0
  64. package/dist/assets/contracts/fixtures/run.queued.json +19 -0
  65. package/dist/assets/contracts/fixtures/run.target.queued.json +38 -0
  66. package/dist/assets/contracts/fixtures/skill-catalog.valid.json +19 -0
  67. package/dist/assets/contracts/fixtures/skill-reference.valid.json +9 -0
  68. package/dist/assets/contracts/fixtures/skill.valid.json +10 -0
  69. package/dist/assets/contracts/fixtures/target-hash-cases.json +30 -0
  70. package/dist/assets/contracts/fixtures/target-preview.hash-mismatch.error.json +8 -0
  71. package/dist/assets/contracts/fixtures/target-preview.no-match.error.json +9 -0
  72. package/dist/assets/contracts/fixtures/target-preview.request.valid.json +9 -0
  73. package/dist/assets/contracts/fixtures/target-preview.success.json +18 -0
  74. package/dist/assets/contracts/fixtures/target-preview.unavailable.json +18 -0
  75. package/dist/assets/contracts/principal.schema.json +72 -0
  76. package/dist/assets/contracts/project-config.schema.json +23 -0
  77. package/dist/assets/contracts/public-script.schema.json +397 -0
  78. package/dist/assets/contracts/run-create-v2.schema.json +78 -0
  79. package/dist/assets/contracts/run-create.schema.json +70 -0
  80. package/dist/assets/contracts/run.schema.json +137 -0
  81. package/dist/assets/contracts/skill-catalog.schema.json +15 -0
  82. package/dist/assets/contracts/skill-reference.schema.json +17 -0
  83. package/dist/assets/contracts/skill-summary.schema.json +28 -0
  84. package/dist/assets/contracts/skill.schema.json +30 -0
  85. package/dist/assets/contracts/target-preview.schema.json +75 -0
  86. package/dist/assets/integrations/manifest.json +17 -0
  87. package/dist/assets/integrations/xagent-skill/SKILL.md +28 -0
  88. package/dist/assets/integrations/xagent-skill/agents/openai.yaml +4 -0
  89. package/dist/assets/integrations/xagent-skill/references/cli-mcp-interop.md +10 -0
  90. package/dist/assets/integrations/xagent-skill/references/host-adapters.md +9 -0
  91. package/dist/assets/integrations/xagent-skill/references/installation.md +10 -0
  92. package/dist/assets/integrations/xagent-skill/references/privacy.md +3 -0
  93. package/dist/assets/integrations/xagent-skill/references/routing.md +32 -0
  94. package/dist/assets/integrations/xagent-skill/scripts/install-cli.ps1 +5 -0
  95. package/dist/assets/integrations/xagent-skill/scripts/install-cli.sh +6 -0
  96. package/dist/assets/skills/xagent-analyze-failure/SKILL.md +13 -0
  97. package/dist/assets/skills/xagent-analyze-failure/agents/openai.yaml +4 -0
  98. package/dist/assets/skills/xagent-analyze-failure/references/failure-classification.md +20 -0
  99. package/dist/assets/skills/xagent-author-test/SKILL.md +19 -0
  100. package/dist/assets/skills/xagent-author-test/agents/openai.yaml +4 -0
  101. package/dist/assets/skills/xagent-author-test/references/authoring-workflow.md +41 -0
  102. package/dist/assets/skills/xagent-author-test/references/host-interaction-adapters.md +81 -0
  103. package/dist/assets/skills/xagent-author-test/references/interaction-modes.md +97 -0
  104. package/dist/assets/skills/xagent-author-test/references/interactive-steering.md +57 -0
  105. package/dist/assets/skills/xagent-author-test/references/script-actions.md +34 -0
  106. package/dist/assets/skills/xagent-author-test/references/script-format.md +100 -0
  107. package/dist/assets/skills/xagent-cli/SKILL.md +31 -0
  108. package/dist/assets/skills/xagent-cli/agents/openai.yaml +4 -0
  109. package/dist/assets/skills/xagent-cli/references/capability-routing.md +36 -0
  110. package/dist/assets/skills/xagent-cli/references/cli-commands.md +23 -0
  111. package/dist/assets/skills/xagent-cli/references/failure-routing.md +18 -0
  112. package/dist/assets/skills/xagent-cli/references/host-modes.md +21 -0
  113. package/dist/assets/skills/xagent-cli/references/mcp-tools.md +26 -0
  114. package/dist/assets/skills/xagent-cli/references/permissions.md +17 -0
  115. package/dist/assets/skills/xagent-explore-device/SKILL.md +26 -0
  116. package/dist/assets/skills/xagent-explore-device/agents/openai.yaml +4 -0
  117. package/dist/assets/skills/xagent-explore-device/references/actions.md +24 -0
  118. package/dist/assets/skills/xagent-explore-device/references/single-action-protocol.md +59 -0
  119. package/dist/assets/skills/xagent-explore-device/references/tool-adapters.md +32 -0
  120. package/dist/assets/skills/xagent-repair-test/SKILL.md +16 -0
  121. package/dist/assets/skills/xagent-repair-test/agents/openai.yaml +4 -0
  122. package/dist/assets/skills/xagent-repair-test/references/repair-workflow.md +21 -0
  123. package/dist/assets/skills/xagent-run-test/SKILL.md +16 -0
  124. package/dist/assets/skills/xagent-run-test/agents/openai.yaml +4 -0
  125. package/dist/assets/skills/xagent-run-test/references/execution-modes.md +23 -0
  126. package/dist/assets/skills/xagent-run-test/references/result-status.md +13 -0
  127. package/dist/assets/skills/xagent-test-report/SKILL.md +20 -0
  128. package/dist/assets/skills/xagent-test-report/agents/openai.yaml +4 -0
  129. package/dist/assets/skills/xagent-test-report/references/evidence-policy.md +20 -0
  130. package/dist/assets/skills/xagent-test-report/references/report-template.md +41 -0
  131. package/dist/assets/skills/xagent-test-report/references/result-classification.md +13 -0
  132. package/dist/authoring/draft-store.d.ts +19 -0
  133. package/dist/authoring/draft-store.d.ts.map +1 -0
  134. package/dist/authoring/draft-store.js +104 -0
  135. package/dist/authoring/draft-store.js.map +1 -0
  136. package/dist/authoring/session-lease.d.ts +64 -0
  137. package/dist/authoring/session-lease.d.ts.map +1 -0
  138. package/dist/authoring/session-lease.js +190 -0
  139. package/dist/authoring/session-lease.js.map +1 -0
  140. package/dist/cli.d.ts +3 -0
  141. package/dist/cli.d.ts.map +1 -0
  142. package/dist/cli.js +529 -0
  143. package/dist/cli.js.map +1 -0
  144. package/dist/config/credentials.d.ts +16 -0
  145. package/dist/config/credentials.d.ts.map +1 -0
  146. package/dist/config/credentials.js +93 -0
  147. package/dist/config/credentials.js.map +1 -0
  148. package/dist/config/store.d.ts +37 -0
  149. package/dist/config/store.d.ts.map +1 -0
  150. package/dist/config/store.js +142 -0
  151. package/dist/config/store.js.map +1 -0
  152. package/dist/core/assets.d.ts +5 -0
  153. package/dist/core/assets.d.ts.map +1 -0
  154. package/dist/core/assets.js +46 -0
  155. package/dist/core/assets.js.map +1 -0
  156. package/dist/core/errors.d.ts +19 -0
  157. package/dist/core/errors.d.ts.map +1 -0
  158. package/dist/core/errors.js +36 -0
  159. package/dist/core/errors.js.map +1 -0
  160. package/dist/core/interrupt.d.ts +8 -0
  161. package/dist/core/interrupt.d.ts.map +1 -0
  162. package/dist/core/interrupt.js +54 -0
  163. package/dist/core/interrupt.js.map +1 -0
  164. package/dist/core/json.d.ts +5 -0
  165. package/dist/core/json.d.ts.map +1 -0
  166. package/dist/core/json.js +21 -0
  167. package/dist/core/json.js.map +1 -0
  168. package/dist/core/version.d.ts +8 -0
  169. package/dist/core/version.d.ts.map +1 -0
  170. package/dist/core/version.js +8 -0
  171. package/dist/core/version.js.map +1 -0
  172. package/dist/integrations/manager.d.ts +12 -0
  173. package/dist/integrations/manager.d.ts.map +1 -0
  174. package/dist/integrations/manager.js +218 -0
  175. package/dist/integrations/manager.js.map +1 -0
  176. package/dist/integrations/routing.d.ts +105 -0
  177. package/dist/integrations/routing.d.ts.map +1 -0
  178. package/dist/integrations/routing.js +85 -0
  179. package/dist/integrations/routing.js.map +1 -0
  180. package/dist/mcp/server.d.ts +4 -0
  181. package/dist/mcp/server.d.ts.map +1 -0
  182. package/dist/mcp/server.js +69 -0
  183. package/dist/mcp/server.js.map +1 -0
  184. package/dist/mcp/tools.d.ts +30 -0
  185. package/dist/mcp/tools.d.ts.map +1 -0
  186. package/dist/mcp/tools.js +345 -0
  187. package/dist/mcp/tools.js.map +1 -0
  188. package/dist/project/config.d.ts +15 -0
  189. package/dist/project/config.d.ts.map +1 -0
  190. package/dist/project/config.js +46 -0
  191. package/dist/project/config.js.map +1 -0
  192. package/dist/run/progress.d.ts +5 -0
  193. package/dist/run/progress.d.ts.map +1 -0
  194. package/dist/run/progress.js +29 -0
  195. package/dist/run/progress.js.map +1 -0
  196. package/dist/script/service.d.ts +42 -0
  197. package/dist/script/service.d.ts.map +1 -0
  198. package/dist/script/service.js +457 -0
  199. package/dist/script/service.js.map +1 -0
  200. package/dist/sdk/authoring.d.ts +19 -0
  201. package/dist/sdk/authoring.d.ts.map +1 -0
  202. package/dist/sdk/authoring.js +43 -0
  203. package/dist/sdk/authoring.js.map +1 -0
  204. package/dist/sdk/client.d.ts +49 -0
  205. package/dist/sdk/client.d.ts.map +1 -0
  206. package/dist/sdk/client.js +241 -0
  207. package/dist/sdk/client.js.map +1 -0
  208. package/dist/skills/catalog.d.ts +7 -0
  209. package/dist/skills/catalog.d.ts.map +1 -0
  210. package/dist/skills/catalog.js +59 -0
  211. package/dist/skills/catalog.js.map +1 -0
  212. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # XAgent CLI
2
+
3
+ XAgent CLI is the local client for the XAgent Developer Public API. It runs on developer machines and CI runners; it is not a second cloud task service.
4
+
5
+ ## Component boundary
6
+
7
+ ```text
8
+ Local terminal / CI / local Agent
9
+ -> xagent CLI and MCP
10
+ -> HTTPS Developer Public API
11
+ -> test-agent-service
12
+ -> Redis / Go exec / cloud device
13
+ ```
14
+
15
+ This repository owns local commands, Profile and credential handling, local YAML validation, the shared HTTP SDK, machine-readable output, exit codes, MCP adapters, packaging, and release artifacts. It must not import Flask applications, server DAOs, Redis clients, task services, or device-internal protocols.
16
+
17
+ The server repository `D:\Py\test-agent-service` owns authentication authority, Developer Token storage, Principal resolution, public API routes, resource authorization, Run orchestration, task dispatch, persistence, and report mapping. The Go executor repository `D:\Py\exec` owns strict consumption of the agreed queue protocol.
18
+
19
+ ## Current source layout
20
+
21
+ ```text
22
+ src/ TypeScript CLI, SDK, MCP, Script and local Draft implementation
23
+ tests/ contract, stdio and behavior tests
24
+ contracts/ synchronized public contract snapshot
25
+ skills/ packaged Skill documents and References
26
+ ```
27
+
28
+ The authoritative public contract is maintained in `D:\Py\test-agent-service\contracts\developer\v1`. Files under this repository's `contracts/` directory are release inputs synchronized from that source; client agents must not change their semantics independently.
29
+
30
+ The cross-component product and system design documents remain under `D:\Py\test-agent-service-dev1.1\docs\xagent-cli`; its repository-routing table determines which project each implementation task may modify.
31
+
32
+ ## Run scripts
33
+
34
+ Personal Runs use `package_id` from YAML or `--package-id` to select an existing
35
+ platform APK. Project CI Runs can instead upload the APK built from the current
36
+ commit and pass the returned temporary ID to `run`.
37
+
38
+ ```powershell
39
+ xagent run D:\Py\xagent-cli\examples\existing-app-smoke.yaml --device-id DEVICE_ID
40
+ xagent run D:\Py\xagent-cli\examples\smoke.yaml --device-id DEVICE_ID
41
+ xagent run D:\Py\xagent-cli\examples\smoke.yaml --package-id OTHER_PACKAGE_ID --device-id DEVICE_ID
42
+ ```
43
+
44
+ Project CI flow:
45
+
46
+ ```powershell
47
+ xagent init --base-url https://xagent.example --upload-base-url https://files.example --token-type project_ci --name ci --token-env XAGENT_CI_TOKEN
48
+ xagent --json --profile ci apps upload .\app-debug.apk
49
+ xagent --json --profile ci --config .\xagent.yaml run .\tests\smoke.yaml --target android-single --app-upload-id APP_UPLOAD_ID --idempotency-key PIPELINE_KEY --wait
50
+ xagent --json --profile ci apps release APP_UPLOAD_ID
51
+ ```
52
+
53
+ File-service upload requests default to a 15-minute timeout. Override it when needed with
54
+ `xagent apps upload .\app-debug.apk --upload-timeout 900` or
55
+ `xagent run tests\smoke.yaml --apk .\app-debug.apk --device-id DEVICE_001 --upload-timeout 900`.
56
+
57
+ `apps upload` and `apps release` require a newly issued `project_ci` Token with
58
+ the `app:upload` capability. One upload can be bound to one Run. Release is
59
+ idempotent and should run from CI cleanup (`after_script` / `finally`).
60
+ The Profile's `upload_base_url` points to the file service. The CLI sends the
61
+ same Developer Token only to `/app/ci/init`; chunk requests use a short-lived
62
+ upload ticket and never persist the Token in project files.
63
+
64
+ ## Development
65
+
66
+ The supported runtime and build path is Node.js 18 or later. No Python runtime,
67
+ PyInstaller or platform compiler is needed to build the customer package.
68
+
69
+ ```powershell
70
+ Set-Location D:\Py\xagent-cli
71
+ npm ci
72
+ npm run check
73
+ node .\dist\cli.js --json version
74
+ node .\dist\cli.js --json validate .\examples\smoke.yaml
75
+ npm pack --dry-run
76
+ ```
77
+
78
+ `npm run check` runs the synchronized contract fixtures, Target hash checks,
79
+ local Draft persistence tests and a real MCP stdio `initialize` / `tools/list`
80
+ exchange.
81
+
82
+ ## npm installation
83
+
84
+ The customer-facing installation package is the single package `@testin-official/xagent`.
85
+ It contains the compiled TypeScript CLI, MCP server, synchronized public schemas,
86
+ Skills and References. It does not download a platform-specific binary package
87
+ and does not contain Python source.
88
+
89
+ ```text
90
+ npm install --global @testin-official/xagent
91
+ xagent --json version
92
+ ```
93
+
94
+ ## Agent Host Skill and routing
95
+
96
+ The npm package is the execution client. Customers also receive one complete
97
+ external `xagent-skill` directory that can be imported directly into an Agent
98
+ Host. It discovers XAgent and routes one request to one isolated MCP domain:
99
+
100
+ ```powershell
101
+ xagent integrations install codex
102
+ xagent integrations doctor --host codex
103
+ xagent --json integrations options
104
+ xagent --json integrations route author --profile personal
105
+ ```
106
+
107
+ The default `xagent-local` MCP remains `action`. It is a long-lived stateful
108
+ device-control process that owns the current device Session, screen evidence,
109
+ pre-action renewal checks, and graceful-shutdown release. An idle MCP process
110
+ does not renew a Session in the background. Do not replace it with setup mode.
111
+ The Skill must tell the user this default and present the behavior choices
112
+ before any side-effect route is selected.
113
+
114
+ The route is explicit and one-to-one:
115
+
116
+ ```text
117
+ setup -> mcp --mode setup -> xagent-cli
118
+ action -> mcp --mode action -> xagent-explore-device
119
+ author -> mcp --mode author -> xagent-author-test
120
+ run -> mcp --mode run -> xagent-run-test
121
+ analyze -> mcp --mode analyze -> xagent-analyze-failure
122
+ repair -> mcp --mode repair -> xagent-repair-test
123
+ report -> mcp --mode report -> xagent-test-report
124
+ ```
125
+
126
+ The same route is available without Shell through setup MCP's local
127
+ `xagent_workflow_route` Tool. Each MCP process exposes one domain only; changing
128
+ domains requires restarting it with the new explicit `--mode`. A mode can load
129
+ only its mapped Skill, and a failed Skill load must stop all device, upload,
130
+ Authoring, Run, and report side effects.
131
+
132
+ `xagent integrations install` writes only XAgent's own Skill files. It does
133
+ not overwrite an existing Host configuration or write Developer Tokens. The
134
+ integration package can be prepared for a market or GitLab Release with:
135
+
136
+ ```powershell
137
+ npm run package:integrations
138
+ ```
139
+
140
+ The generated versioned Skill directory and ZIP are under `release/` and are
141
+ intended to be published as static Release assets, not served by a runtime API.
142
+ The ZIP extracts with `SKILL.md` at its root. The npm package and the Skill ZIP
143
+ are separate artifacts: the former executes requests, while the latter is the
144
+ Agent Host entry and routing contract.
145
+
146
+ The same package runs on Windows, Linux and macOS on x64 or arm64 with Node.js 20.9
147
+ or later. Interactive saved credentials use the operating system credential
148
+ store through a prebuilt N-API adapter; CI Profiles continue to use explicitly
149
+ named environment variables. Downstream CI jobs install from npm and are never
150
+ granted permission to clone this repository.
151
+
152
+ GitLab runs the TypeScript tests and build once on Linux, then produces the same
153
+ npm tarball for every supported operating system. Publishing is manual and
154
+ requires a masked `NPM_TOKEN`; no Windows Runner is required.
155
+
156
+ Migration boundaries, Agent Host integration and platform limitations are
157
+ documented in `docs/typescript-migration.md`.
@@ -0,0 +1,13 @@
1
+ import type { XAgentClient } from "../sdk/client.js";
2
+ export declare class DeviceActionClient {
3
+ private readonly client;
4
+ constructor(client: XAgentClient);
5
+ acquireDevice(deviceId: string, idempotencyKey: string): Promise<Record<string, any>>;
6
+ getSession(sessionId: string): Promise<Record<string, any>>;
7
+ renewSession(sessionId: string): Promise<Record<string, any>>;
8
+ observe(sessionId: string): Promise<Record<string, any>>;
9
+ executeAction(sessionId: string, request: Record<string, unknown>, idempotencyKey: string): Promise<Record<string, any>>;
10
+ release(sessionId: string, idempotencyKey: string): Promise<Record<string, any>>;
11
+ cancel(sessionId: string, idempotencyKey: string): Promise<Record<string, any>>;
12
+ }
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/action/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IACjD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;IAGtD,UAAU,CAAC,SAAS,EAAE,MAAM;IAG5B,YAAY,CAAC,SAAS,EAAE,MAAM;IAG9B,OAAO,CAAC,SAAS,EAAE,MAAM;IAGzB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM;IAGzF,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;IAGjD,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;CAGjD"}
@@ -0,0 +1,28 @@
1
+ export class DeviceActionClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ acquireDevice(deviceId, idempotencyKey) {
7
+ return this.client.request("POST", "/agent/api/developer/v1/device-control/devices/acquire", { json: { device_id: deviceId }, idempotencyKey, timeoutMs: 90_000 });
8
+ }
9
+ getSession(sessionId) {
10
+ return this.client.request("GET", `/agent/api/developer/v1/device-control/sessions/${encodeURIComponent(sessionId)}`);
11
+ }
12
+ renewSession(sessionId) {
13
+ return this.client.request("POST", `/agent/api/developer/v1/device-control/sessions/${encodeURIComponent(sessionId)}/renew`, { json: {}, timeoutMs: 90_000 });
14
+ }
15
+ observe(sessionId) {
16
+ return this.client.request("GET", `/agent/api/developer/v1/device-control/sessions/${encodeURIComponent(sessionId)}/observe`, { timeoutMs: 90_000 });
17
+ }
18
+ executeAction(sessionId, request, idempotencyKey) {
19
+ return this.client.request("POST", `/agent/api/developer/v1/device-control/sessions/${encodeURIComponent(sessionId)}/actions`, { json: request, idempotencyKey, timeoutMs: 300_000 });
20
+ }
21
+ release(sessionId, idempotencyKey) {
22
+ return this.client.request("POST", `/agent/api/developer/v1/device-control/sessions/${encodeURIComponent(sessionId)}/release`, { json: {}, idempotencyKey, timeoutMs: 90_000 });
23
+ }
24
+ cancel(sessionId, idempotencyKey) {
25
+ return this.release(sessionId, idempotencyKey);
26
+ }
27
+ }
28
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/action/client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,kBAAkB;IACA;IAA7B,YAA6B,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;IAAG,CAAC;IACrD,aAAa,CAAC,QAAgB,EAAE,cAAsB;QACpD,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,wDAAwD,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IACrK,CAAC;IACD,UAAU,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,mDAAmD,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACxH,CAAC;IACD,YAAY,CAAC,SAAiB;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,mDAAmD,kBAAkB,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAChK,CAAC;IACD,OAAO,CAAC,SAAiB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,mDAAmD,kBAAkB,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IACvJ,CAAC;IACD,aAAa,CAAC,SAAiB,EAAE,OAAgC,EAAE,cAAsB;QACvF,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,mDAAmD,kBAAkB,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IACxL,CAAC;IACD,OAAO,CAAC,SAAiB,EAAE,cAAsB;QAC/C,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,mDAAmD,kBAAkB,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAClL,CAAC;IACD,MAAM,CAAC,SAAiB,EAAE,cAAsB;QAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare function actionMcpContent(toolName: string, result: Record<string, any>): Promise<Array<Record<string, string>>>;
2
+ //# sourceMappingURL=mcp-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-content.d.ts","sourceRoot":"","sources":["../../src/action/mcp-content.ts"],"names":[],"mappings":"AAkEA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CA8B5H"}
@@ -0,0 +1,116 @@
1
+ import { XAgentApiError } from "../core/errors.js";
2
+ import sharp from "sharp";
3
+ const MAX_IMAGE_BYTES = 15 * 1024 * 1024;
4
+ const MAX_MCP_IMAGE_BYTES = 200 * 1024;
5
+ const JPEG_QUALITIES = [82, 78, 74, 70, 66, 62, 58];
6
+ const IMAGE_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]);
7
+ function textFor(toolName, result) {
8
+ const consoleUrl = result.session?.console_url;
9
+ if (toolName === "xagent_device_acquire" && typeof consoleUrl === "string" && consoleUrl.trim()) {
10
+ return `Device observation console URL (valid for this Session): ${consoleUrl}\n${JSON.stringify(result)}`;
11
+ }
12
+ return JSON.stringify(result);
13
+ }
14
+ function observationFor(toolName, result) {
15
+ if (toolName === "xagent_device_acquire")
16
+ return result.observation;
17
+ if (toolName === "xagent_device_observe")
18
+ return result;
19
+ if (toolName === "xagent_device_action")
20
+ return result.after_observation ?? undefined;
21
+ return undefined;
22
+ }
23
+ function assertImageUrl(value) {
24
+ if (typeof value !== "string")
25
+ throw new XAgentApiError("invalid_response", "Device observation has no screenshot URL");
26
+ let url;
27
+ try {
28
+ url = new URL(value);
29
+ }
30
+ catch {
31
+ throw new XAgentApiError("invalid_response", "Device observation screenshot URL is invalid");
32
+ }
33
+ const localHttp = url.protocol === "http:" && ["localhost", "127.0.0.1", "::1"].includes(url.hostname);
34
+ if (url.protocol !== "https:" && !localHttp)
35
+ throw new XAgentApiError("invalid_response", "Device observation screenshot URL must use HTTPS");
36
+ return url;
37
+ }
38
+ async function prepareMcpImage(bytes, mimeType) {
39
+ if (bytes.length <= MAX_MCP_IMAGE_BYTES)
40
+ return { bytes, mimeType };
41
+ const pipeline = sharp(bytes, { failOn: "error", limitInputPixels: 100_000_000 })
42
+ .rotate()
43
+ .flatten({ background: "#ffffff" });
44
+ let smallest;
45
+ for (const quality of JPEG_QUALITIES) {
46
+ const candidate = await pipeline.clone().jpeg({ quality, mozjpeg: true }).toBuffer();
47
+ if (!smallest || candidate.length < smallest.length)
48
+ smallest = candidate;
49
+ if (candidate.length <= MAX_MCP_IMAGE_BYTES)
50
+ return { bytes: candidate, mimeType: "image/jpeg" };
51
+ }
52
+ const metadata = await pipeline.metadata();
53
+ let longestEdge = Math.max(metadata.width ?? 0, metadata.height ?? 0);
54
+ if (longestEdge < 1 || !smallest)
55
+ throw new XAgentApiError("invalid_response", "Device observation screenshot dimensions are invalid");
56
+ let candidate = smallest;
57
+ while (candidate.length > MAX_MCP_IMAGE_BYTES && longestEdge > 640) {
58
+ const ratio = Math.min(0.9, Math.sqrt(MAX_MCP_IMAGE_BYTES / candidate.length) * 0.95);
59
+ longestEdge = Math.max(640, Math.floor(longestEdge * ratio));
60
+ candidate = await pipeline.clone()
61
+ .resize({ width: longestEdge, height: longestEdge, fit: "inside", withoutEnlargement: true })
62
+ .jpeg({ quality: 72, mozjpeg: true })
63
+ .toBuffer();
64
+ }
65
+ if (candidate.length > MAX_MCP_IMAGE_BYTES) {
66
+ throw new XAgentApiError("invalid_response", "Device observation screenshot cannot be reduced to the MCP image limit");
67
+ }
68
+ return { bytes: candidate, mimeType: "image/jpeg" };
69
+ }
70
+ export async function actionMcpContent(toolName, result) {
71
+ const content = [{ type: "text", text: textFor(toolName, result) }];
72
+ const observation = observationFor(toolName, result);
73
+ if (!observation)
74
+ return content;
75
+ const url = assertImageUrl(observation.screenshot_url);
76
+ let response;
77
+ try {
78
+ response = await fetch(url, { signal: AbortSignal.timeout(30_000) });
79
+ }
80
+ catch (error) {
81
+ throw new XAgentApiError("infrastructure_failed", "Unable to fetch Device observation screenshot", { details: { cause: error instanceof Error ? error.message : String(error) } });
82
+ }
83
+ if (!response.ok)
84
+ throw new XAgentApiError("infrastructure_failed", `Device observation screenshot returned HTTP ${response.status}`);
85
+ const mimeType = String(response.headers.get("content-type") ?? "").split(";", 1)[0].toLowerCase();
86
+ if (!IMAGE_TYPES.has(mimeType))
87
+ throw new XAgentApiError("invalid_response", "Device observation screenshot is not an allowed image MIME type");
88
+ const length = Number(response.headers.get("content-length") ?? 0);
89
+ if (length > MAX_IMAGE_BYTES)
90
+ throw new XAgentApiError("invalid_response", "Device observation screenshot is too large");
91
+ const reader = response.body?.getReader();
92
+ if (!reader)
93
+ throw new XAgentApiError("invalid_response", "Device observation screenshot has no body");
94
+ const chunks = [];
95
+ let total = 0;
96
+ try {
97
+ for (;;) {
98
+ const next = await reader.read();
99
+ if (next.done)
100
+ break;
101
+ total += next.value.byteLength;
102
+ if (total > MAX_IMAGE_BYTES)
103
+ throw new XAgentApiError("invalid_response", "Device observation screenshot is too large");
104
+ chunks.push(next.value);
105
+ }
106
+ }
107
+ finally {
108
+ reader.releaseLock();
109
+ }
110
+ if (total === 0)
111
+ throw new XAgentApiError("invalid_response", "Device observation screenshot is empty");
112
+ const image = await prepareMcpImage(Buffer.concat(chunks.map((chunk) => Buffer.from(chunk))), mimeType);
113
+ content.push({ type: "image", data: image.bytes.toString("base64"), mimeType: image.mimeType });
114
+ return content;
115
+ }
116
+ //# sourceMappingURL=mcp-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-content.js","sourceRoot":"","sources":["../../src/action/mcp-content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export type ResolvedDeviceAction = Record<string, unknown> & {
2
+ action: string;
3
+ };
4
+ export type DeviceObservation = {
5
+ schema_version: "xagent-device-observation/v1";
6
+ screen_id: string;
7
+ session_id: string;
8
+ device_id: string;
9
+ screenshot_url: string;
10
+ mime_type: "image/png" | "image/jpeg" | "image/webp";
11
+ width: number;
12
+ height: number;
13
+ orientation: "portrait" | "landscape";
14
+ captured_at: string;
15
+ expires_at: string;
16
+ };
17
+ export type DeviceActionResult = {
18
+ schema_version: "xagent-device-action-result/v1";
19
+ session_id: string;
20
+ device_id: string;
21
+ screen_id: string;
22
+ status: "PASSED" | "FAILED" | "INFRASTRUCTURE_FAILED";
23
+ action: ResolvedDeviceAction;
24
+ result: {
25
+ success: boolean;
26
+ message: string;
27
+ data: unknown;
28
+ infrastructure_error?: string;
29
+ };
30
+ after_observation: DeviceObservation | null;
31
+ };
32
+ export declare function buildDeviceActionRequest(input: {
33
+ screenId?: unknown;
34
+ requestJson?: unknown;
35
+ }): Record<string, unknown>;
36
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/action/protocol.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAChF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,8BAA8B,CAAC;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,WAAW,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,cAAc,EAAE,gCAAgC,CAAC;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,uBAAuB,CAAC;IACtD,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5F,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC7C,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkBtH"}
@@ -0,0 +1,29 @@
1
+ import { CliError } from "../core/errors.js";
2
+ export function buildDeviceActionRequest(input) {
3
+ if (input.requestJson === undefined)
4
+ throw new CliError("invalid_request", "device action requires --request-json");
5
+ let parsed;
6
+ try {
7
+ parsed = JSON.parse(String(input.requestJson));
8
+ }
9
+ catch {
10
+ throw new CliError("invalid_request", "--request-json must be valid JSON");
11
+ }
12
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
13
+ throw new CliError("invalid_request", "--request-json must be a JSON object");
14
+ const object = parsed;
15
+ const embeddedScreen = typeof object.screen_id === "string" ? object.screen_id.trim() : "";
16
+ if (embeddedScreen && typeof input.screenId === "string" && input.screenId.trim() && embeddedScreen !== input.screenId.trim()) {
17
+ throw new CliError("invalid_request", "--screen-id does not match screen_id in --request-json");
18
+ }
19
+ const screenId = typeof input.screenId === "string" && input.screenId.trim() ? input.screenId.trim() : embeddedScreen;
20
+ const action = object.action && typeof object.action === "object" && !Array.isArray(object.action)
21
+ ? object.action
22
+ : object;
23
+ if (!screenId)
24
+ throw new CliError("invalid_request", "device action requires --screen-id or screen_id in --request-json");
25
+ if (typeof action.action !== "string" || !action.action.trim())
26
+ throw new CliError("invalid_request", "device action JSON must contain action");
27
+ return { screen_id: screenId, action };
28
+ }
29
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/action/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AA2B7C,MAAM,UAAU,wBAAwB,CAAC,KAAoD;IAC3F,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;QAAE,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,uCAAuC,CAAC,CAAC;IACpH,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAAC,CAAC;IACvD,MAAM,CAAC;QAAC,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,mCAAmC,CAAC,CAAC;IAAC,CAAC;IACrF,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,sCAAsC,CAAC,CAAC;IAClJ,MAAM,MAAM,GAAG,MAAiC,CAAC;IACjD,MAAM,cAAc,GAAG,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3F,IAAI,cAAc,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,cAAc,KAAK,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9H,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,wDAAwD,CAAC,CAAC;IAClG,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;IACtH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QAChG,CAAC,CAAC,MAAM,CAAC,MAAiC;QAC1C,CAAC,CAAC,MAAM,CAAC;IACX,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,mEAAmE,CAAC,CAAC;IAC1H,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,wCAAwC,CAAC,CAAC;IAChJ,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/contracts/developer/v1/app-list.schema.json",
4
+ "title": "XAgent Developer Application List",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schema_version", "apps", "page", "page_size", "total"],
8
+ "properties": {
9
+ "schema_version": {"const": "xagent-app-list/v1"},
10
+ "apps": {"type": "array", "items": {"$ref": "#/$defs/app"}},
11
+ "page": {"type": "integer", "minimum": 1},
12
+ "page_size": {"type": "integer", "minimum": 1, "maximum": 100},
13
+ "total": {"type": "integer", "minimum": 0}
14
+ },
15
+ "$defs": {
16
+ "app": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["package_id", "app_id", "name", "package_name", "version_name", "version_code", "launch_path"],
20
+ "properties": {
21
+ "package_id": {"type": "integer", "minimum": 1},
22
+ "app_id": {"type": ["integer", "null"], "minimum": 1},
23
+ "name": {"type": "string"},
24
+ "package_name": {"type": "string", "minLength": 1},
25
+ "version_name": {"type": "string"},
26
+ "version_code": {"type": "string"},
27
+ "launch_path": {"type": "string"}
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/schemas/developer/v1/app-upload.schema.json",
4
+ "title": "XAgent Temporary App Upload v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "id",
10
+ "package_id",
11
+ "status",
12
+ "file_name",
13
+ "sha256",
14
+ "size",
15
+ "app",
16
+ "expires_at"
17
+ ],
18
+ "properties": {
19
+ "schema_version": {"const": "xagent-app-upload/v1"},
20
+ "id": {"type": "string", "pattern": "^appup_[a-f0-9]{32}$"},
21
+ "package_id": {"type": "integer", "minimum": 1},
22
+ "status": {
23
+ "enum": ["active", "bound", "release_requested", "released", "expired"]
24
+ },
25
+ "file_name": {"type": "string", "minLength": 1, "maxLength": 512},
26
+ "sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
27
+ "size": {"type": "integer", "minimum": 1},
28
+ "app": {
29
+ "type": "object",
30
+ "additionalProperties": false,
31
+ "required": ["name", "package_name", "version_name", "version_code", "launch_path"],
32
+ "properties": {
33
+ "name": {"type": "string"},
34
+ "package_name": {"type": "string", "minLength": 1},
35
+ "version_name": {"type": "string"},
36
+ "version_code": {"type": "string"},
37
+ "launch_path": {"type": "string"}
38
+ }
39
+ },
40
+ "expires_at": {"type": "string", "format": "date-time"},
41
+ "bound_run_id": {"type": "string", "minLength": 1},
42
+ "release_requested_at": {"type": "string", "format": "date-time"},
43
+ "released_at": {"type": "string", "format": "date-time"}
44
+ }
45
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/contracts/developer/v1/app.schema.json",
4
+ "title": "XAgent Developer Application",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schema_version", "package_id", "app_id", "name", "package_name", "version_name", "version_code", "launch_path"],
8
+ "properties": {
9
+ "schema_version": {"const": "xagent-app/v1"},
10
+ "package_id": {"type": "integer", "minimum": 1},
11
+ "app_id": {"type": ["integer", "null"], "minimum": 1},
12
+ "name": {"type": "string"},
13
+ "package_name": {"type": "string", "minLength": 1},
14
+ "version_name": {"type": "string"},
15
+ "version_code": {"type": "string"},
16
+ "launch_path": {"type": "string"}
17
+ }
18
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/schemas/developer/v1/authoring-attempt-create.schema.json",
4
+ "title": "XAgent Authoring Attempt Create v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["revision_id", "step_index"],
8
+ "properties": {
9
+ "revision_id": {"type": "string", "pattern": "^rev_[a-f0-9]{32}$"},
10
+ "step_index": {"type": "integer", "minimum": 0}
11
+ }
12
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/schemas/developer/v1/authoring-attempt.schema.json",
4
+ "title": "XAgent Authoring Attempt v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["id", "schema_version", "session_id", "revision_id", "script_source", "script_hash", "step_index", "status", "started_at", "finished_at", "result", "artifacts"],
8
+ "properties": {
9
+ "id": {"type": "string", "pattern": "^attempt_[a-f0-9]{32}$"},
10
+ "schema_version": {"const": "xagent-authoring-attempt/v1"},
11
+ "session_id": {"type": "string", "pattern": "^auth_[a-f0-9]{32}$"},
12
+ "revision_id": {
13
+ "oneOf": [
14
+ {"type": "string", "pattern": "^rev_[a-f0-9]{32}$"},
15
+ {"type": "null"}
16
+ ]
17
+ },
18
+ "script_source": {"enum": ["revision", "draft"]},
19
+ "script_hash": {
20
+ "oneOf": [
21
+ {"type": "string", "pattern": "^[a-f0-9]{64}$"},
22
+ {"type": "null"}
23
+ ]
24
+ },
25
+ "step_index": {"type": "integer", "minimum": 0},
26
+ "status": {"enum": ["QUEUED", "RUNNING", "PASSED", "TEST_FAILED", "INFRASTRUCTURE_FAILED", "CANCELLED"]},
27
+ "started_at": {"type": ["string", "null"], "format": "date-time"},
28
+ "finished_at": {"type": ["string", "null"], "format": "date-time"},
29
+ "result": {"type": ["object", "null"]},
30
+ "artifacts": {
31
+ "type": "array",
32
+ "items": {
33
+ "type": "object",
34
+ "additionalProperties": false,
35
+ "required": ["type", "url"],
36
+ "properties": {
37
+ "type": {"type": "string", "minLength": 1, "maxLength": 64},
38
+ "url": {"type": "string", "format": "uri", "pattern": "^https://"}
39
+ }
40
+ }
41
+ },
42
+ "billing": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "required": ["status", "billable_minutes", "cost", "discount_rate", "started_at", "ended_at"],
46
+ "properties": {
47
+ "status": {"enum": ["pending", "submitting", "succeeded", "failed", "unknown"]},
48
+ "billable_minutes": {"type": "integer", "minimum": 0},
49
+ "cost": {"type": "integer", "minimum": 0},
50
+ "discount_rate": {"type": "number", "minimum": 0},
51
+ "started_at": {"type": ["string", "null"], "format": "date-time"},
52
+ "ended_at": {"type": ["string", "null"], "format": "date-time"}
53
+ }
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/schemas/developer/v1/authoring-complete.schema.json",
4
+ "title": "XAgent Authoring Complete Result v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["session", "revision", "yaml"],
8
+ "properties": {
9
+ "session": {"$ref": "authoring-session.schema.json"},
10
+ "revision": {"$ref": "authoring-revision.schema.json"},
11
+ "yaml": {"type": "string", "minLength": 1}
12
+ }
13
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://xagent.testin.cn/schemas/developer/v1/authoring-draft-attempt-create.schema.json",
4
+ "title": "XAgent Authoring Draft Attempt Create v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["script", "step_index"],
8
+ "properties": {
9
+ "script": {"$ref": "public-script.schema.json"},
10
+ "step_index": {"type": "integer", "minimum": 0}
11
+ }
12
+ }