@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
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Single-Action Protocol
|
|
2
|
+
|
|
3
|
+
## Responsibilities
|
|
4
|
+
|
|
5
|
+
The Agent reads the current image, grounds one action, and decides whether visible business behavior meets the user's request. MCP validates its typed Tool input, maintains the Session lease, returns structured errors, and attaches the screenshot as an image content block. The service validates the resolved action, enforces the current `screen_id` and idempotency contract, executes the device command, and captures the post-action observation.
|
|
6
|
+
|
|
7
|
+
No layer in this path invokes Exec, a GUI model, natural-language formatting, semantic target resolution, or fallback execution.
|
|
8
|
+
|
|
9
|
+
## State Machine
|
|
10
|
+
|
|
11
|
+
| Current state | Operation | Next state |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| No Session | Acquire one explicit device | Active Session plus initial `observation` |
|
|
14
|
+
| Readable observation | Submit one grounded action with its `screen_id` | Action result plus `after_observation` |
|
|
15
|
+
| Readable `after_observation` | Ground the next action or finish | No Observe call |
|
|
16
|
+
| Missing, unavailable, or genuinely ambiguous evidence | Observe once | Fresh observation and `screen_id` |
|
|
17
|
+
| Stale `screen_id` rejected before execution | Observe once, then re-ground the intended action | Fresh observation; do not reuse old coordinates |
|
|
18
|
+
| Session terminal or unrecoverable infrastructure failure | Stop | Release owned resources when possible |
|
|
19
|
+
|
|
20
|
+
Acquire combines Session allocation and the initial observation. Calling Observe immediately afterward duplicates the screenshot round trip and is forbidden when the acquired image is readable.
|
|
21
|
+
|
|
22
|
+
## Action Requests
|
|
23
|
+
|
|
24
|
+
Execution accepts `{ screen_id, action }`. Use a fresh idempotency key for each intended side effect. Reuse a key only when retrying the identical request after an uncertain transport outcome; changed content with the same key is a conflict.
|
|
25
|
+
|
|
26
|
+
Coordinates and bounds are normalized against the image associated with `screen_id`. Never use coordinates grounded from a platform console, another Session, or a manually changed device state.
|
|
27
|
+
|
|
28
|
+
A text action is shaped like:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"action": "type",
|
|
33
|
+
"content": "{{text}}"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Secure keyboard interpretation, semantic target selection, and completion decisions remain in the Agent. Application lifecycle actions use the verified fields in [actions.md](actions.md); installation accepts a project-scoped `app_upload_id` or `package_id`, never an arbitrary download URL.
|
|
38
|
+
|
|
39
|
+
## Result Evaluation
|
|
40
|
+
|
|
41
|
+
Evaluate one action result in this order:
|
|
42
|
+
|
|
43
|
+
1. Read `status`, `result.success`, and any structured error once. Do not revalidate the request schema or authentication in the Agent.
|
|
44
|
+
2. Use the attached `after_observation` image as the authoritative next visible state when it is readable.
|
|
45
|
+
3. For a business-critical action, compare that state with the postcondition derived before acting. Report confirmed only when the evidence proves it, failed when the evidence contradicts it, and inconclusive when it cannot decide.
|
|
46
|
+
4. For intermediate navigation, do not create an extra assertion cycle. Use the returned state directly to ground the next action.
|
|
47
|
+
|
|
48
|
+
`PASSED` proves only that the device command completed. It does not prove login, navigation, selection, input acceptance, or another business result.
|
|
49
|
+
|
|
50
|
+
## Recovery Rules
|
|
51
|
+
|
|
52
|
+
- `FAILED`: the device command reported failure. Use a readable `after_observation` to explain the state; do not Observe again unless the evidence itself is missing or ambiguous.
|
|
53
|
+
- `INFRASTRUCTURE_FAILED` with `result.success: true`: the side effect may have completed but post-action capture or upload failed. Observe once to recover the current state; never resubmit the side effect first.
|
|
54
|
+
- `INFRASTRUCTURE_FAILED` without command success: execution outcome is uncertain or failed. One Observe may establish the current state, but it does not authorize an automatic retry.
|
|
55
|
+
- Stale `screen_id`: Observe once, discard old coordinates, and ground again from the fresh image.
|
|
56
|
+
- Readable but ambiguous image: one Observe is permitted only when a fresh screen can reasonably resolve transient state. If it remains ambiguous, classify the result as inconclusive and stop.
|
|
57
|
+
- Session expiration, allocation failure, unsupported action, or repeated evidence failure: stop without a fallback path.
|
|
58
|
+
|
|
59
|
+
Do not query Principal before every operation. Protected endpoints perform their own authentication and authorization; use auth inspection only for setup or diagnosis.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Action MCP And Manual CLI Adapters
|
|
2
|
+
|
|
3
|
+
MCP and CLI call the same direct Device Action API and share the same Session, `screen_id`, action, and idempotency semantics. Agent Hosts use MCP because it provides typed inputs, structured errors, native image content, and process-owned lease management. Shell CLI commands are for humans and explicit diagnostics, not an automatic Agent fallback.
|
|
4
|
+
|
|
5
|
+
## Agent MCP Workflow
|
|
6
|
+
|
|
7
|
+
Start the isolated surface with `xagent mcp --mode action`, then load `xagent-explore-device`.
|
|
8
|
+
|
|
9
|
+
1. Resolve an existing app with `xagent_app_list` or `xagent_app_get`, or upload one explicit local APK with `xagent_app_upload_local`.
|
|
10
|
+
2. Resolve a device with `xagent_device_list` when its ID is unknown.
|
|
11
|
+
3. Call `xagent_device_acquire` once. Relay `console_url` to the user once and use the returned initial image and `screen_id`; do not immediately call `xagent_device_observe`.
|
|
12
|
+
4. Call `xagent_device_action` with one grounded action. Use its `after_observation` image for both the business decision and the next action.
|
|
13
|
+
5. Call `xagent_device_observe` only under the recovery rules in [single-action-protocol.md](single-action-protocol.md).
|
|
14
|
+
6. End with `xagent_device_release`, then release any temporary app upload no longer in use.
|
|
15
|
+
|
|
16
|
+
## Session Lifecycle
|
|
17
|
+
|
|
18
|
+
The MCP Host registers the Session returned by acquire, renews it before expiry, and checks freshness before Observe or Action. Explicit `xagent_device_renew` keeps the same Session and console link. An idempotent acquire replay must not repeat the console link. On process interruption or close, the Host performs best-effort release of Sessions it owns.
|
|
19
|
+
|
|
20
|
+
The observation console link is for human viewing. It does not replace MCP image evidence and is not a valid source for action coordinates unless the same screen is returned through the active Session observation contract.
|
|
21
|
+
|
|
22
|
+
## Manual CLI
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
xagent --json apps list --keyword <text>
|
|
26
|
+
xagent --json apps show <package-id>
|
|
27
|
+
xagent --json device acquire --device-id <device-id> --idempotency-key <key>
|
|
28
|
+
xagent --json device action <session-id> --screen-id <screen-id> --request-json '{"action":"click","bounds":"0.431,0.815,0.566,0.872"}' --idempotency-key <key>
|
|
29
|
+
xagent --json device observe <session-id>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Manual commands do not share the MCP Host's in-memory lease timer. Long workflows must keep the Session alive and release it explicitly. For parity diagnosis, compare the same Profile, Session, screen, action object, idempotency key, request envelope, and response envelope.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xagent-repair-test
|
|
3
|
+
description: Modify an existing XAgent YAML only after the user explicitly requests or authorizes repair, then verify the justified changes and create one confirmed successor Revision. Do not use for analysis-only, action mode, new-script authoring, unchanged Runs, or infrastructure/auth/device failures.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Repair An XAgent Test
|
|
7
|
+
|
|
8
|
+
1. Require explicit user authorization before modifying the YAML or proposing a new Revision.
|
|
9
|
+
2. Read the complete current YAML and user-selected failure evidence. Classify the failure; do not repair authentication, authorization, infrastructure, or device-availability errors by changing YAML. Read [repair-workflow.md](references/repair-workflow.md) for failure routing and keyboard-input troubleshooting.
|
|
10
|
+
3. Change only behavior justified by the evidence or user correction. Save the complete candidate YAML in a local repair workspace and validate it.
|
|
11
|
+
4. Use `xagent_authoring_draft_step_execute` to verify affected steps plus required prerequisites on the same Authoring Session device. Save the returned state and apply newer user guidance to the candidate before retrying.
|
|
12
|
+
5. After confirmation, create exactly one successor Revision with `source: agent` and `base_revision_id` pointing to the current Revision. Then complete or leave the Session according to the explicit request.
|
|
13
|
+
|
|
14
|
+
A personal Token with Authoring capabilities is required. Do not use a project CI Token for interactive repair, and do not overwrite repository YAML until the user accepts the candidate behavior.
|
|
15
|
+
|
|
16
|
+
This capability may edit only the authorized YAML, verify affected Draft Steps, and create one confirmed successor Revision. It must not use direct scriptless Actions, create a formal Run, broaden the repair beyond evidence, or automatically hand off. If the evidence is not repairable in YAML, report that and stop in this domain.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "XAgent Test Repair"
|
|
3
|
+
short_description: "Repair XAgent YAML with user-approved revisions"
|
|
4
|
+
default_prompt: "Use $xagent-repair-test only for the existing YAML repair I explicitly authorized. Limit edits to the evidence, verify affected Draft Steps, create one successor Revision after confirmation, and do not create a Run or switch workflows."
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Repair Workflow
|
|
2
|
+
|
|
3
|
+
Repair only after explicit user approval.
|
|
4
|
+
|
|
5
|
+
1. Preserve the original YAML and current Revision.
|
|
6
|
+
2. Identify the smallest behavior change supported by the failure evidence or user correction.
|
|
7
|
+
3. Write a complete candidate YAML in the local repair workspace; do not create a patch-only Revision.
|
|
8
|
+
4. Validate locally and resolve every schema issue.
|
|
9
|
+
5. Save a numbered local checkpoint and execute affected zero-based steps through `xagent_authoring_draft_step_execute` on the same Authoring Session. Replay prerequisites first when the correction changed navigation, input, branching, variables, package state, or another dependency.
|
|
10
|
+
6. Compare public Draft Attempt status and Artifacts with the intended behavior, and save the returned state locally.
|
|
11
|
+
7. Yield for newer user input before another side effect. On confirmation, create exactly one successor Revision with `source: agent` and `base_revision_id` equal to the current Revision; otherwise update the local candidate or cancel.
|
|
12
|
+
|
|
13
|
+
Do not repair infrastructure, authentication, authorization, or device availability errors by changing YAML. Do not use a project CI Token for Authoring. Do not overwrite a repository YAML until the user has accepted the candidate behavior. Do not create intermediate Revisions or upload local checkpoints.
|
|
14
|
+
|
|
15
|
+
## Keyboard Input Troubleshooting
|
|
16
|
+
|
|
17
|
+
For keyboard input failures, inspect the focused-field screenshot, the requested `inputMode`, the compiled keyboard-layout branch, and the cloud error before changing the scenario.
|
|
18
|
+
|
|
19
|
+
If `secret` was preserved and the requested layout branch completed but the device returns a secure-keyboard keycode error, treat that as device-input infrastructure evidence rather than an application failure. Do not replace it with fixed key coordinates or literal key-label clicks.
|
|
20
|
+
|
|
21
|
+
When the user requests ordinary input, use the CLI-local `inputMode: normal`; when a layout is required, use the CLI-local `keyboardLayout` field so the CLI emits an evidence-driven layout-switch branch. Submit the complete candidate as YAML `content` to MCP Tools so these local fields are compiled before the Developer API sees the script.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xagent-run-test
|
|
3
|
+
description: Validate and execute the exact existing XAgent YAML selected by the user with a Personal device or Project CI Target. Use for local execution, CI, smoke tests, or an explicit rerun without edits. Do not use to create, modify, analyze, or repair YAML, or for direct device action mode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run An Existing XAgent Test
|
|
7
|
+
|
|
8
|
+
1. Read only the YAML explicitly named by the user or checked into the current CI repository.
|
|
9
|
+
2. Validate YAML content before a network mutation. MCP Run creation receives the same YAML content; do not construct a separate raw script object. Stop on schema errors.
|
|
10
|
+
3. Select the Token execution path from [execution-modes.md](references/execution-modes.md). Inspect the Principal only when setup or permission diagnosis requires it.
|
|
11
|
+
4. Resolve the app. If `package_id` is unknown, list project apps and continue only on one unambiguous match. If `package_id` is known, get its authoritative package metadata rather than guessing a package name. A local APK may be uploaded explicitly by either Token type; Personal also supports one-shot `run --apk`.
|
|
12
|
+
5. Resolve execution. Personal uses an explicit device ID. Project CI uses a configured Target and stable idempotency key.
|
|
13
|
+
6. Wait only when the caller needs terminal status in the same process. Do not release a temporary upload until every dependent Run has terminated.
|
|
14
|
+
7. Classify the result with [result-status.md](references/result-status.md) and report the outcome in this domain. When a requested follow-up is outside Run mode, state that boundary and stop without naming, loading, or entering another Skill.
|
|
15
|
+
|
|
16
|
+
This capability must not create or edit YAML, execute direct device Actions or Draft Steps, create a Revision, automatically retry, or automatically hand off. Run cancellation requires an explicit user request. A schema error stops the Run; it does not authorize an edit.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "XAgent Test Run"
|
|
3
|
+
short_description: "Run confirmed XAgent YAML locally or in CI"
|
|
4
|
+
default_prompt: "Use $xagent-run-test only to validate and run the exact existing YAML I selected. Do not edit it, create Drafts or Revisions, use direct device actions, retry automatically, or switch workflows."
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Execution Modes
|
|
2
|
+
|
|
3
|
+
## Existing Project Application
|
|
4
|
+
|
|
5
|
+
When `package_id` is unknown, use `apps list` or `xagent_app_list` with identifying filters. Continue automatically only for one unambiguous match. When `package_id` is already known, use `apps show` or `xagent_app_get` to resolve authoritative package name, version, and launch metadata.
|
|
6
|
+
|
|
7
|
+
Personal Run uses an explicit device ID and `package_id`. Project CI Run uses a named Target, `package_id`, and stable idempotency key.
|
|
8
|
+
|
|
9
|
+
## Local APK
|
|
10
|
+
|
|
11
|
+
Both Token types can create a temporary upload:
|
|
12
|
+
|
|
13
|
+
xagent --json apps upload <app.apk>
|
|
14
|
+
|
|
15
|
+
MCP uses `xagent_app_upload_local`. The response returns upload `id`, `package_id`, `app.package_name`, and `app.launch_path`.
|
|
16
|
+
|
|
17
|
+
Personal Run passes upload `id` through `--app-upload-id` together with `--device-id`. The one-shot `run --apk` form uploads, binds, and releases automatically when the APK is needed only for that Run.
|
|
18
|
+
|
|
19
|
+
Project CI Run passes upload `id` through `--app-upload-id` together with `--target` and a stable `--idempotency-key`.
|
|
20
|
+
|
|
21
|
+
MCP Run creation supplies `app_upload_id` in the request and YAML content separately. Release with `apps release` or `xagent_app_release` only after all dependent Runs terminate. A released upload can no longer be treated as an installable package when it owns the platform package record.
|
|
22
|
+
|
|
23
|
+
Without `--wait`, Run creation returns immediately. Use `runs wait` or `xagent_run_wait` before release when terminal completion must be observed.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Run Result Status
|
|
2
|
+
|
|
3
|
+
| Status or error | Meaning | Default action |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| `passed` | All reported test steps passed | Report success |
|
|
6
|
+
| `failed` / `test_failed` | Test behavior or assertion failed | Report the evidence; do not auto-retry, edit, or switch modes |
|
|
7
|
+
| `infrastructure_failed` | Platform, device, network, file, or execution infrastructure failed | Report infrastructure failure; do not retry or switch modes |
|
|
8
|
+
| `cancelled` | Cancellation reached a terminal state | Report cancellation |
|
|
9
|
+
| `timed_out` / `timeout` | The wait or operation exceeded its deadline | Query final state when an ID exists before concluding business failure |
|
|
10
|
+
| `schema_invalid` | YAML or request does not match the public contract | Fix only with user authorization |
|
|
11
|
+
| `permission_denied` / `token_type_mismatch` | Current Principal cannot perform the operation | Stop; do not seek a bypass |
|
|
12
|
+
|
|
13
|
+
Use public messages and Artifacts. Never expose Tokens, internal device URLs, callback credentials, or local absolute paths in the report.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xagent-test-report
|
|
3
|
+
description: Write a structured mobile test report from already-collected XAgent Action, Authoring, or Run evidence. Use when the user asks for a test report, test document, Markdown test record, or evidence summary. Do not acquire devices, execute actions, observe devices, rerun tests, or invent missing evidence.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Write An XAgent Test Report
|
|
7
|
+
|
|
8
|
+
This Skill consumes evidence; it does not produce new evidence. Use only the results, image blocks, screen IDs, URLs, and cleanup details already present in the Agent context or explicitly supplied by the user. Do not call a device tool merely to fill a report gap.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Read [report-template.md](references/report-template.md), [evidence-policy.md](references/evidence-policy.md), and [result-classification.md](references/result-classification.md) before drafting.
|
|
13
|
+
2. Establish the report scope and one title. Record time, device, app, execution domain, Session, upload/package identifiers, and cleanup status only when known.
|
|
14
|
+
3. Group the collected evidence into test cases. For each case, state the goal, concise action summary, expected postcondition, actual visible result, selected evidence, and final status.
|
|
15
|
+
4. Select key screenshots rather than every MCP image: initial state when it establishes context, final proof for completed cases, and the image explaining each failure, ambiguity, or infrastructure problem.
|
|
16
|
+
5. Classify the test case from the strongest available evidence. Never promote an action-level `PASSED` to a test-level `PASSED` without a business postcondition.
|
|
17
|
+
6. Write Markdown to the explicitly selected workspace. For an archiveable report, copy only available image bytes to a sibling `evidence/` directory and use relative links. For a short execution record, retain screen IDs and omit unavailable images.
|
|
18
|
+
7. Run a final consistency pass: every linked image exists, every status has a reason, infrastructure problems are not described as app defects, and cleanup is recorded.
|
|
19
|
+
|
|
20
|
+
This is a reporting-only capability. It does not control devices, call MCP observation tools, or retry tests. It must not acquire a device Session, rerun tests, change YAML, create Runs, or automatically hand off into another Skill. If required evidence is absent, mark the relevant result `INCONCLUSIVE` and state the missing evidence. A report request may follow an explicitly completed Action, Authoring, or Run workflow, but it must not reopen that workflow.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "XAgent Test Report"
|
|
3
|
+
short_description: "Write evidence-based mobile test reports"
|
|
4
|
+
default_prompt: "Use $xagent-test-report to write a structured Markdown test report from the evidence already collected. Select key screenshots, classify infrastructure separately, and do not rerun or re-observe the device."
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Evidence Policy
|
|
2
|
+
|
|
3
|
+
Use evidence proportionally rather than attaching every intermediate screen.
|
|
4
|
+
|
|
5
|
+
## Required evidence
|
|
6
|
+
|
|
7
|
+
- The initial screen when it establishes the entry state or environment.
|
|
8
|
+
- One final proof image for each completed test case when an image exists.
|
|
9
|
+
- The relevant screen for a failed, blocked, ambiguous, or infrastructure-affected case.
|
|
10
|
+
|
|
11
|
+
## Optional evidence
|
|
12
|
+
|
|
13
|
+
- A keyboard, permission dialog, popup, navigation transition, or other intermediate state that explains the result.
|
|
14
|
+
- A second image when the first image is visibly stale or does not prove the stated postcondition.
|
|
15
|
+
|
|
16
|
+
## Image handling
|
|
17
|
+
|
|
18
|
+
MCP image content is the preferred Agent evidence. A `screenshot_url` may expire, so long-lived reports should use locally saved image bytes under `evidence/` and relative Markdown links. Do not download a new screenshot solely for documentation. Do not embed all base64 content in the Markdown file.
|
|
19
|
+
|
|
20
|
+
For each image, retain the source `screen_id` and describe what is visibly proven. If image bytes are unavailable, keep the screen ID and classify the evidence as unavailable instead of fabricating an image link.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Test Report Template
|
|
2
|
+
|
|
3
|
+
```markdown
|
|
4
|
+
# <测试报告标题>
|
|
5
|
+
|
|
6
|
+
## 1. 测试概览
|
|
7
|
+
|
|
8
|
+
- 测试时间:
|
|
9
|
+
- 测试范围:
|
|
10
|
+
- 执行链路:Action MCP / Authoring / Run
|
|
11
|
+
- 总体结论:
|
|
12
|
+
|
|
13
|
+
## 2. 测试环境
|
|
14
|
+
|
|
15
|
+
- 设备:
|
|
16
|
+
- `device_id`:
|
|
17
|
+
- Session:
|
|
18
|
+
- 应用与版本:
|
|
19
|
+
- 包名:
|
|
20
|
+
- APK 或上传 ID:
|
|
21
|
+
- 初始证据:
|
|
22
|
+
|
|
23
|
+
## 3. 测试用例
|
|
24
|
+
|
|
25
|
+
### TC-001 <用例名称>
|
|
26
|
+
|
|
27
|
+
- 目标:
|
|
28
|
+
- 步骤摘要:
|
|
29
|
+
- 预期结果:
|
|
30
|
+
- 实际结果:
|
|
31
|
+
- 状态:`PASSED` / `FAILED` / `BLOCKED` / `INCONCLUSIVE` / `INFRASTRUCTURE_FAILED`
|
|
32
|
+
- 关键证据:
|
|
33
|
+
|
|
34
|
+
## 4. 异常与基础设施问题
|
|
35
|
+
|
|
36
|
+
## 5. 资源清理
|
|
37
|
+
|
|
38
|
+
## 6. 总结
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Keep the report concise. Include raw JSON only when it explains a failure or an idempotency/replay decision.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Result Classification
|
|
2
|
+
|
|
3
|
+
Use the narrowest status supported by the evidence.
|
|
4
|
+
|
|
5
|
+
| Status | Meaning |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| `PASSED` | The requested business postcondition is visibly or otherwise explicitly confirmed. |
|
|
8
|
+
| `FAILED` | The test executed, but the requested business postcondition is contradicted. |
|
|
9
|
+
| `BLOCKED` | The test could not proceed because a required app, device, permission, or precondition was unavailable. |
|
|
10
|
+
| `INCONCLUSIVE` | Execution completed or partially completed, but the available evidence cannot establish success or failure. |
|
|
11
|
+
| `INFRASTRUCTURE_FAILED` | Screenshot capture/upload, transport, service, or device-control infrastructure failed and prevented reliable evidence. |
|
|
12
|
+
|
|
13
|
+
An action-level `PASSED` status on an individual device action means only that the device command completed. Combine it with the action result and the post-action evidence before assigning a test-case status. A screenshot upload failure must not be reported as an application failure unless independent evidence shows the application failed.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type CheckpointOptions = {
|
|
2
|
+
nextStepIndex: number;
|
|
3
|
+
executionMode?: "step_confirm" | "auto";
|
|
4
|
+
attemptId?: string;
|
|
5
|
+
attemptStatus?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare class AuthoringDraftStore {
|
|
8
|
+
readonly workspace: string;
|
|
9
|
+
constructor(workspace: string);
|
|
10
|
+
checkpoint(sessionId: string, content: string, options: CheckpointOptions): Promise<Record<string, unknown>>;
|
|
11
|
+
resume(sessionId: string): Promise<Record<string, unknown>>;
|
|
12
|
+
list(): Promise<Record<string, unknown>>;
|
|
13
|
+
private sessionRoot;
|
|
14
|
+
private validateSessionId;
|
|
15
|
+
private readState;
|
|
16
|
+
private atomicWrite;
|
|
17
|
+
private publicState;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=draft-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-store.d.ts","sourceRoot":"","sources":["../../src/authoring/draft-store.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBACf,SAAS,EAAE,MAAM;IAEvB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IA4B5G,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAW3D,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAa9C,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,iBAAiB;YACX,SAAS;YAST,WAAW;IAOzB,OAAO,CAAC,WAAW;CACpB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { mkdir, readFile, readdir, rename, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { stringify } from "yaml";
|
|
4
|
+
import { CliError } from "../core/errors.js";
|
|
5
|
+
import { hashJson } from "../core/json.js";
|
|
6
|
+
import { parseYaml } from "../script/service.js";
|
|
7
|
+
const SESSION_ID = /^[A-Za-z0-9_.-]{1,64}$/;
|
|
8
|
+
const STATE_VERSION = "xagent-local-authoring-state/v1";
|
|
9
|
+
export class AuthoringDraftStore {
|
|
10
|
+
workspace;
|
|
11
|
+
constructor(workspace) { this.workspace = path.resolve(workspace); }
|
|
12
|
+
async checkpoint(sessionId, content, options) {
|
|
13
|
+
this.validateSessionId(sessionId);
|
|
14
|
+
if (!Number.isInteger(options.nextStepIndex) || options.nextStepIndex < 0)
|
|
15
|
+
throw new CliError("invalid_request", "next_step_index must be a non-negative integer");
|
|
16
|
+
const parsed = await parseYaml(content);
|
|
17
|
+
if (!parsed.valid)
|
|
18
|
+
throw new CliError("schema_invalid", "Local Authoring draft is invalid", 2, { issues: parsed.issues });
|
|
19
|
+
const normalized = stringify(parsed.script, { lineWidth: 0 });
|
|
20
|
+
const root = this.sessionRoot(sessionId);
|
|
21
|
+
const checkpoints = path.join(root, "checkpoints");
|
|
22
|
+
await mkdir(checkpoints, { recursive: true });
|
|
23
|
+
const previous = await this.readState(root);
|
|
24
|
+
const number = Number(previous.checkpoint ?? 0) + 1;
|
|
25
|
+
const state = {
|
|
26
|
+
schema_version: STATE_VERSION,
|
|
27
|
+
session_id: sessionId,
|
|
28
|
+
checkpoint: number,
|
|
29
|
+
next_step_index: options.nextStepIndex,
|
|
30
|
+
execution_mode: options.executionMode ?? null,
|
|
31
|
+
last_attempt_id: options.attemptId ?? null,
|
|
32
|
+
last_attempt_status: options.attemptStatus ?? null,
|
|
33
|
+
script_hash: hashJson(parsed.script),
|
|
34
|
+
updated_at: new Date().toISOString().replace(/\.\d{3}Z$/, "+00:00"),
|
|
35
|
+
};
|
|
36
|
+
await this.atomicWrite(path.join(checkpoints, `${String(number).padStart(6, "0")}.yaml`), normalized);
|
|
37
|
+
await this.atomicWrite(path.join(root, "draft.yaml"), normalized);
|
|
38
|
+
await this.atomicWrite(path.join(root, "state.json"), `${JSON.stringify(state, null, 2)}\n`);
|
|
39
|
+
return this.publicState(root, state);
|
|
40
|
+
}
|
|
41
|
+
async resume(sessionId) {
|
|
42
|
+
this.validateSessionId(sessionId);
|
|
43
|
+
const root = this.sessionRoot(sessionId);
|
|
44
|
+
const state = await this.readState(root);
|
|
45
|
+
let content;
|
|
46
|
+
try {
|
|
47
|
+
content = await readFile(path.join(root, "draft.yaml"), "utf8");
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
throw new CliError("resource_not_found", "Local Authoring draft was not found");
|
|
51
|
+
}
|
|
52
|
+
if (Object.keys(state).length === 0)
|
|
53
|
+
throw new CliError("resource_not_found", "Local Authoring draft was not found");
|
|
54
|
+
return { ...this.publicState(root, state), content };
|
|
55
|
+
}
|
|
56
|
+
async list() {
|
|
57
|
+
const root = path.join(this.workspace, ".xagent", "authoring");
|
|
58
|
+
const drafts = [];
|
|
59
|
+
let entries = [];
|
|
60
|
+
try {
|
|
61
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return { workspace: this.workspace, drafts };
|
|
65
|
+
}
|
|
66
|
+
for (const entry of entries.filter((item) => item.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
67
|
+
const sessionRoot = path.join(root, entry.name);
|
|
68
|
+
const state = await this.readState(sessionRoot);
|
|
69
|
+
if (Object.keys(state).length)
|
|
70
|
+
drafts.push(this.publicState(sessionRoot, state));
|
|
71
|
+
}
|
|
72
|
+
return { workspace: this.workspace, drafts };
|
|
73
|
+
}
|
|
74
|
+
sessionRoot(sessionId) { return path.join(this.workspace, ".xagent", "authoring", sessionId); }
|
|
75
|
+
validateSessionId(sessionId) { if (!SESSION_ID.test(String(sessionId ?? "").trim()))
|
|
76
|
+
throw new CliError("invalid_request", "session_id is invalid"); }
|
|
77
|
+
async readState(root) {
|
|
78
|
+
try {
|
|
79
|
+
const value = JSON.parse(await readFile(path.join(root, "state.json"), "utf8"));
|
|
80
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error?.code === "ENOENT")
|
|
84
|
+
return {};
|
|
85
|
+
throw new CliError("local_draft_invalid", "Local Authoring state cannot be read");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async atomicWrite(filePath, content) {
|
|
89
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
90
|
+
const temporary = `${filePath}.tmp`;
|
|
91
|
+
try {
|
|
92
|
+
await writeFile(temporary, content, "utf8");
|
|
93
|
+
await rename(temporary, filePath);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new CliError("local_draft_write_failed", "Local Authoring draft cannot be saved");
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await unlink(temporary).catch(() => undefined);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
publicState(root, state) { return { ...state, draft_path: path.join(root, "draft.yaml"), state_path: path.join(root, "state.json") }; }
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=draft-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-store.js","sourceRoot":"","sources":["../../src/authoring/draft-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export type SessionLeaseSnapshot = {
|
|
2
|
+
id?: unknown;
|
|
3
|
+
session_id?: unknown;
|
|
4
|
+
status?: unknown;
|
|
5
|
+
expires_at?: unknown;
|
|
6
|
+
device_id?: unknown;
|
|
7
|
+
session?: SessionLeaseSnapshot;
|
|
8
|
+
};
|
|
9
|
+
export type SessionLeaseClient = {
|
|
10
|
+
getSession?: (sessionId: string) => Promise<Record<string, any>>;
|
|
11
|
+
renewSession: (sessionId: string) => Promise<Record<string, any>>;
|
|
12
|
+
cancel?: (sessionId: string, idempotencyKey: string) => Promise<Record<string, any>>;
|
|
13
|
+
};
|
|
14
|
+
export type SessionLeaseEvent = {
|
|
15
|
+
type: "registered" | "renewed" | "renewal_failed" | "release_failed" | "unregistered" | "expired";
|
|
16
|
+
session_id: string;
|
|
17
|
+
expires_at?: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
};
|
|
20
|
+
type Timer = ReturnType<typeof setTimeout>;
|
|
21
|
+
type Clock = {
|
|
22
|
+
now: () => number;
|
|
23
|
+
setTimeout: (callback: () => void, delay: number) => Timer;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Owns only the Session leases created or explicitly touched by this process.
|
|
27
|
+
* The server remains the authority for expiry and device ownership; this class
|
|
28
|
+
* renews only when active work checks freshness or explicit keepalive is running.
|
|
29
|
+
*/
|
|
30
|
+
export declare class SessionLeaseManager {
|
|
31
|
+
private readonly client;
|
|
32
|
+
private readonly leases;
|
|
33
|
+
private readonly renewals;
|
|
34
|
+
private readonly clock;
|
|
35
|
+
private readonly renewBeforeMs;
|
|
36
|
+
private readonly onEvent?;
|
|
37
|
+
constructor(client: SessionLeaseClient, options?: {
|
|
38
|
+
renewBeforeMs?: number;
|
|
39
|
+
clock?: Partial<Clock>;
|
|
40
|
+
onEvent?: (event: SessionLeaseEvent) => void;
|
|
41
|
+
});
|
|
42
|
+
register(sessionId: string, snapshot?: SessionLeaseSnapshot): void;
|
|
43
|
+
unregister(sessionId: string): void;
|
|
44
|
+
has(sessionId: string): boolean;
|
|
45
|
+
getLease(sessionId: string): Record<string, unknown> | undefined;
|
|
46
|
+
/** Ensure a Session is known and renew it when it is inside the lease window. */
|
|
47
|
+
ensureFresh(sessionId: string): Promise<Record<string, any> | undefined>;
|
|
48
|
+
renew(sessionId: string): Promise<Record<string, any>>;
|
|
49
|
+
private performRenew;
|
|
50
|
+
/** Keep one Session alive until it reaches a terminal server state. */
|
|
51
|
+
keepAlive(sessionId: string, options?: {
|
|
52
|
+
pollMs?: number;
|
|
53
|
+
onEvent?: (event: SessionLeaseEvent) => void;
|
|
54
|
+
}): Promise<void>;
|
|
55
|
+
/** Best-effort release for resources owned by this MCP process on shutdown. */
|
|
56
|
+
releaseAll(): Promise<void>;
|
|
57
|
+
private assertUsable;
|
|
58
|
+
private readStatus;
|
|
59
|
+
private readExpiresAt;
|
|
60
|
+
private emit;
|
|
61
|
+
private emitTo;
|
|
62
|
+
}
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=session-lease.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-lease.d.ts","sourceRoot":"","sources":["../../src/authoring/session-lease.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACjE,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;CACtF,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IAClG,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAC3C,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;CAC5D,CAAC;AAeF;;;;GAIG;AACH,qBAAa,mBAAmB;IAQ5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmD;IAC5E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAqC;gBAG3C,MAAM,EAAE,kBAAkB,EAC3C,OAAO,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAA;KAAO;IAWhH,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,oBAAyB,GAAG,IAAI;IAiBtE,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAOnC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAE/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAWhE,iFAAiF;IAC3E,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IA6BxE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAU9C,YAAY;IAuB1B,uEAAuE;IACjE,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBlI,+EAA+E;IACzE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;CACf"}
|