@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.
Files changed (251) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +245 -0
  3. package/dist/bin/xyte-cli.d.ts +3 -0
  4. package/dist/bin/xyte-cli.d.ts.map +1 -0
  5. package/dist/bin/xyte-cli.js +18 -0
  6. package/dist/bin/xyte-cli.js.map +1 -0
  7. package/dist/cli/index.d.ts +24 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +1185 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/client/catalog.d.ts +6 -0
  12. package/dist/client/catalog.d.ts.map +1 -0
  13. package/dist/client/catalog.js +32 -0
  14. package/dist/client/catalog.js.map +1 -0
  15. package/dist/client/create-client.d.ts +3 -0
  16. package/dist/client/create-client.d.ts.map +1 -0
  17. package/dist/client/create-client.js +235 -0
  18. package/dist/client/create-client.js.map +1 -0
  19. package/dist/config/connectivity.d.ts +19 -0
  20. package/dist/config/connectivity.d.ts.map +1 -0
  21. package/dist/config/connectivity.js +166 -0
  22. package/dist/config/connectivity.js.map +1 -0
  23. package/dist/config/readiness.d.ts +32 -0
  24. package/dist/config/readiness.d.ts.map +1 -0
  25. package/dist/config/readiness.js +96 -0
  26. package/dist/config/readiness.js.map +1 -0
  27. package/dist/config/retry-policy.d.ts +16 -0
  28. package/dist/config/retry-policy.d.ts.map +1 -0
  29. package/dist/config/retry-policy.js +24 -0
  30. package/dist/config/retry-policy.js.map +1 -0
  31. package/dist/contracts/call-envelope.d.ts +74 -0
  32. package/dist/contracts/call-envelope.d.ts.map +1 -0
  33. package/dist/contracts/call-envelope.js +72 -0
  34. package/dist/contracts/call-envelope.js.map +1 -0
  35. package/dist/contracts/problem.d.ts +11 -0
  36. package/dist/contracts/problem.d.ts.map +1 -0
  37. package/dist/contracts/problem.js +55 -0
  38. package/dist/contracts/problem.js.map +1 -0
  39. package/dist/contracts/versions.d.ts +6 -0
  40. package/dist/contracts/versions.d.ts.map +1 -0
  41. package/dist/contracts/versions.js +9 -0
  42. package/dist/contracts/versions.js.map +1 -0
  43. package/dist/http/errors.d.ts +24 -0
  44. package/dist/http/errors.d.ts.map +1 -0
  45. package/dist/http/errors.js +39 -0
  46. package/dist/http/errors.js.map +1 -0
  47. package/dist/http/transport.d.ts +35 -0
  48. package/dist/http/transport.d.ts.map +1 -0
  49. package/dist/http/transport.js +129 -0
  50. package/dist/http/transport.js.map +1 -0
  51. package/dist/index.d.ts +10 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +23 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/mcp/server.d.ts +12 -0
  56. package/dist/mcp/server.d.ts.map +1 -0
  57. package/dist/mcp/server.js +404 -0
  58. package/dist/mcp/server.js.map +1 -0
  59. package/dist/namespaces/device.d.ts +38 -0
  60. package/dist/namespaces/device.d.ts.map +1 -0
  61. package/dist/namespaces/device.js +36 -0
  62. package/dist/namespaces/device.js.map +1 -0
  63. package/dist/namespaces/organization.d.ts +27 -0
  64. package/dist/namespaces/organization.d.ts.map +1 -0
  65. package/dist/namespaces/organization.js +30 -0
  66. package/dist/namespaces/organization.js.map +1 -0
  67. package/dist/namespaces/partner.d.ts +18 -0
  68. package/dist/namespaces/partner.d.ts.map +1 -0
  69. package/dist/namespaces/partner.js +21 -0
  70. package/dist/namespaces/partner.js.map +1 -0
  71. package/dist/observability/logger.d.ts +3 -0
  72. package/dist/observability/logger.d.ts.map +1 -0
  73. package/dist/observability/logger.js +21 -0
  74. package/dist/observability/logger.js.map +1 -0
  75. package/dist/observability/tracing.d.ts +3 -0
  76. package/dist/observability/tracing.d.ts.map +1 -0
  77. package/dist/observability/tracing.js +26 -0
  78. package/dist/observability/tracing.js.map +1 -0
  79. package/dist/secure/key-slots.d.ts +8 -0
  80. package/dist/secure/key-slots.d.ts.map +1 -0
  81. package/dist/secure/key-slots.js +47 -0
  82. package/dist/secure/key-slots.js.map +1 -0
  83. package/dist/secure/keychain.d.ts +20 -0
  84. package/dist/secure/keychain.d.ts.map +1 -0
  85. package/dist/secure/keychain.js +170 -0
  86. package/dist/secure/keychain.js.map +1 -0
  87. package/dist/secure/profile-store.d.ts +66 -0
  88. package/dist/secure/profile-store.d.ts.map +1 -0
  89. package/dist/secure/profile-store.js +309 -0
  90. package/dist/secure/profile-store.js.map +1 -0
  91. package/dist/spec/public-endpoints.json +1175 -0
  92. package/dist/tui/animation.d.ts +12 -0
  93. package/dist/tui/animation.d.ts.map +1 -0
  94. package/dist/tui/animation.js +41 -0
  95. package/dist/tui/animation.js.map +1 -0
  96. package/dist/tui/app.d.ts +27 -0
  97. package/dist/tui/app.d.ts.map +1 -0
  98. package/dist/tui/app.js +711 -0
  99. package/dist/tui/app.js.map +1 -0
  100. package/dist/tui/assets/logo.d.ts +5 -0
  101. package/dist/tui/assets/logo.d.ts.map +1 -0
  102. package/dist/tui/assets/logo.js +24 -0
  103. package/dist/tui/assets/logo.js.map +1 -0
  104. package/dist/tui/data-loaders.d.ts +33 -0
  105. package/dist/tui/data-loaders.d.ts.map +1 -0
  106. package/dist/tui/data-loaders.js +250 -0
  107. package/dist/tui/data-loaders.js.map +1 -0
  108. package/dist/tui/dispatch.d.ts +14 -0
  109. package/dist/tui/dispatch.d.ts.map +1 -0
  110. package/dist/tui/dispatch.js +44 -0
  111. package/dist/tui/dispatch.js.map +1 -0
  112. package/dist/tui/headless-renderer.d.ts +20 -0
  113. package/dist/tui/headless-renderer.d.ts.map +1 -0
  114. package/dist/tui/headless-renderer.js +598 -0
  115. package/dist/tui/headless-renderer.js.map +1 -0
  116. package/dist/tui/input-controller.d.ts +29 -0
  117. package/dist/tui/input-controller.d.ts.map +1 -0
  118. package/dist/tui/input-controller.js +76 -0
  119. package/dist/tui/input-controller.js.map +1 -0
  120. package/dist/tui/key-wizard.d.ts +29 -0
  121. package/dist/tui/key-wizard.d.ts.map +1 -0
  122. package/dist/tui/key-wizard.js +177 -0
  123. package/dist/tui/key-wizard.js.map +1 -0
  124. package/dist/tui/keymap.d.ts +9 -0
  125. package/dist/tui/keymap.d.ts.map +1 -0
  126. package/dist/tui/keymap.js +29 -0
  127. package/dist/tui/keymap.js.map +1 -0
  128. package/dist/tui/layout.d.ts +16 -0
  129. package/dist/tui/layout.d.ts.map +1 -0
  130. package/dist/tui/layout.js +99 -0
  131. package/dist/tui/layout.js.map +1 -0
  132. package/dist/tui/logger.d.ts +12 -0
  133. package/dist/tui/logger.d.ts.map +1 -0
  134. package/dist/tui/logger.js +83 -0
  135. package/dist/tui/logger.js.map +1 -0
  136. package/dist/tui/navigation.d.ts +26 -0
  137. package/dist/tui/navigation.d.ts.map +1 -0
  138. package/dist/tui/navigation.js +136 -0
  139. package/dist/tui/navigation.js.map +1 -0
  140. package/dist/tui/panes.d.ts +7 -0
  141. package/dist/tui/panes.d.ts.map +1 -0
  142. package/dist/tui/panes.js +34 -0
  143. package/dist/tui/panes.js.map +1 -0
  144. package/dist/tui/runtime.d.ts +34 -0
  145. package/dist/tui/runtime.d.ts.map +1 -0
  146. package/dist/tui/runtime.js +100 -0
  147. package/dist/tui/runtime.js.map +1 -0
  148. package/dist/tui/scene.d.ts +160 -0
  149. package/dist/tui/scene.d.ts.map +1 -0
  150. package/dist/tui/scene.js +424 -0
  151. package/dist/tui/scene.js.map +1 -0
  152. package/dist/tui/screens/config.d.ts +3 -0
  153. package/dist/tui/screens/config.d.ts.map +1 -0
  154. package/dist/tui/screens/config.js +406 -0
  155. package/dist/tui/screens/config.js.map +1 -0
  156. package/dist/tui/screens/dashboard.d.ts +3 -0
  157. package/dist/tui/screens/dashboard.d.ts.map +1 -0
  158. package/dist/tui/screens/dashboard.js +176 -0
  159. package/dist/tui/screens/dashboard.js.map +1 -0
  160. package/dist/tui/screens/devices.d.ts +3 -0
  161. package/dist/tui/screens/devices.d.ts.map +1 -0
  162. package/dist/tui/screens/devices.js +297 -0
  163. package/dist/tui/screens/devices.js.map +1 -0
  164. package/dist/tui/screens/incidents.d.ts +4 -0
  165. package/dist/tui/screens/incidents.d.ts.map +1 -0
  166. package/dist/tui/screens/incidents.js +304 -0
  167. package/dist/tui/screens/incidents.js.map +1 -0
  168. package/dist/tui/screens/setup.d.ts +3 -0
  169. package/dist/tui/screens/setup.d.ts.map +1 -0
  170. package/dist/tui/screens/setup.js +299 -0
  171. package/dist/tui/screens/setup.js.map +1 -0
  172. package/dist/tui/screens/spaces.d.ts +7 -0
  173. package/dist/tui/screens/spaces.d.ts.map +1 -0
  174. package/dist/tui/screens/spaces.js +422 -0
  175. package/dist/tui/screens/spaces.js.map +1 -0
  176. package/dist/tui/screens/tickets.d.ts +9 -0
  177. package/dist/tui/screens/tickets.d.ts.map +1 -0
  178. package/dist/tui/screens/tickets.js +418 -0
  179. package/dist/tui/screens/tickets.js.map +1 -0
  180. package/dist/tui/serialize.d.ts +31 -0
  181. package/dist/tui/serialize.d.ts.map +1 -0
  182. package/dist/tui/serialize.js +183 -0
  183. package/dist/tui/serialize.js.map +1 -0
  184. package/dist/tui/table-format.d.ts +11 -0
  185. package/dist/tui/table-format.d.ts.map +1 -0
  186. package/dist/tui/table-format.js +77 -0
  187. package/dist/tui/table-format.js.map +1 -0
  188. package/dist/tui/tabs.d.ts +4 -0
  189. package/dist/tui/tabs.d.ts.map +1 -0
  190. package/dist/tui/tabs.js +13 -0
  191. package/dist/tui/tabs.js.map +1 -0
  192. package/dist/tui/types.d.ts +37 -0
  193. package/dist/tui/types.d.ts.map +1 -0
  194. package/dist/tui/types.js +3 -0
  195. package/dist/tui/types.js.map +1 -0
  196. package/dist/types/client.d.ts +54 -0
  197. package/dist/types/client.d.ts.map +1 -0
  198. package/dist/types/client.js +3 -0
  199. package/dist/types/client.js.map +1 -0
  200. package/dist/types/endpoints.d.ts +29 -0
  201. package/dist/types/endpoints.d.ts.map +1 -0
  202. package/dist/types/endpoints.js +3 -0
  203. package/dist/types/endpoints.js.map +1 -0
  204. package/dist/types/profile.d.ts +29 -0
  205. package/dist/types/profile.d.ts.map +1 -0
  206. package/dist/types/profile.js +3 -0
  207. package/dist/types/profile.js.map +1 -0
  208. package/dist/utils/config-dir.d.ts +2 -0
  209. package/dist/utils/config-dir.d.ts.map +1 -0
  210. package/dist/utils/config-dir.js +23 -0
  211. package/dist/utils/config-dir.js.map +1 -0
  212. package/dist/utils/error-format.d.ts +4 -0
  213. package/dist/utils/error-format.d.ts.map +1 -0
  214. package/dist/utils/error-format.js +34 -0
  215. package/dist/utils/error-format.js.map +1 -0
  216. package/dist/utils/install-skills.d.ts +38 -0
  217. package/dist/utils/install-skills.d.ts.map +1 -0
  218. package/dist/utils/install-skills.js +117 -0
  219. package/dist/utils/install-skills.js.map +1 -0
  220. package/dist/utils/json-output.d.ts +6 -0
  221. package/dist/utils/json-output.d.ts.map +1 -0
  222. package/dist/utils/json-output.js +30 -0
  223. package/dist/utils/json-output.js.map +1 -0
  224. package/dist/utils/json.d.ts +4 -0
  225. package/dist/utils/json.d.ts.map +1 -0
  226. package/dist/utils/json.js +36 -0
  227. package/dist/utils/json.js.map +1 -0
  228. package/dist/utils/version.d.ts +2 -0
  229. package/dist/utils/version.d.ts.map +1 -0
  230. package/dist/utils/version.js +28 -0
  231. package/dist/utils/version.js.map +1 -0
  232. package/dist/workflows/fleet-insights.d.ts +122 -0
  233. package/dist/workflows/fleet-insights.d.ts.map +1 -0
  234. package/dist/workflows/fleet-insights.js +938 -0
  235. package/dist/workflows/fleet-insights.js.map +1 -0
  236. package/docs/schemas/call-envelope.v1.schema.json +140 -0
  237. package/docs/schemas/headless-frame.v1.schema.json +159 -0
  238. package/docs/schemas/inspect-deep-dive.v1.schema.json +251 -0
  239. package/docs/schemas/inspect-fleet.v1.schema.json +111 -0
  240. package/docs/schemas/report.v1.schema.json +39 -0
  241. package/package.json +75 -0
  242. package/skills/xyte-cli/SKILL.md +181 -0
  243. package/skills/xyte-cli/agents/openai.yaml +4 -0
  244. package/skills/xyte-cli/references/endpoints.md +106 -0
  245. package/skills/xyte-cli/references/headless-contract.md +96 -0
  246. package/skills/xyte-cli/references/tui-flows.md +126 -0
  247. package/skills/xyte-cli/scripts/check_headless.sh +83 -0
  248. package/skills/xyte-cli/scripts/endpoint_filters_report.sh +33 -0
  249. package/skills/xyte-cli/scripts/run_xyte_cli.sh +12 -0
  250. package/skills/xyte-cli/scripts/validate_agent_contracts.sh +72 -0
  251. 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`);