@xyteai/cli 0.1.0
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/LICENSE +176 -0
- package/README.md +245 -0
- package/dist/bin/xyte-cli.d.ts +3 -0
- package/dist/bin/xyte-cli.d.ts.map +1 -0
- package/dist/bin/xyte-cli.js +18 -0
- package/dist/bin/xyte-cli.js.map +1 -0
- package/dist/cli/index.d.ts +24 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +1185 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client/catalog.d.ts +6 -0
- package/dist/client/catalog.d.ts.map +1 -0
- package/dist/client/catalog.js +32 -0
- package/dist/client/catalog.js.map +1 -0
- package/dist/client/create-client.d.ts +3 -0
- package/dist/client/create-client.d.ts.map +1 -0
- package/dist/client/create-client.js +235 -0
- package/dist/client/create-client.js.map +1 -0
- package/dist/config/connectivity.d.ts +19 -0
- package/dist/config/connectivity.d.ts.map +1 -0
- package/dist/config/connectivity.js +166 -0
- package/dist/config/connectivity.js.map +1 -0
- package/dist/config/readiness.d.ts +32 -0
- package/dist/config/readiness.d.ts.map +1 -0
- package/dist/config/readiness.js +96 -0
- package/dist/config/readiness.js.map +1 -0
- package/dist/config/retry-policy.d.ts +16 -0
- package/dist/config/retry-policy.d.ts.map +1 -0
- package/dist/config/retry-policy.js +24 -0
- package/dist/config/retry-policy.js.map +1 -0
- package/dist/contracts/call-envelope.d.ts +74 -0
- package/dist/contracts/call-envelope.d.ts.map +1 -0
- package/dist/contracts/call-envelope.js +72 -0
- package/dist/contracts/call-envelope.js.map +1 -0
- package/dist/contracts/problem.d.ts +11 -0
- package/dist/contracts/problem.d.ts.map +1 -0
- package/dist/contracts/problem.js +55 -0
- package/dist/contracts/problem.js.map +1 -0
- package/dist/contracts/versions.d.ts +6 -0
- package/dist/contracts/versions.d.ts.map +1 -0
- package/dist/contracts/versions.js +9 -0
- package/dist/contracts/versions.js.map +1 -0
- package/dist/http/errors.d.ts +24 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/http/errors.js +39 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/transport.d.ts +35 -0
- package/dist/http/transport.d.ts.map +1 -0
- package/dist/http/transport.js +129 -0
- package/dist/http/transport.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +12 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +404 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/namespaces/device.d.ts +38 -0
- package/dist/namespaces/device.d.ts.map +1 -0
- package/dist/namespaces/device.js +36 -0
- package/dist/namespaces/device.js.map +1 -0
- package/dist/namespaces/organization.d.ts +27 -0
- package/dist/namespaces/organization.d.ts.map +1 -0
- package/dist/namespaces/organization.js +30 -0
- package/dist/namespaces/organization.js.map +1 -0
- package/dist/namespaces/partner.d.ts +18 -0
- package/dist/namespaces/partner.d.ts.map +1 -0
- package/dist/namespaces/partner.js +21 -0
- package/dist/namespaces/partner.js.map +1 -0
- package/dist/observability/logger.d.ts +3 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +21 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/tracing.d.ts +3 -0
- package/dist/observability/tracing.d.ts.map +1 -0
- package/dist/observability/tracing.js +26 -0
- package/dist/observability/tracing.js.map +1 -0
- package/dist/secure/key-slots.d.ts +8 -0
- package/dist/secure/key-slots.d.ts.map +1 -0
- package/dist/secure/key-slots.js +47 -0
- package/dist/secure/key-slots.js.map +1 -0
- package/dist/secure/keychain.d.ts +20 -0
- package/dist/secure/keychain.d.ts.map +1 -0
- package/dist/secure/keychain.js +170 -0
- package/dist/secure/keychain.js.map +1 -0
- package/dist/secure/profile-store.d.ts +66 -0
- package/dist/secure/profile-store.d.ts.map +1 -0
- package/dist/secure/profile-store.js +309 -0
- package/dist/secure/profile-store.js.map +1 -0
- package/dist/spec/public-endpoints.json +1175 -0
- package/dist/tui/animation.d.ts +12 -0
- package/dist/tui/animation.d.ts.map +1 -0
- package/dist/tui/animation.js +41 -0
- package/dist/tui/animation.js.map +1 -0
- package/dist/tui/app.d.ts +27 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +711 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/assets/logo.d.ts +5 -0
- package/dist/tui/assets/logo.d.ts.map +1 -0
- package/dist/tui/assets/logo.js +24 -0
- package/dist/tui/assets/logo.js.map +1 -0
- package/dist/tui/data-loaders.d.ts +33 -0
- package/dist/tui/data-loaders.d.ts.map +1 -0
- package/dist/tui/data-loaders.js +250 -0
- package/dist/tui/data-loaders.js.map +1 -0
- package/dist/tui/dispatch.d.ts +14 -0
- package/dist/tui/dispatch.d.ts.map +1 -0
- package/dist/tui/dispatch.js +44 -0
- package/dist/tui/dispatch.js.map +1 -0
- package/dist/tui/headless-renderer.d.ts +20 -0
- package/dist/tui/headless-renderer.d.ts.map +1 -0
- package/dist/tui/headless-renderer.js +598 -0
- package/dist/tui/headless-renderer.js.map +1 -0
- package/dist/tui/input-controller.d.ts +29 -0
- package/dist/tui/input-controller.d.ts.map +1 -0
- package/dist/tui/input-controller.js +76 -0
- package/dist/tui/input-controller.js.map +1 -0
- package/dist/tui/key-wizard.d.ts +29 -0
- package/dist/tui/key-wizard.d.ts.map +1 -0
- package/dist/tui/key-wizard.js +177 -0
- package/dist/tui/key-wizard.js.map +1 -0
- package/dist/tui/keymap.d.ts +9 -0
- package/dist/tui/keymap.d.ts.map +1 -0
- package/dist/tui/keymap.js +29 -0
- package/dist/tui/keymap.js.map +1 -0
- package/dist/tui/layout.d.ts +16 -0
- package/dist/tui/layout.d.ts.map +1 -0
- package/dist/tui/layout.js +99 -0
- package/dist/tui/layout.js.map +1 -0
- package/dist/tui/logger.d.ts +12 -0
- package/dist/tui/logger.d.ts.map +1 -0
- package/dist/tui/logger.js +83 -0
- package/dist/tui/logger.js.map +1 -0
- package/dist/tui/navigation.d.ts +26 -0
- package/dist/tui/navigation.d.ts.map +1 -0
- package/dist/tui/navigation.js +136 -0
- package/dist/tui/navigation.js.map +1 -0
- package/dist/tui/panes.d.ts +7 -0
- package/dist/tui/panes.d.ts.map +1 -0
- package/dist/tui/panes.js +34 -0
- package/dist/tui/panes.js.map +1 -0
- package/dist/tui/runtime.d.ts +34 -0
- package/dist/tui/runtime.d.ts.map +1 -0
- package/dist/tui/runtime.js +100 -0
- package/dist/tui/runtime.js.map +1 -0
- package/dist/tui/scene.d.ts +160 -0
- package/dist/tui/scene.d.ts.map +1 -0
- package/dist/tui/scene.js +424 -0
- package/dist/tui/scene.js.map +1 -0
- package/dist/tui/screens/config.d.ts +3 -0
- package/dist/tui/screens/config.d.ts.map +1 -0
- package/dist/tui/screens/config.js +406 -0
- package/dist/tui/screens/config.js.map +1 -0
- package/dist/tui/screens/dashboard.d.ts +3 -0
- package/dist/tui/screens/dashboard.d.ts.map +1 -0
- package/dist/tui/screens/dashboard.js +176 -0
- package/dist/tui/screens/dashboard.js.map +1 -0
- package/dist/tui/screens/devices.d.ts +3 -0
- package/dist/tui/screens/devices.d.ts.map +1 -0
- package/dist/tui/screens/devices.js +297 -0
- package/dist/tui/screens/devices.js.map +1 -0
- package/dist/tui/screens/incidents.d.ts +4 -0
- package/dist/tui/screens/incidents.d.ts.map +1 -0
- package/dist/tui/screens/incidents.js +304 -0
- package/dist/tui/screens/incidents.js.map +1 -0
- package/dist/tui/screens/setup.d.ts +3 -0
- package/dist/tui/screens/setup.d.ts.map +1 -0
- package/dist/tui/screens/setup.js +299 -0
- package/dist/tui/screens/setup.js.map +1 -0
- package/dist/tui/screens/spaces.d.ts +7 -0
- package/dist/tui/screens/spaces.d.ts.map +1 -0
- package/dist/tui/screens/spaces.js +422 -0
- package/dist/tui/screens/spaces.js.map +1 -0
- package/dist/tui/screens/tickets.d.ts +9 -0
- package/dist/tui/screens/tickets.d.ts.map +1 -0
- package/dist/tui/screens/tickets.js +418 -0
- package/dist/tui/screens/tickets.js.map +1 -0
- package/dist/tui/serialize.d.ts +31 -0
- package/dist/tui/serialize.d.ts.map +1 -0
- package/dist/tui/serialize.js +183 -0
- package/dist/tui/serialize.js.map +1 -0
- package/dist/tui/table-format.d.ts +11 -0
- package/dist/tui/table-format.d.ts.map +1 -0
- package/dist/tui/table-format.js +77 -0
- package/dist/tui/table-format.js.map +1 -0
- package/dist/tui/tabs.d.ts +4 -0
- package/dist/tui/tabs.d.ts.map +1 -0
- package/dist/tui/tabs.js +13 -0
- package/dist/tui/tabs.js.map +1 -0
- package/dist/tui/types.d.ts +37 -0
- package/dist/tui/types.d.ts.map +1 -0
- package/dist/tui/types.js +3 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/types/client.d.ts +54 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +3 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/endpoints.d.ts +29 -0
- package/dist/types/endpoints.d.ts.map +1 -0
- package/dist/types/endpoints.js +3 -0
- package/dist/types/endpoints.js.map +1 -0
- package/dist/types/profile.d.ts +29 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/profile.js +3 -0
- package/dist/types/profile.js.map +1 -0
- package/dist/utils/config-dir.d.ts +2 -0
- package/dist/utils/config-dir.d.ts.map +1 -0
- package/dist/utils/config-dir.js +23 -0
- package/dist/utils/config-dir.js.map +1 -0
- package/dist/utils/error-format.d.ts +4 -0
- package/dist/utils/error-format.d.ts.map +1 -0
- package/dist/utils/error-format.js +34 -0
- package/dist/utils/error-format.js.map +1 -0
- package/dist/utils/install-skills.d.ts +38 -0
- package/dist/utils/install-skills.d.ts.map +1 -0
- package/dist/utils/install-skills.js +117 -0
- package/dist/utils/install-skills.js.map +1 -0
- package/dist/utils/json-output.d.ts +6 -0
- package/dist/utils/json-output.d.ts.map +1 -0
- package/dist/utils/json-output.js +30 -0
- package/dist/utils/json-output.js.map +1 -0
- package/dist/utils/json.d.ts +4 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +36 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +28 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/workflows/fleet-insights.d.ts +122 -0
- package/dist/workflows/fleet-insights.d.ts.map +1 -0
- package/dist/workflows/fleet-insights.js +938 -0
- package/dist/workflows/fleet-insights.js.map +1 -0
- package/docs/schemas/call-envelope.v1.schema.json +140 -0
- package/docs/schemas/headless-frame.v1.schema.json +159 -0
- package/docs/schemas/inspect-deep-dive.v1.schema.json +251 -0
- package/docs/schemas/inspect-fleet.v1.schema.json +111 -0
- package/docs/schemas/report.v1.schema.json +39 -0
- package/package.json +75 -0
- package/skills/xyte-cli/SKILL.md +181 -0
- package/skills/xyte-cli/agents/openai.yaml +4 -0
- package/skills/xyte-cli/references/endpoints.md +106 -0
- package/skills/xyte-cli/references/headless-contract.md +96 -0
- package/skills/xyte-cli/references/tui-flows.md +126 -0
- package/skills/xyte-cli/scripts/check_headless.sh +83 -0
- package/skills/xyte-cli/scripts/endpoint_filters_report.sh +33 -0
- package/skills/xyte-cli/scripts/run_xyte_cli.sh +12 -0
- package/skills/xyte-cli/scripts/validate_agent_contracts.sh +72 -0
- package/skills/xyte-cli/scripts/validate_with_schema.js +30 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Headless Flows (Agent-First)
|
|
2
|
+
|
|
3
|
+
Use `xyte-cli tui --headless` as the visual/tooling interface for agents.
|
|
4
|
+
|
|
5
|
+
## Base Pattern
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
xyte-cli tui --headless --screen <screen> --format json --once --tenant <tenant-id>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Supported screens:
|
|
12
|
+
- `setup`
|
|
13
|
+
- `config`
|
|
14
|
+
- `dashboard`
|
|
15
|
+
- `spaces`
|
|
16
|
+
- `devices`
|
|
17
|
+
- `incidents`
|
|
18
|
+
- `tickets`
|
|
19
|
+
|
|
20
|
+
## Deterministic Branching (Required)
|
|
21
|
+
|
|
22
|
+
1. Request operational screen (for example `dashboard`).
|
|
23
|
+
2. Parse last non-startup frame.
|
|
24
|
+
3. If `frame.screen == "setup"` and `frame.meta.redirectedFrom` is set:
|
|
25
|
+
- treat tenant/keys/setup as blocking
|
|
26
|
+
- switch to setup/config remediation flow
|
|
27
|
+
4. Retry requested operational screen after remediation.
|
|
28
|
+
|
|
29
|
+
## Setup/Config Remediation Flow
|
|
30
|
+
|
|
31
|
+
1. Check readiness frame:
|
|
32
|
+
```bash
|
|
33
|
+
xyte-cli tui --headless --screen setup --format json --once --tenant <tenant-id>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. If missing auth, run CLI key-slot operations:
|
|
37
|
+
```bash
|
|
38
|
+
xyte-cli auth key add --tenant <tenant-id> --provider xyte-org --name primary --key <value> --set-active
|
|
39
|
+
xyte-cli auth key list --tenant <tenant-id> --format json
|
|
40
|
+
xyte-cli config doctor --tenant <tenant-id> --format json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. Re-request operational headless frame.
|
|
44
|
+
|
|
45
|
+
## Per-Screen Headless Recipes
|
|
46
|
+
|
|
47
|
+
Setup:
|
|
48
|
+
```bash
|
|
49
|
+
xyte-cli tui --headless --screen setup --format json --once --tenant <tenant-id>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Config:
|
|
53
|
+
```bash
|
|
54
|
+
xyte-cli tui --headless --screen config --format json --once --tenant <tenant-id>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Dashboard:
|
|
58
|
+
```bash
|
|
59
|
+
xyte-cli tui --headless --screen dashboard --format json --once --tenant <tenant-id>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Spaces:
|
|
63
|
+
```bash
|
|
64
|
+
xyte-cli tui --headless --screen spaces --format json --once --tenant <tenant-id>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Devices:
|
|
68
|
+
```bash
|
|
69
|
+
xyte-cli tui --headless --screen devices --format json --once --tenant <tenant-id>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Incidents:
|
|
73
|
+
```bash
|
|
74
|
+
xyte-cli tui --headless --screen incidents --format json --once --tenant <tenant-id>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Tickets:
|
|
78
|
+
```bash
|
|
79
|
+
xyte-cli tui --headless --screen tickets --format json --once --tenant <tenant-id>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Follow Mode (Streaming)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
xyte-cli tui --headless --screen spaces --format json --follow --interval-ms 2000 --tenant <tenant-id>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Use `--follow` only when continuous status is needed.
|
|
89
|
+
|
|
90
|
+
## Metadata Keys Agents Should Parse
|
|
91
|
+
|
|
92
|
+
From top-level frame:
|
|
93
|
+
- `schemaVersion` (expect `xyte.headless.frame.v1`)
|
|
94
|
+
- `sessionId` (stable for one run)
|
|
95
|
+
- `sequence` (monotonic ordering key in `--follow`)
|
|
96
|
+
|
|
97
|
+
From `frame.meta`:
|
|
98
|
+
- `readiness`
|
|
99
|
+
- `connection`
|
|
100
|
+
- `refreshState`
|
|
101
|
+
- `renderSafety`
|
|
102
|
+
- `tableFormat`
|
|
103
|
+
- `activePane`
|
|
104
|
+
- `availablePanes`
|
|
105
|
+
- `navigationMode`
|
|
106
|
+
- `tabId`
|
|
107
|
+
- `tabOrder`
|
|
108
|
+
- `tabNavBoundary`
|
|
109
|
+
- `redirectedFrom` (when setup gate blocks)
|
|
110
|
+
- `contract.frameVersion`
|
|
111
|
+
- `contract.tableFormat`
|
|
112
|
+
- `contract.navigationMode`
|
|
113
|
+
|
|
114
|
+
## Output Mode
|
|
115
|
+
|
|
116
|
+
Headless is JSON-only. Always parse NDJSON frames:
|
|
117
|
+
```bash
|
|
118
|
+
xyte-cli tui --headless --screen config --format json --once --tenant <tenant-id>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Safety Model
|
|
122
|
+
|
|
123
|
+
- Headless frames are read-only visualization.
|
|
124
|
+
- Mutations still must go through guarded CLI commands:
|
|
125
|
+
- non-read methods require `--allow-write`
|
|
126
|
+
- delete methods require `--allow-write --confirm <endpoint-key>`
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
RUN_CLI="$SCRIPT_DIR/run_xyte_cli.sh"
|
|
6
|
+
VALIDATE_SCHEMA="$SCRIPT_DIR/validate_with_schema.js"
|
|
7
|
+
TENANT_ID="${1:-}"
|
|
8
|
+
|
|
9
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
10
|
+
echo "jq is required" >&2
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
if [[ ! -x "$RUN_CLI" ]]; then
|
|
15
|
+
echo "Missing launcher script: $RUN_CLI" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
if [[ ! -x "$VALIDATE_SCHEMA" ]]; then
|
|
20
|
+
echo "Missing validator script: $VALIDATE_SCHEMA" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
25
|
+
if [[ ! -f "$REPO_ROOT/dist/bin/xyte-cli.js" ]]; then
|
|
26
|
+
echo "Build output missing at $REPO_ROOT/dist/bin/xyte-cli.js" >&2
|
|
27
|
+
echo "Run: npm run build" >&2
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
SCREENS=(setup config dashboard spaces devices incidents tickets)
|
|
32
|
+
META_KEYS=(inputState queueDepth droppedEvents transitionState refreshState navigationMode activePane availablePanes tabId tabOrder tabNavBoundary renderSafety tableFormat contract)
|
|
33
|
+
TMP_CFG="$(mktemp -d)"
|
|
34
|
+
trap 'rm -rf "$TMP_CFG"' EXIT
|
|
35
|
+
|
|
36
|
+
PASS_COUNT=0
|
|
37
|
+
for screen in "${SCREENS[@]}"; do
|
|
38
|
+
cmd=("$RUN_CLI" tui --headless --screen "$screen" --format json --once --no-motion)
|
|
39
|
+
if [[ -n "$TENANT_ID" ]]; then
|
|
40
|
+
cmd+=(--tenant "$TENANT_ID")
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if [[ -n "$TENANT_ID" ]]; then
|
|
44
|
+
output="$("${cmd[@]}")"
|
|
45
|
+
else
|
|
46
|
+
output="$(XYTE_CLI_CONFIG_DIR="$TMP_CFG" XYTE_CLI_KEYCHAIN_BACKEND=memory "${cmd[@]}")"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
runtime_frame="$(printf '%s\n' "$output" | jq -c 'select((.meta.startup // false) | not)' | tail -n1)"
|
|
50
|
+
if [[ -z "$runtime_frame" ]]; then
|
|
51
|
+
echo "FAIL [$screen] no runtime frame" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
printf '%s\n' "$runtime_frame" | jq -e '.schemaVersion == "xyte.headless.frame.v1"' >/dev/null
|
|
56
|
+
printf '%s\n' "$runtime_frame" | jq -e '.sessionId | type == "string"' >/dev/null
|
|
57
|
+
printf '%s\n' "$runtime_frame" | jq -e '.sequence | type == "number"' >/dev/null
|
|
58
|
+
|
|
59
|
+
for key in "${META_KEYS[@]}"; do
|
|
60
|
+
printf '%s\n' "$runtime_frame" | jq -e --arg k "$key" '.meta | has($k)' >/dev/null
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
printf '%s\n' "$runtime_frame" | jq -e '.meta.contract.frameVersion == "xyte.headless.frame.v1"' >/dev/null
|
|
64
|
+
|
|
65
|
+
runtime_path="$TMP_CFG/headless-$screen.json"
|
|
66
|
+
printf '%s\n' "$runtime_frame" > "$runtime_path"
|
|
67
|
+
"$VALIDATE_SCHEMA" "$REPO_ROOT/docs/schemas/headless-frame.v1.schema.json" "$runtime_path" >/dev/null
|
|
68
|
+
|
|
69
|
+
runtime_screen="$(printf '%s\n' "$runtime_frame" | jq -r '.screen')"
|
|
70
|
+
if [[ "$screen" != "setup" && "$screen" != "config" && "$runtime_screen" == "setup" ]]; then
|
|
71
|
+
redirected_from="$(printf '%s\n' "$runtime_frame" | jq -r '.meta.redirectedFrom // ""')"
|
|
72
|
+
if [[ "$redirected_from" != "$screen" ]]; then
|
|
73
|
+
echo "FAIL [$screen] expected redirectedFrom=$screen, got '$redirected_from'" >&2
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
printf '%s\n' "$runtime_frame" | jq -e '.panels | type == "array"' >/dev/null
|
|
79
|
+
echo "PASS [$screen] runtime_screen=$runtime_screen"
|
|
80
|
+
PASS_COUNT=$((PASS_COUNT + 1))
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
echo "Headless smoke passed: $PASS_COUNT/${#SCREENS[@]} screens"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
5
|
+
SPEC="$REPO_ROOT/src/spec/public-endpoints.json"
|
|
6
|
+
|
|
7
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
8
|
+
echo "jq is required" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
if [[ ! -f "$SPEC" ]]; then
|
|
13
|
+
echo "Spec file not found: $SPEC" >&2
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
echo "key | method | query_params | pagination"
|
|
18
|
+
echo "--- | --- | --- | ---"
|
|
19
|
+
|
|
20
|
+
jq -r '
|
|
21
|
+
.[]
|
|
22
|
+
| select((.queryParams | length) > 0)
|
|
23
|
+
| {
|
|
24
|
+
key,
|
|
25
|
+
method,
|
|
26
|
+
query: (.queryParams | join(", ")),
|
|
27
|
+
pagination: (if ((.queryParams | index("page")) != null or (.queryParams | index("per_page")) != null)
|
|
28
|
+
then "page/per_page"
|
|
29
|
+
else "none"
|
|
30
|
+
end)
|
|
31
|
+
}
|
|
32
|
+
| "\(.key) | \(.method) | \(.query) | \(.pagination)"
|
|
33
|
+
' "$SPEC"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
5
|
+
cd "$REPO_ROOT"
|
|
6
|
+
|
|
7
|
+
if [[ ! -x ./bin/xyte-cli ]]; then
|
|
8
|
+
echo "xyte-cli binary wrapper not found at ./bin/xyte-cli" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
./bin/xyte-cli "$@"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
RUN_CLI="$SCRIPT_DIR/run_xyte_cli.sh"
|
|
6
|
+
VALIDATE_SCHEMA="$SCRIPT_DIR/validate_with_schema.js"
|
|
7
|
+
TENANT_ID="${1:-}"
|
|
8
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
9
|
+
|
|
10
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
11
|
+
echo "jq is required" >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
if [[ -z "$TENANT_ID" ]]; then
|
|
16
|
+
echo "Usage: $(basename "$0") <tenant-id>" >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if [[ ! -x "$VALIDATE_SCHEMA" ]]; then
|
|
21
|
+
echo "Missing validator script: $VALIDATE_SCHEMA" >&2
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
TMP_DIR="$(mktemp -d)"
|
|
26
|
+
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
27
|
+
|
|
28
|
+
echo "Validating call envelope contract..."
|
|
29
|
+
set +e
|
|
30
|
+
CALL_OUTPUT="$("$RUN_CLI" call organization.devices.getDevices --tenant "$TENANT_ID" --output-mode envelope 2>/dev/null)"
|
|
31
|
+
CALL_EXIT=$?
|
|
32
|
+
set -e
|
|
33
|
+
|
|
34
|
+
if [[ -z "$CALL_OUTPUT" ]]; then
|
|
35
|
+
echo "FAIL call envelope emitted empty output" >&2
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
printf '%s\n' "$CALL_OUTPUT" | jq -e '.schemaVersion == "xyte.call.envelope.v1"' >/dev/null
|
|
39
|
+
printf '%s\n' "$CALL_OUTPUT" | jq -e '.requestId | type == "string"' >/dev/null
|
|
40
|
+
CALL_PATH="$TMP_DIR/call-envelope.json"
|
|
41
|
+
printf '%s\n' "$CALL_OUTPUT" > "$CALL_PATH"
|
|
42
|
+
"$VALIDATE_SCHEMA" "$REPO_ROOT/docs/schemas/call-envelope.v1.schema.json" "$CALL_PATH"
|
|
43
|
+
echo "PASS call envelope (exit=$CALL_EXIT)"
|
|
44
|
+
|
|
45
|
+
echo "Validating inspect fleet contract..."
|
|
46
|
+
FLEET_OUTPUT="$("$RUN_CLI" inspect fleet --tenant "$TENANT_ID" --format json)"
|
|
47
|
+
printf '%s\n' "$FLEET_OUTPUT" | jq -e '.schemaVersion == "xyte.inspect.fleet.v1"' >/dev/null
|
|
48
|
+
FLEET_PATH="$TMP_DIR/fleet.json"
|
|
49
|
+
printf '%s\n' "$FLEET_OUTPUT" > "$FLEET_PATH"
|
|
50
|
+
"$VALIDATE_SCHEMA" "$REPO_ROOT/docs/schemas/inspect-fleet.v1.schema.json" "$FLEET_PATH"
|
|
51
|
+
echo "PASS inspect fleet"
|
|
52
|
+
|
|
53
|
+
echo "Validating inspect deep-dive + report contracts..."
|
|
54
|
+
DEEP_OUTPUT="$("$RUN_CLI" inspect deep-dive --tenant "$TENANT_ID" --format json)"
|
|
55
|
+
printf '%s\n' "$DEEP_OUTPUT" | jq -e '.schemaVersion == "xyte.inspect.deep-dive.v1"' >/dev/null
|
|
56
|
+
DEEP_PATH="$TMP_DIR/deep-dive.json"
|
|
57
|
+
REPORT_PATH="$TMP_DIR/report.md"
|
|
58
|
+
printf '%s\n' "$DEEP_OUTPUT" > "$DEEP_PATH"
|
|
59
|
+
"$VALIDATE_SCHEMA" "$REPO_ROOT/docs/schemas/inspect-deep-dive.v1.schema.json" "$DEEP_PATH"
|
|
60
|
+
|
|
61
|
+
REPORT_OUTPUT="$("$RUN_CLI" report generate --tenant "$TENANT_ID" --input "$DEEP_PATH" --out "$REPORT_PATH" --format markdown)"
|
|
62
|
+
printf '%s\n' "$REPORT_OUTPUT" | jq -e '.schemaVersion == "xyte.report.v1"' >/dev/null
|
|
63
|
+
REPORT_META_PATH="$TMP_DIR/report-meta.json"
|
|
64
|
+
printf '%s\n' "$REPORT_OUTPUT" > "$REPORT_META_PATH"
|
|
65
|
+
"$VALIDATE_SCHEMA" "$REPO_ROOT/docs/schemas/report.v1.schema.json" "$REPORT_META_PATH"
|
|
66
|
+
[[ -s "$REPORT_PATH" ]]
|
|
67
|
+
echo "PASS report generation"
|
|
68
|
+
|
|
69
|
+
echo "Validating headless contract..."
|
|
70
|
+
"$SCRIPT_DIR/check_headless.sh" "$TENANT_ID"
|
|
71
|
+
|
|
72
|
+
echo "All agent contracts validated."
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const Ajv2020 = require('ajv/dist/2020').default;
|
|
5
|
+
|
|
6
|
+
function usage() {
|
|
7
|
+
process.stderr.write('Usage: validate_with_schema.js <schema.json> <data.json>\n');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const [, , schemaPathArg, dataPathArg] = process.argv;
|
|
12
|
+
if (!schemaPathArg || !dataPathArg) {
|
|
13
|
+
usage();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const schemaPath = path.resolve(schemaPathArg);
|
|
17
|
+
const dataPath = path.resolve(dataPathArg);
|
|
18
|
+
|
|
19
|
+
const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
|
|
20
|
+
const data = JSON.parse(fs.readFileSync(dataPath, 'utf8'));
|
|
21
|
+
const ajv = new Ajv2020({ strict: false });
|
|
22
|
+
const validate = ajv.compile(schema);
|
|
23
|
+
|
|
24
|
+
if (!validate(data)) {
|
|
25
|
+
process.stderr.write(`Schema validation failed for ${dataPath}\n`);
|
|
26
|
+
process.stderr.write(`${JSON.stringify(validate.errors, null, 2)}\n`);
|
|
27
|
+
process.exit(2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
process.stdout.write(`Schema validation passed: ${path.basename(dataPath)} against ${path.basename(schemaPath)}\n`);
|