@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.
- package/README.md +157 -0
- package/dist/action/client.d.ts +13 -0
- package/dist/action/client.d.ts.map +1 -0
- package/dist/action/client.js +28 -0
- package/dist/action/client.js.map +1 -0
- package/dist/action/mcp-content.d.ts +2 -0
- package/dist/action/mcp-content.d.ts.map +1 -0
- package/dist/action/mcp-content.js +116 -0
- package/dist/action/mcp-content.js.map +1 -0
- package/dist/action/protocol.d.ts +36 -0
- package/dist/action/protocol.d.ts.map +1 -0
- package/dist/action/protocol.js +29 -0
- package/dist/action/protocol.js.map +1 -0
- package/dist/assets/contracts/app-list.schema.json +31 -0
- package/dist/assets/contracts/app-upload.schema.json +45 -0
- package/dist/assets/contracts/app.schema.json +18 -0
- package/dist/assets/contracts/authoring-attempt-create.schema.json +12 -0
- package/dist/assets/contracts/authoring-attempt.schema.json +56 -0
- package/dist/assets/contracts/authoring-complete.schema.json +13 -0
- package/dist/assets/contracts/authoring-draft-attempt-create.schema.json +12 -0
- package/dist/assets/contracts/authoring-observation.schema.json +28 -0
- package/dist/assets/contracts/authoring-revision-create.schema.json +13 -0
- package/dist/assets/contracts/authoring-revision.schema.json +19 -0
- package/dist/assets/contracts/authoring-session-create.schema.json +11 -0
- package/dist/assets/contracts/authoring-session.schema.json +54 -0
- package/dist/assets/contracts/canonical-script.schema.json +219 -0
- package/dist/assets/contracts/compat-script.schema.json +380 -0
- package/dist/assets/contracts/device-list.schema.json +19 -0
- package/dist/assets/contracts/error.schema.json +47 -0
- package/dist/assets/contracts/execution-target.schema.json +55 -0
- package/dist/assets/contracts/fixtures/authoring-attempt-create.valid.json +4 -0
- package/dist/assets/contracts/fixtures/authoring-attempt.passed.json +16 -0
- package/dist/assets/contracts/fixtures/authoring-draft-attempt-create.valid.json +10 -0
- package/dist/assets/contracts/fixtures/authoring-observation.valid.json +7 -0
- package/dist/assets/contracts/fixtures/authoring-revision.valid.json +16 -0
- package/dist/assets/contracts/fixtures/authoring-session.active.json +12 -0
- package/dist/assets/contracts/fixtures/canonical-script.valid.json +17 -0
- package/dist/assets/contracts/fixtures/ci-exit-status-cases.json +44 -0
- package/dist/assets/contracts/fixtures/command-mutual-exclusion-cases.json +20 -0
- package/dist/assets/contracts/fixtures/compat-script.all-platform-actions.yaml +227 -0
- package/dist/assets/contracts/fixtures/execution-target.both.invalid.json +7 -0
- package/dist/assets/contracts/fixtures/execution-target.concurrency-two.invalid.json +4 -0
- package/dist/assets/contracts/fixtures/execution-target.count-two.invalid.json +6 -0
- package/dist/assets/contracts/fixtures/execution-target.dynamic.valid.json +12 -0
- package/dist/assets/contracts/fixtures/execution-target.fixed.valid.json +4 -0
- package/dist/assets/contracts/fixtures/execution-target.multiple-devices.invalid.json +4 -0
- package/dist/assets/contracts/fixtures/execution-target.multiple-filters.invalid.json +7 -0
- package/dist/assets/contracts/fixtures/execution-target.strategy-all.invalid.json +6 -0
- package/dist/assets/contracts/fixtures/idempotency.conflict.json +26 -0
- package/dist/assets/contracts/fixtures/idempotency.same-request.json +26 -0
- package/dist/assets/contracts/fixtures/principal.personal.json +23 -0
- package/dist/assets/contracts/fixtures/principal.project-ci.json +20 -0
- package/dist/assets/contracts/fixtures/project-config.no-default.valid.json +9 -0
- package/dist/assets/contracts/fixtures/project-config.secret.invalid.json +10 -0
- package/dist/assets/contracts/fixtures/project-config.target-name.invalid.json +10 -0
- package/dist/assets/contracts/fixtures/project-config.valid.json +22 -0
- package/dist/assets/contracts/fixtures/public-script.all-cli-actions.yaml +39 -0
- package/dist/assets/contracts/fixtures/public-script.invalid.json +8 -0
- package/dist/assets/contracts/fixtures/public-script.valid.json +17 -0
- package/dist/assets/contracts/fixtures/run-create-v2.device-id.invalid.json +16 -0
- package/dist/assets/contracts/fixtures/run-create.personal-upload.valid.json +20 -0
- package/dist/assets/contracts/fixtures/run-create.single-device.json +19 -0
- package/dist/assets/contracts/fixtures/run-create.target.valid.json +22 -0
- package/dist/assets/contracts/fixtures/run.queued.json +19 -0
- package/dist/assets/contracts/fixtures/run.target.queued.json +38 -0
- package/dist/assets/contracts/fixtures/skill-catalog.valid.json +19 -0
- package/dist/assets/contracts/fixtures/skill-reference.valid.json +9 -0
- package/dist/assets/contracts/fixtures/skill.valid.json +10 -0
- package/dist/assets/contracts/fixtures/target-hash-cases.json +30 -0
- package/dist/assets/contracts/fixtures/target-preview.hash-mismatch.error.json +8 -0
- package/dist/assets/contracts/fixtures/target-preview.no-match.error.json +9 -0
- package/dist/assets/contracts/fixtures/target-preview.request.valid.json +9 -0
- package/dist/assets/contracts/fixtures/target-preview.success.json +18 -0
- package/dist/assets/contracts/fixtures/target-preview.unavailable.json +18 -0
- package/dist/assets/contracts/principal.schema.json +72 -0
- package/dist/assets/contracts/project-config.schema.json +23 -0
- package/dist/assets/contracts/public-script.schema.json +397 -0
- package/dist/assets/contracts/run-create-v2.schema.json +78 -0
- package/dist/assets/contracts/run-create.schema.json +70 -0
- package/dist/assets/contracts/run.schema.json +137 -0
- package/dist/assets/contracts/skill-catalog.schema.json +15 -0
- package/dist/assets/contracts/skill-reference.schema.json +17 -0
- package/dist/assets/contracts/skill-summary.schema.json +28 -0
- package/dist/assets/contracts/skill.schema.json +30 -0
- package/dist/assets/contracts/target-preview.schema.json +75 -0
- package/dist/assets/integrations/manifest.json +17 -0
- package/dist/assets/integrations/xagent-skill/SKILL.md +28 -0
- package/dist/assets/integrations/xagent-skill/agents/openai.yaml +4 -0
- package/dist/assets/integrations/xagent-skill/references/cli-mcp-interop.md +10 -0
- package/dist/assets/integrations/xagent-skill/references/host-adapters.md +9 -0
- package/dist/assets/integrations/xagent-skill/references/installation.md +10 -0
- package/dist/assets/integrations/xagent-skill/references/privacy.md +3 -0
- package/dist/assets/integrations/xagent-skill/references/routing.md +32 -0
- package/dist/assets/integrations/xagent-skill/scripts/install-cli.ps1 +5 -0
- package/dist/assets/integrations/xagent-skill/scripts/install-cli.sh +6 -0
- package/dist/assets/skills/xagent-analyze-failure/SKILL.md +13 -0
- package/dist/assets/skills/xagent-analyze-failure/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-analyze-failure/references/failure-classification.md +20 -0
- package/dist/assets/skills/xagent-author-test/SKILL.md +19 -0
- package/dist/assets/skills/xagent-author-test/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-author-test/references/authoring-workflow.md +41 -0
- package/dist/assets/skills/xagent-author-test/references/host-interaction-adapters.md +81 -0
- package/dist/assets/skills/xagent-author-test/references/interaction-modes.md +97 -0
- package/dist/assets/skills/xagent-author-test/references/interactive-steering.md +57 -0
- package/dist/assets/skills/xagent-author-test/references/script-actions.md +34 -0
- package/dist/assets/skills/xagent-author-test/references/script-format.md +100 -0
- package/dist/assets/skills/xagent-cli/SKILL.md +31 -0
- package/dist/assets/skills/xagent-cli/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-cli/references/capability-routing.md +36 -0
- package/dist/assets/skills/xagent-cli/references/cli-commands.md +23 -0
- package/dist/assets/skills/xagent-cli/references/failure-routing.md +18 -0
- package/dist/assets/skills/xagent-cli/references/host-modes.md +21 -0
- package/dist/assets/skills/xagent-cli/references/mcp-tools.md +26 -0
- package/dist/assets/skills/xagent-cli/references/permissions.md +17 -0
- package/dist/assets/skills/xagent-explore-device/SKILL.md +26 -0
- package/dist/assets/skills/xagent-explore-device/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-explore-device/references/actions.md +24 -0
- package/dist/assets/skills/xagent-explore-device/references/single-action-protocol.md +59 -0
- package/dist/assets/skills/xagent-explore-device/references/tool-adapters.md +32 -0
- package/dist/assets/skills/xagent-repair-test/SKILL.md +16 -0
- package/dist/assets/skills/xagent-repair-test/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-repair-test/references/repair-workflow.md +21 -0
- package/dist/assets/skills/xagent-run-test/SKILL.md +16 -0
- package/dist/assets/skills/xagent-run-test/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-run-test/references/execution-modes.md +23 -0
- package/dist/assets/skills/xagent-run-test/references/result-status.md +13 -0
- package/dist/assets/skills/xagent-test-report/SKILL.md +20 -0
- package/dist/assets/skills/xagent-test-report/agents/openai.yaml +4 -0
- package/dist/assets/skills/xagent-test-report/references/evidence-policy.md +20 -0
- package/dist/assets/skills/xagent-test-report/references/report-template.md +41 -0
- package/dist/assets/skills/xagent-test-report/references/result-classification.md +13 -0
- package/dist/authoring/draft-store.d.ts +19 -0
- package/dist/authoring/draft-store.d.ts.map +1 -0
- package/dist/authoring/draft-store.js +104 -0
- package/dist/authoring/draft-store.js.map +1 -0
- package/dist/authoring/session-lease.d.ts +64 -0
- package/dist/authoring/session-lease.d.ts.map +1 -0
- package/dist/authoring/session-lease.js +190 -0
- package/dist/authoring/session-lease.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +529 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/credentials.d.ts +16 -0
- package/dist/config/credentials.d.ts.map +1 -0
- package/dist/config/credentials.js +93 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/store.d.ts +37 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +142 -0
- package/dist/config/store.js.map +1 -0
- package/dist/core/assets.d.ts +5 -0
- package/dist/core/assets.d.ts.map +1 -0
- package/dist/core/assets.js +46 -0
- package/dist/core/assets.js.map +1 -0
- package/dist/core/errors.d.ts +19 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +36 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/interrupt.d.ts +8 -0
- package/dist/core/interrupt.d.ts.map +1 -0
- package/dist/core/interrupt.js +54 -0
- package/dist/core/interrupt.js.map +1 -0
- package/dist/core/json.d.ts +5 -0
- package/dist/core/json.d.ts.map +1 -0
- package/dist/core/json.js +21 -0
- package/dist/core/json.js.map +1 -0
- package/dist/core/version.d.ts +8 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +8 -0
- package/dist/core/version.js.map +1 -0
- package/dist/integrations/manager.d.ts +12 -0
- package/dist/integrations/manager.d.ts.map +1 -0
- package/dist/integrations/manager.js +218 -0
- package/dist/integrations/manager.js.map +1 -0
- package/dist/integrations/routing.d.ts +105 -0
- package/dist/integrations/routing.d.ts.map +1 -0
- package/dist/integrations/routing.js +85 -0
- package/dist/integrations/routing.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +69 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +30 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +345 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/project/config.d.ts +15 -0
- package/dist/project/config.d.ts.map +1 -0
- package/dist/project/config.js +46 -0
- package/dist/project/config.js.map +1 -0
- package/dist/run/progress.d.ts +5 -0
- package/dist/run/progress.d.ts.map +1 -0
- package/dist/run/progress.js +29 -0
- package/dist/run/progress.js.map +1 -0
- package/dist/script/service.d.ts +42 -0
- package/dist/script/service.d.ts.map +1 -0
- package/dist/script/service.js +457 -0
- package/dist/script/service.js.map +1 -0
- package/dist/sdk/authoring.d.ts +19 -0
- package/dist/sdk/authoring.d.ts.map +1 -0
- package/dist/sdk/authoring.js +43 -0
- package/dist/sdk/authoring.js.map +1 -0
- package/dist/sdk/client.d.ts +49 -0
- package/dist/sdk/client.d.ts.map +1 -0
- package/dist/sdk/client.js +241 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/skills/catalog.d.ts +7 -0
- package/dist/skills/catalog.d.ts.map +1 -0
- package/dist/skills/catalog.js +59 -0
- package/dist/skills/catalog.js.map +1 -0
- 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 @@
|
|
|
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
|
+
}
|