@alwaysai/device-agent 0.0.4 → 0.0.5

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 (191) hide show
  1. package/lib/application-control/backup.d.ts.map +1 -1
  2. package/lib/application-control/backup.js +10 -6
  3. package/lib/application-control/backup.js.map +1 -1
  4. package/lib/application-control/environment-variables.d.ts +9 -0
  5. package/lib/application-control/environment-variables.d.ts.map +1 -0
  6. package/lib/application-control/environment-variables.js +82 -0
  7. package/lib/application-control/environment-variables.js.map +1 -0
  8. package/lib/application-control/index.d.ts +9 -0
  9. package/lib/application-control/index.d.ts.map +1 -0
  10. package/lib/application-control/index.js +27 -0
  11. package/lib/application-control/index.js.map +1 -0
  12. package/lib/application-control/install.d.ts +8 -2
  13. package/lib/application-control/install.d.ts.map +1 -1
  14. package/lib/application-control/install.js +72 -42
  15. package/lib/application-control/install.js.map +1 -1
  16. package/lib/application-control/models.d.ts.map +1 -1
  17. package/lib/application-control/models.js +7 -17
  18. package/lib/application-control/models.js.map +1 -1
  19. package/lib/application-control/status.d.ts +3 -3
  20. package/lib/application-control/status.d.ts.map +1 -1
  21. package/lib/application-control/status.js +19 -20
  22. package/lib/application-control/status.js.map +1 -1
  23. package/lib/application-control/types.d.ts +0 -13
  24. package/lib/application-control/types.d.ts.map +1 -1
  25. package/lib/application-control/utils.d.ts +2 -9
  26. package/lib/application-control/utils.d.ts.map +1 -1
  27. package/lib/application-control/utils.js +13 -28
  28. package/lib/application-control/utils.js.map +1 -1
  29. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +15 -2
  30. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  31. package/lib/cloud-connection/device-agent-cloud-connection.js +200 -27
  32. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  33. package/lib/docker/docker-cmd.js +2 -2
  34. package/lib/docker/docker-cmd.js.map +1 -1
  35. package/lib/docker/docker-compose-cmd.js +2 -2
  36. package/lib/docker/docker-compose-cmd.js.map +1 -1
  37. package/lib/environment.d.ts +2 -0
  38. package/lib/environment.d.ts.map +1 -1
  39. package/lib/environment.js +3 -1
  40. package/lib/environment.js.map +1 -1
  41. package/lib/index.js +10 -8
  42. package/lib/index.js.map +1 -1
  43. package/lib/infrastructure/agent-config.d.ts +73 -0
  44. package/lib/infrastructure/agent-config.d.ts.map +1 -0
  45. package/lib/infrastructure/agent-config.js +186 -0
  46. package/lib/infrastructure/agent-config.js.map +1 -0
  47. package/lib/infrastructure/agent-config.test.d.ts +2 -0
  48. package/lib/infrastructure/agent-config.test.d.ts.map +1 -0
  49. package/lib/infrastructure/agent-config.test.js +135 -0
  50. package/lib/infrastructure/agent-config.test.js.map +1 -0
  51. package/lib/infrastructure/certificates-and-tokens.d.ts +6 -0
  52. package/lib/infrastructure/certificates-and-tokens.d.ts.map +1 -0
  53. package/lib/infrastructure/certificates-and-tokens.js +69 -0
  54. package/lib/infrastructure/certificates-and-tokens.js.map +1 -0
  55. package/lib/{util → infrastructure}/urls.d.ts +0 -0
  56. package/lib/infrastructure/urls.d.ts.map +1 -0
  57. package/lib/{util → infrastructure}/urls.js +3 -3
  58. package/lib/infrastructure/urls.js.map +1 -0
  59. package/lib/root.js +3 -3
  60. package/lib/root.js.map +1 -1
  61. package/lib/subcommands/app/app.d.ts +8 -1
  62. package/lib/subcommands/app/app.d.ts.map +1 -1
  63. package/lib/subcommands/app/app.js +58 -24
  64. package/lib/subcommands/app/app.js.map +1 -1
  65. package/lib/subcommands/app/index.d.ts.map +1 -1
  66. package/lib/subcommands/app/index.js +2 -0
  67. package/lib/subcommands/app/index.js.map +1 -1
  68. package/lib/subcommands/device/device.d.ts +6 -0
  69. package/lib/subcommands/device/device.d.ts.map +1 -0
  70. package/lib/subcommands/device/device.js +62 -0
  71. package/lib/subcommands/device/device.js.map +1 -0
  72. package/lib/subcommands/device/index.d.ts +2 -0
  73. package/lib/subcommands/device/index.d.ts.map +1 -0
  74. package/lib/subcommands/device/index.js +11 -0
  75. package/lib/subcommands/device/index.js.map +1 -0
  76. package/lib/subcommands/get-model-package.d.ts +5 -0
  77. package/lib/subcommands/get-model-package.d.ts.map +1 -0
  78. package/lib/subcommands/get-model-package.js +51 -0
  79. package/lib/subcommands/get-model-package.js.map +1 -0
  80. package/lib/subcommands/index.d.ts +8 -1
  81. package/lib/subcommands/index.d.ts.map +1 -1
  82. package/lib/subcommands/index.js +9 -3
  83. package/lib/subcommands/index.js.map +1 -1
  84. package/lib/subcommands/login.d.ts +3 -2
  85. package/lib/subcommands/login.d.ts.map +1 -1
  86. package/lib/subcommands/login.js +11 -4
  87. package/lib/subcommands/login.js.map +1 -1
  88. package/lib/util/copy-dir.js +3 -3
  89. package/lib/util/copy-dir.js.map +1 -1
  90. package/lib/util/directories.js +5 -5
  91. package/lib/util/directories.js.map +1 -1
  92. package/package.json +19 -14
  93. package/readme.md +176 -79
  94. package/src/application-control/backup.ts +10 -6
  95. package/src/application-control/environment-variables.ts +81 -0
  96. package/src/application-control/index.ts +40 -0
  97. package/src/application-control/install.ts +79 -55
  98. package/src/application-control/models.ts +12 -17
  99. package/src/application-control/status.ts +26 -24
  100. package/src/application-control/types.ts +0 -4
  101. package/src/application-control/utils.ts +10 -25
  102. package/src/cloud-connection/device-agent-cloud-connection.ts +243 -40
  103. package/src/docker/docker-cmd.ts +1 -1
  104. package/src/docker/docker-compose-cmd.ts +1 -1
  105. package/src/environment.ts +2 -0
  106. package/src/index.ts +10 -7
  107. package/src/infrastructure/agent-config.test.ts +143 -0
  108. package/src/infrastructure/agent-config.ts +217 -0
  109. package/src/infrastructure/certificates-and-tokens.ts +71 -0
  110. package/src/{util → infrastructure}/urls.ts +1 -1
  111. package/src/root.ts +3 -3
  112. package/src/subcommands/app/app.ts +57 -19
  113. package/src/subcommands/app/index.ts +4 -0
  114. package/src/subcommands/device/device.ts +63 -0
  115. package/src/subcommands/device/index.ts +8 -0
  116. package/src/subcommands/get-model-package.ts +60 -0
  117. package/src/subcommands/index.ts +9 -3
  118. package/src/subcommands/login.ts +11 -4
  119. package/src/util/copy-dir.ts +1 -1
  120. package/src/util/directories.ts +8 -8
  121. package/lib/constants.d.ts +0 -13
  122. package/lib/constants.d.ts.map +0 -1
  123. package/lib/constants.js +0 -18
  124. package/lib/constants.js.map +0 -1
  125. package/lib/subcommands/device-control.d.ts +0 -2
  126. package/lib/subcommands/device-control.d.ts.map +0 -1
  127. package/lib/subcommands/device-control.js +0 -19
  128. package/lib/subcommands/device-control.js.map +0 -1
  129. package/lib/util/spawner/gnu-spawner.d.ts +0 -9
  130. package/lib/util/spawner/gnu-spawner.d.ts.map +0 -1
  131. package/lib/util/spawner/gnu-spawner.js +0 -102
  132. package/lib/util/spawner/gnu-spawner.js.map +0 -1
  133. package/lib/util/spawner/js-spawner.d.ts +0 -5
  134. package/lib/util/spawner/js-spawner.d.ts.map +0 -1
  135. package/lib/util/spawner/js-spawner.js +0 -89
  136. package/lib/util/spawner/js-spawner.js.map +0 -1
  137. package/lib/util/spawner/types.d.ts +0 -28
  138. package/lib/util/spawner/types.d.ts.map +0 -1
  139. package/lib/util/spawner/types.js +0 -3
  140. package/lib/util/spawner/types.js.map +0 -1
  141. package/lib/util/spawner-base/index.d.ts +0 -17
  142. package/lib/util/spawner-base/index.d.ts.map +0 -1
  143. package/lib/util/spawner-base/index.js +0 -30
  144. package/lib/util/spawner-base/index.js.map +0 -1
  145. package/lib/util/spawner-base/run-foreground-sync.d.ts +0 -3
  146. package/lib/util/spawner-base/run-foreground-sync.d.ts.map +0 -1
  147. package/lib/util/spawner-base/run-foreground-sync.js +0 -18
  148. package/lib/util/spawner-base/run-foreground-sync.js.map +0 -1
  149. package/lib/util/spawner-base/run-foreground.d.ts +0 -3
  150. package/lib/util/spawner-base/run-foreground.d.ts.map +0 -1
  151. package/lib/util/spawner-base/run-foreground.js +0 -49
  152. package/lib/util/spawner-base/run-foreground.js.map +0 -1
  153. package/lib/util/spawner-base/run-streaming.d.ts +0 -4
  154. package/lib/util/spawner-base/run-streaming.d.ts.map +0 -1
  155. package/lib/util/spawner-base/run-streaming.js +0 -35
  156. package/lib/util/spawner-base/run-streaming.js.map +0 -1
  157. package/lib/util/spawner-base/run.d.ts +0 -4
  158. package/lib/util/spawner-base/run.d.ts.map +0 -1
  159. package/lib/util/spawner-base/run.js +0 -56
  160. package/lib/util/spawner-base/run.js.map +0 -1
  161. package/lib/util/urls.d.ts.map +0 -1
  162. package/lib/util/urls.js.map +0 -1
  163. package/lib/web/index.html +0 -229
  164. package/lib/web/static/Karla.css +0 -18
  165. package/lib/web/static/bootstrap-4.3.1.min.css +0 -7
  166. package/lib/web/static/bootstrap-4.3.1.min.js +0 -7
  167. package/lib/web/static/favicon.ico +0 -0
  168. package/lib/web/static/jquery-3.3.1.slim.min.js +0 -2
  169. package/lib/web/static/popper-1.14.7.min.js +0 -5
  170. package/lib/web/web-interface.d.ts +0 -2
  171. package/lib/web/web-interface.d.ts.map +0 -1
  172. package/lib/web/web-interface.js +0 -75
  173. package/lib/web/web-interface.js.map +0 -1
  174. package/src/constants.ts +0 -22
  175. package/src/subcommands/device-control.ts +0 -16
  176. package/src/util/spawner/gnu-spawner.ts +0 -114
  177. package/src/util/spawner/js-spawner.ts +0 -110
  178. package/src/util/spawner/types.ts +0 -28
  179. package/src/util/spawner-base/index.ts +0 -28
  180. package/src/util/spawner-base/run-foreground-sync.ts +0 -16
  181. package/src/util/spawner-base/run-foreground.ts +0 -49
  182. package/src/util/spawner-base/run-streaming.ts +0 -40
  183. package/src/util/spawner-base/run.ts +0 -60
  184. package/src/web/index.html +0 -229
  185. package/src/web/static/Karla.css +0 -18
  186. package/src/web/static/bootstrap-4.3.1.min.css +0 -7
  187. package/src/web/static/bootstrap-4.3.1.min.js +0 -7
  188. package/src/web/static/favicon.ico +0 -0
  189. package/src/web/static/jquery-3.3.1.slim.min.js +0 -2
  190. package/src/web/static/popper-1.14.7.min.js +0 -5
  191. package/src/web/web-interface.ts +0 -85
@@ -1,22 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCredentialsFilePath = exports.getRootCertificateFilePath = exports.getCertificateFilePath = exports.getPrivateKeyFilePath = void 0;
4
+ const constants_1 = require("alwaysai/lib/constants");
4
5
  const path_1 = require("path");
5
- const constants_1 = require("../constants");
6
6
  function getPrivateKeyFilePath() {
7
- return (0, path_1.join)(constants_1.CERT_AND_KEY_DIR, constants_1.DEVICE_PRIVATE_KEY_FILE_NAME);
7
+ return (0, path_1.join)(constants_1.LOCAL_CERT_AND_KEY_DIR, constants_1.DEVICE_PRIVATE_KEY_FILE_NAME);
8
8
  }
9
9
  exports.getPrivateKeyFilePath = getPrivateKeyFilePath;
10
10
  function getCertificateFilePath() {
11
- return (0, path_1.join)(constants_1.CERT_AND_KEY_DIR, constants_1.DEVICE_CERTIFICATE_FILE_NAME);
11
+ return (0, path_1.join)(constants_1.LOCAL_CERT_AND_KEY_DIR, constants_1.DEVICE_CERTIFICATE_FILE_NAME);
12
12
  }
13
13
  exports.getCertificateFilePath = getCertificateFilePath;
14
14
  function getRootCertificateFilePath() {
15
- return (0, path_1.join)(constants_1.CERT_AND_KEY_DIR, constants_1.DEVICE_ROOT_CERT_FILE_NAME);
15
+ return (0, path_1.join)(constants_1.LOCAL_CERT_AND_KEY_DIR, constants_1.DEVICE_ROOT_CERT_FILE_NAME);
16
16
  }
17
17
  exports.getRootCertificateFilePath = getRootCertificateFilePath;
18
18
  function getCredentialsFilePath() {
19
- return (0, path_1.join)(constants_1.TOKEN_DIR, constants_1.DEVICE_TOKEN_FILE_NAME);
19
+ return (0, path_1.join)(constants_1.LOCAL_AAI_CFG_DIR, constants_1.DEVICE_TOKEN_FILE_NAME);
20
20
  }
21
21
  exports.getCredentialsFilePath = getCredentialsFilePath;
22
22
  //# sourceMappingURL=directories.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"directories.js","sourceRoot":"","sources":["../../src/util/directories.ts"],"names":[],"mappings":";;;AAAA,+BAA4B;AAC5B,4CAOsB;AAEtB,SAAgB,qBAAqB;IACnC,OAAO,IAAA,WAAI,EAAC,4BAAgB,EAAE,wCAA4B,CAAC,CAAC;AAC9D,CAAC;AAFD,sDAEC;AAED,SAAgB,sBAAsB;IACpC,OAAO,IAAA,WAAI,EAAC,4BAAgB,EAAE,wCAA4B,CAAC,CAAC;AAC9D,CAAC;AAFD,wDAEC;AAED,SAAgB,0BAA0B;IACxC,OAAO,IAAA,WAAI,EAAC,4BAAgB,EAAE,sCAA0B,CAAC,CAAC;AAC5D,CAAC;AAFD,gEAEC;AAED,SAAgB,sBAAsB;IACpC,OAAO,IAAA,WAAI,EAAC,qBAAS,EAAE,kCAAsB,CAAC,CAAC;AACjD,CAAC;AAFD,wDAEC"}
1
+ {"version":3,"file":"directories.js","sourceRoot":"","sources":["../../src/util/directories.ts"],"names":[],"mappings":";;;AAAA,sDAOgC;AAChC,+BAA4B;AAE5B,SAAgB,qBAAqB;IACnC,OAAO,IAAA,WAAI,EAAC,kCAAsB,EAAE,wCAA4B,CAAC,CAAC;AACpE,CAAC;AAFD,sDAEC;AAED,SAAgB,sBAAsB;IACpC,OAAO,IAAA,WAAI,EAAC,kCAAsB,EAAE,wCAA4B,CAAC,CAAC;AACpE,CAAC;AAFD,wDAEC;AAED,SAAgB,0BAA0B;IACxC,OAAO,IAAA,WAAI,EAAC,kCAAsB,EAAE,sCAA0B,CAAC,CAAC;AAClE,CAAC;AAFD,gEAEC;AAED,SAAgB,sBAAsB;IACpC,OAAO,IAAA,WAAI,EAAC,6BAAiB,EAAE,kCAAsB,CAAC,CAAC;AACzD,CAAC;AAFD,wDAEC"}
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@alwaysai/device-agent",
3
3
  "description": "The alwaysAI Device Agent",
4
- "version": "0.0.4",
5
- "main": "lib/exports.js",
6
- "types": "lib/exports.d.ts",
4
+ "version": "0.0.5",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "tag": "next"
10
+ },
7
11
  "bin": {
8
12
  "aai-agent": "lib/index.js"
9
13
  },
@@ -12,34 +16,35 @@
12
16
  "node": ">=16.0.0"
13
17
  },
14
18
  "scripts": {
15
- "build": "tsc --project tsconfig.build.json && copyfiles -u 1 src/web/*.html src/web/static/* lib/",
19
+ "build": "tsc --project tsconfig.build.json",
16
20
  "clean": "rimraf lib packages",
17
21
  "build:clean": "npm run clean && npm run build",
18
22
  "build:watch": "tsc --project . --watch",
19
23
  "lint": "tslint --project tsconfig.build.json",
20
24
  "lint:fix": "npm run lint -- --fix",
21
- "test": "npm run lint",
25
+ "test": "npm run test:unit",
22
26
  "test:unit": "jest --coverage src",
23
27
  "test:watch": "npm run test:unit -- --watch",
24
28
  "preversion": "npm test && npm run build:clean",
25
29
  "postversion": "npm publish"
26
30
  },
27
31
  "dependencies": {
28
- "@alwaysai/alwayscli": "0.3.0",
29
- "@alwaysai/config-nodejs": "0.0.2",
32
+ "@alwaysai/alwayscli": "0.3.1",
33
+ "@alwaysai/config-nodejs": "0.1.0",
30
34
  "@carnesen/coded-error": "0.4.0",
35
+ "@alwaysai/device-agent-schemas": "0.0.2",
31
36
  "@types/mkdirp": "1.0.2",
32
37
  "@types/pump": "1.1.1",
33
38
  "@types/rimraf": "3.0.2",
34
39
  "@types/signal-exit": "3.0.1",
35
40
  "@types/tar": "6.1.1",
41
+ "ajv": "8.11.0",
42
+ "alwaysai": "1.8.0",
36
43
  "aws-iot-device-sdk": "2.2.12",
37
- "alwaysai": "1.6.0",
38
44
  "docker-compose": "0.23.17",
39
45
  "express": "4.17.3",
40
- "fp-ts": "2.11.5",
41
- "io-ts": "2.2.16",
42
46
  "mkdirp": "1.0.4",
47
+ "node-fetch": "2.6.1",
43
48
  "node-os-utils": "1.3.6",
44
49
  "pump": "3.0.0",
45
50
  "rimraf": "3.0.2",
@@ -48,17 +53,17 @@
48
53
  "tar": "6.1.11",
49
54
  "tree-kill": "1.2.2",
50
55
  "winston": "3.3.3",
51
- "winston-daily-rotate-file": "4.5.5"
56
+ "winston-daily-rotate-file": "4.5.5",
57
+ "yaml": "2.1.1"
52
58
  },
53
59
  "devDependencies": {
54
- "@alwaysai/tsconfig": "0.0.0",
55
- "@alwaysai/tslint-config": "0.0.3",
60
+ "@alwaysai/tsconfig": "0.0.1",
61
+ "@alwaysai/tslint-config": "0.0.4",
56
62
  "@carnesen/run-and-catch": "0.4.3",
57
63
  "@types/jest": "27.0.3",
58
64
  "@types/node": "16.11.12",
59
65
  "@types/sinon": "10.0.6",
60
66
  "aws-sdk": "^2.1046.0",
61
- "copyfiles": "^2.4.1",
62
67
  "cp-cli": "2.0.0",
63
68
  "get-stream": "6.0.1",
64
69
  "jest": "27.4.3",
package/readme.md CHANGED
@@ -1,122 +1,219 @@
1
1
  # alwaysAI Device Agent
2
2
 
3
+ The alwaysAI Device Agent is a tool that runs on an alwaysAI device provisioned
4
+ for production remote deployment. It enables management of one or more alwaysAI
5
+ apps on a particular device via a command line interface.
6
+
7
+ Note that the Device Agent is still in an experimental phase and these commands
8
+ are likely to change. This guide will be updated with the latest usage as things
9
+ change.
10
+
3
11
  ## System Requirements
4
12
 
5
- 1. Preferably running Linux, but can hack it to work on Mac too
6
- 2. Docker installed with user access (On Linux: `$ sudo usermod -aG docker $USER`, nothing needed for Mac)
7
- 3. Docker Compose installed
8
- 4. npm and node (for build and test)
13
+ * Recent version of Debian or Ubuntu
14
+ * `npm` >= 7.0.0
15
+ * `node` >= 16.0.0
16
+ * Recent version of `docker` with user access
17
+ * On Linux: `$ sudo usermod -aG docker $USER`
18
+ * Recent version of `docker-compose`
19
+ * `curl` installed.
20
+
21
+ ## Provision Device
22
+
23
+ ### Provision the device
24
+
25
+ If you're system already meets all the system requirements, you can simply install the device agent via `npm`:
26
+
27
+ ```
28
+ sudo npm install -g @alwaysai/device-agent@latest
29
+ ```
9
30
 
10
- ## Lint and Build
31
+ Otherwise, you can run the provision script to install the agent and its dependencies:
11
32
 
12
33
  ```
13
- $ npm run lint:fix
14
- $ npm run build
34
+ curl -fsSL https://alwaysai-artifacts-prod.s3.us-west-1.amazonaws.com/device-agent/install-device-agent.sh | sudo -E bash -
15
35
  ```
16
36
 
17
- ## Usage
37
+ The Device Agent will be available in the terminal as `aai-agent`.
18
38
 
19
- There are three modes of operation: CLI, which is great for testing new features, the device-hosted web dashboard, and the IoT Core cloud connection.
39
+ Next, log in to the Device Agent with the following command:
20
40
 
21
- To enable the cloud IoT Core connection, set the following environment variable:
22
41
  ```
23
- export ALWAYSAI_DEVICE_AGENT_MODE="cloud"
42
+ aai-agent login --email <username> --password <password> [--device <device_id>]
24
43
  ```
25
44
 
26
- To enable the device-hosted web dashboard, set the following environment variable:
45
+ Note that if you already have a device registered with the alwaysAI cloud, you
46
+ can optionally provide that device ID in the login command. If you don't yet
47
+ have a device configured, follow the next step to initialize the device.
48
+
49
+ ### Initialize the alwaysAI device
50
+
51
+ After logging in, run the following command to initialize the current device as
52
+ an alwaysAI device:
53
+
27
54
  ```
28
- export ALWAYSAI_DEVICE_AGENT_MODE="web"
55
+ $ aai-agent device init --name <name> [--description <description>]
29
56
  ```
30
57
 
31
- Any other value will run the CLI.
58
+ For example:
32
59
 
33
- On Mac you need to override the OS to remove some usage restrictions:
34
60
  ```
35
- export ALWAYSAI_OS_PLATFORM="linux"
61
+ $ aai-agent device init --name test-dev-1 --description "Device for testing alwaysAI Device Agent"
36
62
  ```
37
63
 
38
- ### CLI
64
+ ## Run an alwaysAI application on your device
65
+
66
+ ### Publish an application release and install on device
67
+
68
+ First, you must publish your application to the alwaysAI cloud. From the root
69
+ of your application directory (where the `alwaysai.app.json` file is) on your
70
+ development host:
39
71
 
40
- Here are the available commands:
41
72
  ```
42
- $ node lib --help
43
- Starting alwaysAI Device Agent
44
- Usage: aai-agent <subcommand> ...
73
+ aai app configure
74
+ aai app publish
75
+ ```
45
76
 
46
- Manage your alwaysAI production device
77
+ The output of the final command will give you the release hash that was
78
+ published. You can run `aai release list --project <project_id>` to list all
79
+ release versions for the project, where project ID can be found in the
80
+ `alwaysai.project.json` file.
47
81
 
48
- Subcommands:
82
+ Now you can install the application on the device using the device agent. Run
83
+ the following on the device where the Device Agent is installed:
49
84
 
50
- login : Login to alwaysAI (this is meant for scripted environments)
51
- app list : List all installed apps
52
- app list-releases : List all releases for a given app
53
- app list-latest-release : List the latest release hash for a given app
54
- app install : Install an alwaysAI app from a project
55
- app status : Get the status of an installed alwaysAI app
56
- app start : Start an installed alwaysAI app
57
- app logs : Get logs for an application
58
- app stop : Stop a running alwaysAI app
59
- app uninstall : Remove an alwaysAI app
60
- app rollback : Rollback an alwaysAI app to the previous version
61
- app add-model : Add a model to an alwaysAI app
62
- app remove-model : Remove a model from an alwaysAI app
63
- app update-models : Update all models for an alwaysAI app
64
- get-device-info : Get device info
85
+ ```
86
+ aai-agent app install --project <project_id> [--release <release_hash>]
87
+ ```
88
+
89
+ ### Control the application
90
+
91
+ Run the following commands on the device where the Device Agent is installed:
92
+
93
+ Get application status:
94
+ ```
95
+ aai-agent app status --project <project_id>
65
96
  ```
66
97
 
67
- To install a test app, run:
98
+ Start the application:
68
99
  ```
69
- $ node lib install-test-app
100
+ aai-agent app start --project <project_id>
70
101
  ```
71
102
 
72
- The test app has the project ID 16ad11bb-8c3a-4a15-923e-49f7a8311dc6.
103
+ Show the application logs:
104
+ ```
105
+ aai-agent app logs --project <project_id>
106
+ ```
73
107
 
74
- Now you can start, check the status, and stop using the commands:
108
+ Stop the application:
75
109
  ```
76
- $ node lib start-app --project 16ad11bb-8c3a-4a15-923e-49f7a8311dc6
77
- Starting alwaysAI Device Agent
78
- Starting app...
79
- {
80
- exitCode: 0,
81
- err: 'Starting 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1 ... \r\n' +
82
- 'Starting 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1 ... done\r\n',
83
- out: ''
84
- }
85
- $ node lib get-app-status --project 16ad11bb-8c3a-4a15-923e-49f7a8311dc6
86
- Starting alwaysAI Device Agent
87
- [
88
- {
89
- name: '16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1',
90
- command: 'tail -f /dev/null',
91
- state: 'Up',
92
- ports: []
93
- }
94
- ]
95
- $ node lib stop-app --project 16ad11bb-8c3a-4a15-923e-49f7a8311dc6
96
- Starting alwaysAI Device Agent
97
- {
98
- exitCode: 0,
99
- err: 'Stopping 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1 ... \r\n' +
100
- 'Stopping 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1 ... done\r\n' +
101
- 'Removing 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1 ... \r\n' +
102
- 'Removing 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_alwaysai_1 ... done\r\n' +
103
- 'Removing network 16ad11bb-8c3a-4a15-923e-49f7a8311dc6_default\n',
104
- out: ''
105
- }
110
+ aai-agent app stop --project <project_id>
111
+ ```
112
+
113
+ Uninstall the application:
114
+ ```
115
+ aai-agent app uninstall --project <project_id>
116
+ ```
117
+
118
+ ### Manage application models
119
+
120
+ There are several ways to manage the models for your application.
121
+
122
+ #### Update models to new version of the same model ID
123
+
124
+ If a new version of a model is published for an existing model ID, and an
125
+ application is already configured to be using that model ID, updating to the
126
+ new model can simply be done with:
127
+
128
+ ```
129
+ aai-agent app stop --project <project_id>
130
+ aai-agent app update-models --project <project_id>
131
+ aai-agent app start --project <project_id>
132
+ ```
133
+
134
+ #### Replace models for an application for new ID
135
+
136
+ If you'd like to install an entirely new model to an application, replacing the
137
+ model the app was originally configured with, run the following command:
138
+
139
+ ```
140
+ aai-agent app stop --project <project_id>
141
+ aai-agent app replace-models --project <project_id> --models <model_id_1> [<model_id_2> ...]
142
+ aai-agent app start --project <project_id>
143
+ ```
144
+
145
+ If you plan on using this method, you can make your application source model ID
146
+ agnostic by providing the model ID to edgeIQ in the following way:
147
+
148
+ Select the first model in the config list:
149
+ ```
150
+ obj_detect = edgeiq.ObjectDetection(edgeiq._globals.MODEL_ID_LIST[0])
151
+ ```
152
+
153
+ #### Manually download a model package
154
+
155
+ To download a model package from the alwaysAI cloud and unpack to a specific directory, run:
156
+
106
157
  ```
158
+ aai-agent get-model-package <model ID> [--path <destination path>]
159
+ ```
160
+
161
+ For example, to download `alwaysai/yolo_v3` to `~/models` run:
162
+
163
+ ```
164
+ aai-agent get-model-package alwaysai/yolo_v3 --path ~/models
165
+ ```
166
+
167
+ Once the command completes, you'll see the model package in the
168
+ `~/models/alwaysai/yolo_v3` directory.
107
169
 
108
- ### Web Dashboard
170
+ ### Set and update environment variables
109
171
 
110
- You can start the web dashboard by running:
172
+ The Device Agent enables you to set and update environment variables for all
173
+ services or a single service of you application.
111
174
 
112
175
  ```
113
- node lib
176
+ aai-agent app set-env <key=val> --project <project_id> [--service <service>]
114
177
  ```
115
178
 
116
- And clicking the link that comes up.
179
+ For example, to set the following environment variable for the `alwaysai`
180
+ service run the following command on the device:
117
181
 
118
- If you are developing new functionality for the cli in tandem with the device agent, you can run
119
182
  ```
120
- npm i --save /path/to/your/cli/repo
183
+ aai-agent app set-env TEST_ENV=1 --project <project_id> --service alwaysai
121
184
  ```
122
- Remember to not commit the package.json, or revert it when you are done developing a feature
185
+
186
+ ## Device Agent Commands
187
+
188
+ ```
189
+ $ aai-agent --help
190
+ Starting alwaysAI Device Agent
191
+ Usage: aai-agent <subcommand> ...
192
+
193
+ Manage your alwaysAI production device
194
+
195
+ Subcommands:
196
+
197
+ login : Login to alwaysAI (this is meant for scripted environments)
198
+ app list : List all installed apps
199
+ app list-releases : List all releases for a given app
200
+ app list-latest-release : List the latest release hash for a given app
201
+ app install : Install an alwaysAI app from a project
202
+ app status : Get the status of an installed alwaysAI app
203
+ app start : Start an installed alwaysAI app
204
+ app stop : Stop a running alwaysAI app
205
+ app restart : Restart running alwaysAI app
206
+ app logs : Get logs for an application
207
+ app uninstall : Remove an alwaysAI app
208
+ app rollback : Rollback an alwaysAI app to the previous version
209
+ app show-models : Show the application models
210
+ app add-model : Add a model to an alwaysAI app
211
+ app remove-model : Remove a model from an alwaysAI app
212
+ app replace-models : Replace all models of an alwaysAI app with new models
213
+ app update-models : Update all models for an alwaysAI app
214
+ app get-all-envs : Get environment variables for an application
215
+ app set-env : Set environment variables for a service
216
+ device init : Initialize device
217
+ device get-info : Get device info
218
+ get-model-package : Download and unpack a model package
219
+ ```
@@ -1,8 +1,8 @@
1
1
  import * as rimraf from 'rimraf';
2
- import * as fs from 'fs';
3
2
 
4
3
  import { copyDir } from '../util/copy-dir';
5
4
  import { buildApp, getAppDir } from './utils';
5
+ import { AgentConfigFile } from '../infrastructure/agent-config';
6
6
 
7
7
  export const BACKUP_EXT = '.bak';
8
8
 
@@ -10,19 +10,23 @@ export async function createAppBackup(props: { projectId: string }) {
10
10
  const { projectId } = props;
11
11
  const appDir = getAppDir(projectId);
12
12
  const backupAppDir = `${appDir}${BACKUP_EXT}`;
13
+ rimraf.sync(backupAppDir);
13
14
  await copyDir({ srcPath: appDir, destPath: backupAppDir });
15
+ await AgentConfigFile().setAppBackup({ projectId });
14
16
  console.log(`Backed up app ${projectId} to ${backupAppDir}`);
15
17
  }
16
18
 
17
19
  export async function rollbackApp(props: { projectId: string }) {
18
20
  const { projectId } = props;
19
- const appDir = getAppDir(projectId);
20
- const backupAppDir = `${appDir}${BACKUP_EXT}`;
21
- if (!fs.existsSync(backupAppDir)) {
21
+ const config = await AgentConfigFile().getAppBackup({ projectId });
22
+ if (!config) {
22
23
  throw new Error(`Backup doesn't exist for ${projectId}`);
23
24
  }
25
+ const appDir = getAppDir(projectId);
26
+ const backupAppDir = `${appDir}${BACKUP_EXT}`;
24
27
  rimraf.sync(appDir);
25
- await copyDir({ srcPath: `${appDir}${BACKUP_EXT}`, destPath: appDir });
28
+ await copyDir({ srcPath: backupAppDir, destPath: appDir });
26
29
  await buildApp({ appDir });
27
- console.log(`Rolled back app ${projectId} to previous version`);
30
+ await AgentConfigFile().setAppInstalled({ projectId, version: config.version });
31
+ console.log(`Rolled back app ${projectId} to ${config.version}`);
28
32
  }
@@ -0,0 +1,81 @@
1
+ import { JsSpawner } from 'alwaysai/lib/util';
2
+ import compose from 'docker-compose';
3
+ import { parse, stringify } from 'yaml';
4
+ import { AgentConfigFile } from '../infrastructure/agent-config';
5
+ import { getAppDir } from './utils';
6
+
7
+ export async function setEnv(props: {
8
+ projectId: string;
9
+ vars: string[];
10
+ service?: string;
11
+ }) {
12
+ const { projectId, vars } = props;
13
+ if (!AgentConfigFile().isAppReady({ projectId })) {
14
+ throw new Error(`App ${projectId} is not ready!`);
15
+ }
16
+ const appDir = getAppDir(projectId);
17
+ const spawner = JsSpawner({ path: appDir });
18
+ const composeContents = await spawner.readFile('docker-compose.yaml');
19
+ const composeParsed = parse(composeContents);
20
+ if ('services' in composeParsed) {
21
+ let services: string[] = Object.keys(composeParsed['services']);
22
+ if (props.service) {
23
+ console.log(services);
24
+ if (services.includes(props.service)) {
25
+ services = [props.service];
26
+ } else {
27
+ throw new Error(`Service ${props.service} not found in ${services}`);
28
+ }
29
+ }
30
+ for (const s of services) {
31
+ const service = composeParsed['services'][s];
32
+ // The environment field overrides the env files, so by appending to
33
+ // the environment list we can assure the value will be used
34
+ if ('environment' in service) {
35
+ const environment: string[] = service['environment'];
36
+ composeParsed['services'][s]['environment'] = environment.concat(vars);
37
+ } else {
38
+ composeParsed['services'][s]['environment'] = vars;
39
+ }
40
+ }
41
+ }
42
+ const composeOutput = stringify(composeParsed);
43
+ // Validate new contents
44
+ await compose.config({ cwd: appDir, configAsString: composeOutput });
45
+ await spawner.writeFile('docker-compose.yaml', composeOutput);
46
+ }
47
+
48
+ export async function getAllEnvs(props: { projectId: string }) {
49
+ const { projectId } = props;
50
+ if (!AgentConfigFile().isAppReady({ projectId })) {
51
+ throw new Error(`App ${projectId} is not ready!`);
52
+ }
53
+ const appDir = getAppDir(projectId);
54
+ const spawner = JsSpawner({ path: appDir });
55
+ const envVars = {};
56
+ const composeContents = await spawner.readFile('docker-compose.yaml');
57
+ const composeParsed = parse(composeContents);
58
+ if ('services' in composeParsed) {
59
+ const services = Object.keys(composeParsed['services']);
60
+ for (const s of services) {
61
+ envVars[s] = [];
62
+ const service = composeParsed['services'][s];
63
+ if ('env_file' in service) {
64
+ const envFiles: string[] = service['env_file'];
65
+ for (const ef of envFiles) {
66
+ envVars[s] = envVars[s].concat((await spawner.readFile(ef)).split('\n'));
67
+ }
68
+ }
69
+ if ('environment' in service) {
70
+ const environment: string[] = service['environment'];
71
+ envVars[s] = envVars[s].concat(environment);
72
+ }
73
+ // Filter out empty lines and comment lines
74
+ envVars[s] = envVars[s].filter((v) => {
75
+ return v !== '' && !v.includes('#');
76
+ });
77
+ }
78
+ }
79
+
80
+ return envVars;
81
+ }
@@ -0,0 +1,40 @@
1
+ import { installApp, uninstallApp } from './install';
2
+ import { rollbackApp } from './backup';
3
+ import {
4
+ listAppReleases,
5
+ listAppLatestRelease,
6
+ getAppStatus,
7
+ startApp,
8
+ getAppLogs,
9
+ stopApp,
10
+ restartApp,
11
+ } from './status';
12
+ import { ModelDetails } from './types';
13
+ import { getAllEnvs, setEnv } from './environment-variables';
14
+
15
+ export {
16
+ installApp,
17
+ uninstallApp,
18
+ rollbackApp,
19
+ listAppReleases,
20
+ listAppLatestRelease,
21
+ getAppStatus,
22
+ startApp,
23
+ getAppLogs,
24
+ stopApp,
25
+ restartApp,
26
+ ModelDetails,
27
+ getAllEnvs,
28
+ setEnv,
29
+ };
30
+
31
+ // CLI-mode only
32
+ import {
33
+ addModel,
34
+ getAppModels,
35
+ removeModel,
36
+ replaceModels,
37
+ updateModels,
38
+ } from './models';
39
+
40
+ export { addModel, getAppModels, removeModel, replaceModels, updateModels };