@alwaysai/device-agent 0.0.12 → 0.0.14

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 (227) hide show
  1. package/lib/application-control/backup.d.ts.map +1 -1
  2. package/lib/application-control/backup.js +11 -5
  3. package/lib/application-control/backup.js.map +1 -1
  4. package/lib/application-control/config.d.ts +12 -4
  5. package/lib/application-control/config.d.ts.map +1 -1
  6. package/lib/application-control/config.js +59 -16
  7. package/lib/application-control/config.js.map +1 -1
  8. package/lib/application-control/environment-variables.d.ts.map +1 -1
  9. package/lib/application-control/environment-variables.js.map +1 -1
  10. package/lib/application-control/index.d.ts +5 -5
  11. package/lib/application-control/index.d.ts.map +1 -1
  12. package/lib/application-control/index.js +4 -6
  13. package/lib/application-control/index.js.map +1 -1
  14. package/lib/application-control/install.d.ts +1 -1
  15. package/lib/application-control/install.d.ts.map +1 -1
  16. package/lib/application-control/install.js +58 -57
  17. package/lib/application-control/install.js.map +1 -1
  18. package/lib/application-control/models.d.ts +7 -5
  19. package/lib/application-control/models.d.ts.map +1 -1
  20. package/lib/application-control/models.js +78 -57
  21. package/lib/application-control/models.js.map +1 -1
  22. package/lib/application-control/status.d.ts +0 -6
  23. package/lib/application-control/status.d.ts.map +1 -1
  24. package/lib/application-control/status.js +21 -33
  25. package/lib/application-control/status.js.map +1 -1
  26. package/lib/application-control/utils.d.ts +3 -2
  27. package/lib/application-control/utils.d.ts.map +1 -1
  28. package/lib/application-control/utils.js +54 -34
  29. package/lib/application-control/utils.js.map +1 -1
  30. package/lib/cloud-connection/app-install-status.d.ts +16 -0
  31. package/lib/cloud-connection/app-install-status.d.ts.map +1 -0
  32. package/lib/cloud-connection/app-install-status.js +53 -0
  33. package/lib/cloud-connection/app-install-status.js.map +1 -0
  34. package/lib/cloud-connection/bootstrap-provision.d.ts +2 -0
  35. package/lib/cloud-connection/bootstrap-provision.d.ts.map +1 -0
  36. package/lib/cloud-connection/bootstrap-provision.js +34 -0
  37. package/lib/cloud-connection/bootstrap-provision.js.map +1 -0
  38. package/lib/cloud-connection/cmd-status.d.ts +16 -0
  39. package/lib/cloud-connection/cmd-status.d.ts.map +1 -0
  40. package/lib/cloud-connection/cmd-status.js +49 -0
  41. package/lib/cloud-connection/cmd-status.js.map +1 -0
  42. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +21 -34
  43. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  44. package/lib/cloud-connection/device-agent-cloud-connection.js +211 -387
  45. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  46. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  47. package/lib/cloud-connection/device-agent.js +22 -26
  48. package/lib/cloud-connection/device-agent.js.map +1 -1
  49. package/lib/cloud-connection/live-updates-handler.d.ts +34 -0
  50. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -0
  51. package/lib/cloud-connection/live-updates-handler.js +167 -0
  52. package/lib/cloud-connection/live-updates-handler.js.map +1 -0
  53. package/lib/cloud-connection/messages.d.ts +14 -0
  54. package/lib/cloud-connection/messages.d.ts.map +1 -0
  55. package/lib/cloud-connection/messages.js +38 -0
  56. package/lib/cloud-connection/messages.js.map +1 -0
  57. package/lib/cloud-connection/passthrough-handler.d.ts +11 -0
  58. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -0
  59. package/lib/cloud-connection/passthrough-handler.js +59 -0
  60. package/lib/cloud-connection/passthrough-handler.js.map +1 -0
  61. package/lib/cloud-connection/publisher.d.ts +15 -0
  62. package/lib/cloud-connection/publisher.d.ts.map +1 -0
  63. package/lib/cloud-connection/publisher.js +58 -0
  64. package/lib/cloud-connection/publisher.js.map +1 -0
  65. package/lib/cloud-connection/shadow-handler.d.ts +33 -0
  66. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -0
  67. package/lib/cloud-connection/shadow-handler.js +108 -0
  68. package/lib/cloud-connection/shadow-handler.js.map +1 -0
  69. package/lib/cloud-connection/shadow-handler.test.d.ts +2 -0
  70. package/lib/cloud-connection/shadow-handler.test.d.ts.map +1 -0
  71. package/lib/cloud-connection/shadow-handler.test.js +321 -0
  72. package/lib/cloud-connection/shadow-handler.test.js.map +1 -0
  73. package/lib/cloud-connection/shadow.d.ts +16 -0
  74. package/lib/cloud-connection/shadow.d.ts.map +1 -0
  75. package/lib/cloud-connection/shadow.js +36 -0
  76. package/lib/cloud-connection/shadow.js.map +1 -0
  77. package/lib/device-control/device-control.d.ts.map +1 -1
  78. package/lib/device-control/device-control.js +1 -0
  79. package/lib/device-control/device-control.js.map +1 -1
  80. package/lib/docker/docker-cmd.js +1 -1
  81. package/lib/docker/docker-compose-cmd.d.ts.map +1 -1
  82. package/lib/docker/docker-compose-cmd.js +1 -1
  83. package/lib/docker/docker-compose-cmd.js.map +1 -1
  84. package/lib/endpoints.js +10 -10
  85. package/lib/endpoints.js.map +1 -1
  86. package/lib/environment.d.ts +1 -0
  87. package/lib/environment.d.ts.map +1 -1
  88. package/lib/environment.js +2 -1
  89. package/lib/environment.js.map +1 -1
  90. package/lib/infrastructure/agent-config.d.ts +15 -58
  91. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  92. package/lib/infrastructure/agent-config.js +22 -15
  93. package/lib/infrastructure/agent-config.js.map +1 -1
  94. package/lib/infrastructure/agent-config.test.js +25 -23
  95. package/lib/infrastructure/agent-config.test.js.map +1 -1
  96. package/lib/infrastructure/system-id.d.ts +2 -0
  97. package/lib/infrastructure/system-id.d.ts.map +1 -0
  98. package/lib/infrastructure/system-id.js +21 -0
  99. package/lib/infrastructure/system-id.js.map +1 -0
  100. package/lib/infrastructure/tokens-and-device-cfg.d.ts +4 -0
  101. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -0
  102. package/lib/infrastructure/tokens-and-device-cfg.js +27 -0
  103. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -0
  104. package/lib/infrastructure/urls.d.ts.map +1 -1
  105. package/lib/infrastructure/urls.js +3 -3
  106. package/lib/infrastructure/urls.js.map +1 -1
  107. package/lib/local-connection/rabbitmq-connection.d.ts +4 -0
  108. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -0
  109. package/lib/local-connection/rabbitmq-connection.js +58 -0
  110. package/lib/local-connection/rabbitmq-connection.js.map +1 -0
  111. package/lib/root.d.ts.map +1 -1
  112. package/lib/root.js +2 -7
  113. package/lib/root.js.map +1 -1
  114. package/lib/subcommands/app/app.d.ts +2 -1
  115. package/lib/subcommands/app/app.d.ts.map +1 -1
  116. package/lib/subcommands/app/app.js +112 -77
  117. package/lib/subcommands/app/app.js.map +1 -1
  118. package/lib/subcommands/app/index.js +2 -2
  119. package/lib/subcommands/device/clean.d.ts +2 -0
  120. package/lib/subcommands/device/clean.d.ts.map +1 -0
  121. package/lib/subcommands/device/clean.js +29 -0
  122. package/lib/subcommands/device/clean.js.map +1 -0
  123. package/lib/subcommands/device/device.d.ts +1 -1
  124. package/lib/subcommands/device/device.d.ts.map +1 -1
  125. package/lib/subcommands/device/device.js +44 -33
  126. package/lib/subcommands/device/device.js.map +1 -1
  127. package/lib/subcommands/device/index.d.ts.map +1 -1
  128. package/lib/subcommands/device/index.js +2 -1
  129. package/lib/subcommands/device/index.js.map +1 -1
  130. package/lib/subcommands/get-model-package.js +5 -5
  131. package/lib/subcommands/index.d.ts +0 -1
  132. package/lib/subcommands/index.d.ts.map +1 -1
  133. package/lib/subcommands/index.js +1 -1
  134. package/lib/subcommands/login.d.ts +0 -1
  135. package/lib/subcommands/login.d.ts.map +1 -1
  136. package/lib/subcommands/login.js +6 -14
  137. package/lib/subcommands/login.js.map +1 -1
  138. package/lib/util/clean-certs.d.ts +2 -0
  139. package/lib/util/clean-certs.d.ts.map +1 -0
  140. package/lib/util/clean-certs.js +16 -0
  141. package/lib/util/clean-certs.js.map +1 -0
  142. package/lib/util/directories.d.ts +16 -15
  143. package/lib/util/directories.d.ts.map +1 -1
  144. package/lib/util/directories.js +45 -26
  145. package/lib/util/directories.js.map +1 -1
  146. package/lib/util/fetch-with-timeout.d.ts +4 -0
  147. package/lib/util/fetch-with-timeout.d.ts.map +1 -0
  148. package/lib/util/fetch-with-timeout.js +15 -0
  149. package/lib/util/fetch-with-timeout.js.map +1 -0
  150. package/lib/util/get-device-id.d.ts +1 -1
  151. package/lib/util/get-device-id.d.ts.map +1 -1
  152. package/lib/util/get-device-id.js +14 -19
  153. package/lib/util/get-device-id.js.map +1 -1
  154. package/lib/util/http-client.d.ts +1 -1
  155. package/lib/util/http-client.d.ts.map +1 -1
  156. package/lib/util/http-client.js +10 -8
  157. package/lib/util/http-client.js.map +1 -1
  158. package/lib/util/logger.d.ts.map +1 -1
  159. package/lib/util/logger.js +4 -5
  160. package/lib/util/logger.js.map +1 -1
  161. package/lib/util/require-logged-in-and-paid-plan.d.ts +2 -0
  162. package/lib/util/require-logged-in-and-paid-plan.d.ts.map +1 -0
  163. package/lib/util/require-logged-in-and-paid-plan.js +18 -0
  164. package/lib/util/require-logged-in-and-paid-plan.js.map +1 -0
  165. package/lib/util/run-in-dir.d.ts.map +1 -1
  166. package/lib/util/run-in-dir.js +1 -0
  167. package/lib/util/run-in-dir.js.map +1 -1
  168. package/lib/util/timer.d.ts +2 -0
  169. package/lib/util/timer.d.ts.map +1 -0
  170. package/lib/util/timer.js +6 -0
  171. package/lib/util/timer.js.map +1 -0
  172. package/package.json +32 -35
  173. package/readme.md +100 -89
  174. package/src/application-control/backup.ts +11 -6
  175. package/src/application-control/config.ts +75 -13
  176. package/src/application-control/environment-variables.ts +3 -3
  177. package/src/application-control/index.ts +18 -11
  178. package/src/application-control/install.ts +82 -78
  179. package/src/application-control/models.ts +104 -72
  180. package/src/application-control/status.ts +29 -40
  181. package/src/application-control/utils.ts +66 -38
  182. package/src/cloud-connection/app-install-status.ts +62 -0
  183. package/src/cloud-connection/bootstrap-provision.ts +40 -0
  184. package/src/cloud-connection/cmd-status.ts +52 -0
  185. package/src/cloud-connection/device-agent-cloud-connection.ts +302 -526
  186. package/src/cloud-connection/device-agent.ts +31 -38
  187. package/src/cloud-connection/live-updates-handler.ts +226 -0
  188. package/src/cloud-connection/messages.ts +39 -0
  189. package/src/cloud-connection/passthrough-handler.ts +67 -0
  190. package/src/cloud-connection/publisher.ts +86 -0
  191. package/src/cloud-connection/shadow-handler.test.ts +361 -0
  192. package/src/cloud-connection/shadow-handler.ts +175 -0
  193. package/src/cloud-connection/shadow.ts +50 -0
  194. package/src/device-control/device-control.ts +1 -0
  195. package/src/docker/docker-cmd.ts +1 -1
  196. package/src/docker/docker-compose-cmd.ts +5 -2
  197. package/src/endpoints.ts +9 -9
  198. package/src/environment.ts +11 -3
  199. package/src/infrastructure/agent-config.test.ts +33 -29
  200. package/src/infrastructure/agent-config.ts +57 -22
  201. package/src/infrastructure/system-id.ts +18 -0
  202. package/src/infrastructure/tokens-and-device-cfg.ts +34 -0
  203. package/src/infrastructure/urls.ts +4 -2
  204. package/src/local-connection/rabbitmq-connection.ts +53 -0
  205. package/src/root.ts +2 -8
  206. package/src/subcommands/app/app.ts +119 -83
  207. package/src/subcommands/app/index.ts +3 -3
  208. package/src/subcommands/device/clean.ts +26 -0
  209. package/src/subcommands/device/device.ts +67 -54
  210. package/src/subcommands/device/index.ts +2 -1
  211. package/src/subcommands/get-model-package.ts +5 -5
  212. package/src/subcommands/index.ts +1 -1
  213. package/src/subcommands/login.ts +6 -14
  214. package/src/util/clean-certs.ts +12 -0
  215. package/src/util/directories.ts +68 -52
  216. package/src/util/fetch-with-timeout.ts +18 -0
  217. package/src/util/get-device-id.ts +16 -18
  218. package/src/util/http-client.ts +18 -13
  219. package/src/util/logger.ts +6 -6
  220. package/src/util/require-logged-in-and-paid-plan.ts +16 -0
  221. package/src/util/run-in-dir.ts +2 -1
  222. package/src/util/timer.ts +1 -0
  223. package/lib/infrastructure/certificates-and-tokens.d.ts +0 -6
  224. package/lib/infrastructure/certificates-and-tokens.d.ts.map +0 -1
  225. package/lib/infrastructure/certificates-and-tokens.js +0 -43
  226. package/lib/infrastructure/certificates-and-tokens.js.map +0 -1
  227. package/src/infrastructure/certificates-and-tokens.ts +0 -53
@@ -2,17 +2,15 @@ import {
2
2
  CliLeaf,
3
3
  CliStringArrayInput,
4
4
  CliStringInput,
5
- CliTerseError,
5
+ CliTerseError
6
6
  } from '@alwaysai/alwayscli';
7
+ import { ClientMessage, keyMirrors } from '@alwaysai/device-agent-schemas';
7
8
  import {
8
- addModel,
9
9
  getAllEnvs,
10
10
  getAppLogs,
11
11
  getAppModels,
12
12
  getAppStatus,
13
- installApp,
14
- listAppLatestRelease,
15
- listAppReleases,
13
+ readAppCfgFile,
16
14
  removeModel,
17
15
  replaceModels,
18
16
  restartApp,
@@ -21,10 +19,12 @@ import {
21
19
  startApp,
22
20
  stopApp,
23
21
  uninstallApp,
24
- updateModels,
22
+ updateModels
25
23
  } from '../../application-control';
24
+ import { DeviceAgentCloudConnection } from '../../cloud-connection/device-agent-cloud-connection';
26
25
  import { AgentConfigFile } from '../../infrastructure/agent-config';
27
26
  import { logger } from '../../util/logger';
27
+ import { timer } from '../../util/timer';
28
28
 
29
29
  export const listAppsCliLeaf = CliLeaf({
30
30
  name: 'list',
@@ -33,7 +33,7 @@ export const listAppsCliLeaf = CliLeaf({
33
33
  async action(_, opts) {
34
34
  const apps = await AgentConfigFile().getApps();
35
35
  console.table(apps);
36
- },
36
+ }
37
37
  });
38
38
 
39
39
  export const listAppReleasesCliLeaf = CliLeaf({
@@ -42,14 +42,13 @@ export const listAppReleasesCliLeaf = CliLeaf({
42
42
  namedInputs: {
43
43
  project: CliStringInput({
44
44
  description: 'Project ID',
45
- required: true,
46
- }),
45
+ required: true
46
+ })
47
47
  },
48
+ hidden: true,
48
49
  async action(_, opts) {
49
- const { project } = opts;
50
- const releaseHistory = await listAppReleases({ projectId: project });
51
- logger.info(releaseHistory);
52
- },
50
+ throw new CliTerseError('This command is yet currently implemented!');
51
+ }
53
52
  });
54
53
 
55
54
  export const listAppLatestReleaseCliLeaf = CliLeaf({
@@ -58,17 +57,13 @@ export const listAppLatestReleaseCliLeaf = CliLeaf({
58
57
  namedInputs: {
59
58
  project: CliStringInput({
60
59
  description: 'Project ID',
61
- required: true,
62
- }),
60
+ required: true
61
+ })
63
62
  },
63
+ hidden: true,
64
64
  async action(_, opts) {
65
- const { project } = opts;
66
- const latestReleaseHash = await listAppLatestRelease({ projectId: project });
67
- if (latestReleaseHash === undefined) {
68
- throw new CliTerseError('This application has not been published yet');
69
- }
70
- logger.info(latestReleaseHash);
71
- },
65
+ throw new CliTerseError('This command is yet currently implemented!');
66
+ }
72
67
  });
73
68
 
74
69
  export const installAppCliLeaf = CliLeaf({
@@ -77,23 +72,36 @@ export const installAppCliLeaf = CliLeaf({
77
72
  namedInputs: {
78
73
  project: CliStringInput({
79
74
  description: 'Project ID',
80
- required: true,
75
+ required: true
81
76
  }),
82
77
  releaseHash: CliStringInput({
83
78
  description: 'Release Hash',
84
- }),
79
+ required: true
80
+ })
85
81
  },
86
82
  async action(_, opts) {
87
- const project = opts.project;
88
- let releaseHash = opts.releaseHash;
89
- if (releaseHash === undefined) {
90
- releaseHash = await listAppLatestRelease({ projectId: project });
83
+ const { project, releaseHash } = opts;
84
+ const deviceAgent = new DeviceAgentCloudConnection();
85
+ await deviceAgent.setupHandlers();
86
+ const topic = deviceAgent.getToDeviceTopic();
87
+ const message: ClientMessage = {
88
+ timestamp: '',
89
+ topic,
90
+ payload: {
91
+ messageType: keyMirrors.clientMessageType.app_version_control,
92
+ appVersionControl: {
93
+ baseCommand: keyMirrors.appVersionControl.install,
94
+ projectId: project,
95
+ appReleaseHash: releaseHash
96
+ }
97
+ }
98
+ };
99
+ await deviceAgent.handleClientMessage({ topic, message });
100
+ while (deviceAgent.getCmdStatus(project) === 'in_progress') {
101
+ await timer(1000);
91
102
  }
92
- if (releaseHash === undefined) {
93
- throw new CliTerseError('This application has not been published yet');
94
- }
95
- await installApp({ projectId: project, appReleaseHash: releaseHash });
96
- },
103
+ deviceAgent.stop();
104
+ }
97
105
  });
98
106
 
99
107
  export const getAppStatusCliLeaf = CliLeaf({
@@ -102,14 +110,14 @@ export const getAppStatusCliLeaf = CliLeaf({
102
110
  namedInputs: {
103
111
  project: CliStringInput({
104
112
  description: 'Project ID',
105
- required: true,
106
- }),
113
+ required: true
114
+ })
107
115
  },
108
116
  async action(_, opts) {
109
117
  const { project } = opts;
110
118
  const appStatus = await getAppStatus({ projectId: project });
111
- logger.info(appStatus);
112
- },
119
+ logger.info(JSON.stringify(appStatus, null, 2));
120
+ }
113
121
  });
114
122
 
115
123
  export const startAppCliLeaf = CliLeaf({
@@ -118,16 +126,16 @@ export const startAppCliLeaf = CliLeaf({
118
126
  namedInputs: {
119
127
  project: CliStringInput({
120
128
  description: 'Project ID',
121
- required: true,
129
+ required: true
122
130
  }),
123
131
  dockerLoginToken: CliStringInput({
124
- description: 'Docker login token',
125
- }),
132
+ description: 'Docker login token'
133
+ })
126
134
  },
127
135
  async action(_, opts) {
128
136
  const { project, dockerLoginToken } = opts;
129
137
  await startApp({ projectId: project, dockerLoginToken });
130
- },
138
+ }
131
139
  });
132
140
 
133
141
  export const getAppLogsCliLeaf = CliLeaf({
@@ -136,8 +144,8 @@ export const getAppLogsCliLeaf = CliLeaf({
136
144
  namedInputs: {
137
145
  project: CliStringInput({
138
146
  description: 'Project ID',
139
- required: true,
140
- }),
147
+ required: true
148
+ })
141
149
  },
142
150
  async action(_, opts) {
143
151
  const { project } = opts;
@@ -146,7 +154,7 @@ export const getAppLogsCliLeaf = CliLeaf({
146
154
  for await (const chunk of readable) {
147
155
  logger.info(chunk);
148
156
  }
149
- },
157
+ }
150
158
  });
151
159
 
152
160
  export const stopAppCliLeaf = CliLeaf({
@@ -155,13 +163,13 @@ export const stopAppCliLeaf = CliLeaf({
155
163
  namedInputs: {
156
164
  project: CliStringInput({
157
165
  description: 'Project ID',
158
- required: true,
159
- }),
166
+ required: true
167
+ })
160
168
  },
161
169
  async action(_, opts) {
162
170
  const { project } = opts;
163
171
  await stopApp({ projectId: project });
164
- },
172
+ }
165
173
  });
166
174
 
167
175
  export const restartAppCliLeaf = CliLeaf({
@@ -170,13 +178,13 @@ export const restartAppCliLeaf = CliLeaf({
170
178
  namedInputs: {
171
179
  project: CliStringInput({
172
180
  description: 'Project ID',
173
- required: true,
174
- }),
181
+ required: true
182
+ })
175
183
  },
176
184
  async action(_, opts) {
177
185
  const { project } = opts;
178
186
  await restartApp({ projectId: project });
179
- },
187
+ }
180
188
  });
181
189
 
182
190
  export const uninstallAppCliLeaf = CliLeaf({
@@ -185,13 +193,13 @@ export const uninstallAppCliLeaf = CliLeaf({
185
193
  namedInputs: {
186
194
  project: CliStringInput({
187
195
  description: 'Project ID',
188
- required: true,
189
- }),
196
+ required: true
197
+ })
190
198
  },
191
199
  async action(_, opts) {
192
200
  const { project } = opts;
193
201
  await uninstallApp({ projectId: project });
194
- },
202
+ }
195
203
  });
196
204
 
197
205
  export const rollbackAppCliLeaf = CliLeaf({
@@ -200,13 +208,14 @@ export const rollbackAppCliLeaf = CliLeaf({
200
208
  namedInputs: {
201
209
  project: CliStringInput({
202
210
  description: 'Project ID',
203
- required: true,
204
- }),
211
+ required: true
212
+ })
205
213
  },
214
+ hidden: true,
206
215
  async action(_, opts) {
207
216
  const { project } = opts;
208
217
  await rollbackApp({ projectId: project });
209
- },
218
+ }
210
219
  });
211
220
 
212
221
  export const showAppModelsCliLeaf = CliLeaf({
@@ -215,14 +224,14 @@ export const showAppModelsCliLeaf = CliLeaf({
215
224
  namedInputs: {
216
225
  project: CliStringInput({
217
226
  description: 'Project ID',
218
- required: true,
219
- }),
227
+ required: true
228
+ })
220
229
  },
221
230
  async action(_, opts) {
222
231
  const { project } = opts;
223
232
  const appModels = await getAppModels({ projectId: project });
224
233
  console.table(appModels);
225
- },
234
+ }
226
235
  });
227
236
 
228
237
  export const addModelCliLeaf = CliLeaf({
@@ -231,17 +240,44 @@ export const addModelCliLeaf = CliLeaf({
231
240
  namedInputs: {
232
241
  project: CliStringInput({
233
242
  description: 'Project ID',
234
- required: true,
243
+ required: true
235
244
  }),
236
245
  model: CliStringInput({
237
246
  description: 'Model ID',
238
- required: true,
247
+ required: true
239
248
  }),
249
+ version: CliStringInput({
250
+ description: 'Model version',
251
+ required: true
252
+ })
240
253
  },
241
254
  async action(_, opts) {
242
- const { project, model } = opts;
243
- await addModel({ projectId: project, modelId: model });
244
- },
255
+ const { project, model, version } = opts;
256
+ const deviceAgent = new DeviceAgentCloudConnection();
257
+ await deviceAgent.setupHandlers();
258
+
259
+ const topic = deviceAgent.getShadowTopics().projects.updateDelta;
260
+
261
+ const newAppCfg = await readAppCfgFile({ projectId: project });
262
+ newAppCfg.models[model] = Number(version);
263
+
264
+ const message = {
265
+ version: 3,
266
+ timestamp: 0,
267
+ state: {
268
+ [project]: {
269
+ appConfig: JSON.stringify(newAppCfg)
270
+ }
271
+ },
272
+ clientToken: 'not-self'
273
+ };
274
+
275
+ await deviceAgent.handleMessage(topic, message);
276
+ while (deviceAgent.getCmdStatus(project) === 'in_progress') {
277
+ await timer(1000);
278
+ }
279
+ deviceAgent.stop();
280
+ }
245
281
  });
246
282
 
247
283
  export const removeModelCliLeaf = CliLeaf({
@@ -250,17 +286,17 @@ export const removeModelCliLeaf = CliLeaf({
250
286
  namedInputs: {
251
287
  project: CliStringInput({
252
288
  description: 'Project ID',
253
- required: true,
289
+ required: true
254
290
  }),
255
291
  model: CliStringInput({
256
292
  description: 'Model ID',
257
- required: true,
258
- }),
293
+ required: true
294
+ })
259
295
  },
260
296
  async action(_, opts) {
261
297
  const { project, model } = opts;
262
298
  await removeModel({ projectId: project, modelId: model });
263
- },
299
+ }
264
300
  });
265
301
 
266
302
  export const replaceModelsCliLeaf = CliLeaf({
@@ -269,17 +305,17 @@ export const replaceModelsCliLeaf = CliLeaf({
269
305
  namedInputs: {
270
306
  project: CliStringInput({
271
307
  description: 'Project Id',
272
- required: true,
308
+ required: true
273
309
  }),
274
310
  models: CliStringArrayInput({
275
311
  description: 'One or more model IDs',
276
- required: true,
277
- }),
312
+ required: true
313
+ })
278
314
  },
279
315
  async action(_, opts) {
280
316
  const { project, models } = opts;
281
317
  await replaceModels({ projectId: project, modelIds: models });
282
- },
318
+ }
283
319
  });
284
320
 
285
321
  export const updateModelsCliLeaf = CliLeaf({
@@ -288,13 +324,13 @@ export const updateModelsCliLeaf = CliLeaf({
288
324
  namedInputs: {
289
325
  project: CliStringInput({
290
326
  description: 'Project Id',
291
- required: true,
292
- }),
327
+ required: true
328
+ })
293
329
  },
294
330
  async action(_, opts) {
295
331
  const { project } = opts;
296
332
  await updateModels({ projectId: project });
297
- },
333
+ }
298
334
  });
299
335
 
300
336
  export const getAllEnvsCLiLeaf = CliLeaf({
@@ -303,13 +339,13 @@ export const getAllEnvsCLiLeaf = CliLeaf({
303
339
  namedInputs: {
304
340
  project: CliStringInput({
305
341
  description: 'Project Id',
306
- required: true,
307
- }),
342
+ required: true
343
+ })
308
344
  },
309
345
  async action(_, opts) {
310
346
  const { project } = opts;
311
347
  logger.info(await getAllEnvs({ projectId: project }));
312
- },
348
+ }
313
349
  });
314
350
 
315
351
  export const setEnvCLiLeaf = CliLeaf({
@@ -317,21 +353,21 @@ export const setEnvCLiLeaf = CliLeaf({
317
353
  description: 'Set environment variables for a service',
318
354
  positionalInput: CliStringArrayInput({
319
355
  placeholder: '<NAME=VALUE> [<NAME=VALUE> ...]',
320
- required: true,
356
+ required: true
321
357
  }),
322
358
  namedInputs: {
323
359
  project: CliStringInput({
324
360
  description: 'Project Id',
325
- required: true,
361
+ required: true
326
362
  }),
327
363
  service: CliStringInput({
328
364
  description:
329
365
  'The name of the docker-compose service to apply environment variable to',
330
- required: false,
331
- }),
366
+ required: false
367
+ })
332
368
  },
333
369
  async action(args, opts) {
334
370
  const { project, service } = opts;
335
371
  await setEnv({ projectId: project, vars: args, service });
336
- },
372
+ }
337
373
  });
@@ -17,7 +17,7 @@ import {
17
17
  replaceModelsCliLeaf,
18
18
  showAppModelsCliLeaf,
19
19
  getAllEnvsCLiLeaf,
20
- setEnvCLiLeaf,
20
+ setEnvCLiLeaf
21
21
  } from './app';
22
22
 
23
23
  export const appCliBranch = CliBranch({
@@ -41,6 +41,6 @@ export const appCliBranch = CliBranch({
41
41
  replaceModelsCliLeaf,
42
42
  updateModelsCliLeaf,
43
43
  getAllEnvsCLiLeaf,
44
- setEnvCLiLeaf,
45
- ],
44
+ setEnvCLiLeaf
45
+ ]
46
46
  });
@@ -0,0 +1,26 @@
1
+ import { CliLeaf } from '@alwaysai/alwayscli';
2
+ import { rimraf } from 'rimraf';
3
+ import { LOCAL_CERT_AND_KEY_DIR } from 'alwaysai/lib/constants';
4
+ import { logger } from '../../util/logger';
5
+ import { AgentConfigFile } from '../../infrastructure/agent-config';
6
+ import { DeviceConfigFile } from 'alwaysai/lib/core/device';
7
+ import { APP_ROOT, CREDENTIALS_FILE_PATH } from '../../util/directories';
8
+
9
+ export const cleanCliLeaf = CliLeaf({
10
+ name: 'clean',
11
+ description: 'Remove all provisioning files',
12
+ async action(_, opts) {
13
+ logger.info('Cleaning device configuration');
14
+ logger.debug(`Removing ${LOCAL_CERT_AND_KEY_DIR}`);
15
+ await rimraf(LOCAL_CERT_AND_KEY_DIR);
16
+ logger.debug(`Removing ${AgentConfigFile().path}`);
17
+ AgentConfigFile().remove();
18
+ logger.debug(`Removing ${DeviceConfigFile().path}`);
19
+ DeviceConfigFile().remove();
20
+ logger.debug(`Removing ${CREDENTIALS_FILE_PATH}`);
21
+ await rimraf(CREDENTIALS_FILE_PATH);
22
+ logger.debug(`Removing ${APP_ROOT}`);
23
+ await rimraf(APP_ROOT);
24
+ logger.info('Device configuration cleaned');
25
+ }
26
+ });
@@ -1,100 +1,113 @@
1
- import { CliLeaf, CliStringInput } from "@alwaysai/alwayscli";
2
- import { checkUserIsLoggedInComponent } from "alwaysai/lib/components/user";
3
- import { checkPaidPlan } from "alwaysai/lib/core/project";
4
- import { v4 as uuidv4 } from "uuid";
5
- import { CliAuthenticationClient } from "alwaysai/lib/infrastructure";
6
-
7
- import { httpClient, microServiceHttpClient } from "../../util/http-client";
1
+ import { CliLeaf, CliStringInput } from '@alwaysai/alwayscli';
2
+ import { getTargetHardwareUuid } from 'alwaysai/lib/core/app';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ import { CliAuthenticationClient } from 'alwaysai/lib/infrastructure';
5
+ import { existsSync } from 'fs';
6
+ import { httpClient, microServiceHttpClient } from '../../util/http-client';
8
7
  import {
9
8
  AWS_ROOT_CERTIFICATE_FILE_NAME,
10
9
  BOOTSTRAP_CERTIFICATES_DIR_PATH,
11
- } from "../../util/directories";
10
+ getPrivateKeyFilePath
11
+ } from '../../util/directories';
12
12
 
13
- import { LOCAL_CERT_AND_KEY_DIR } from "alwaysai/lib/constants";
14
- import fetch from "node-fetch";
15
- import { JsSpawner } from "alwaysai/lib/util";
13
+ import { LOCAL_CERT_AND_KEY_DIR } from 'alwaysai/lib/constants';
14
+ import { JsSpawner } from 'alwaysai/lib/util';
16
15
  import {
17
16
  getCpuUtil,
18
17
  getDiskUtil,
19
- getMemUtil,
20
- } from "../../device-control/device-control";
21
- import {
22
- getTargetHardwareUuid,
23
- writeCertificateAndToken,
24
- } from "../../infrastructure/certificates-and-tokens";
25
- import { logger } from "../../util/logger";
18
+ getMemUtil
19
+ } from '../../device-control/device-control';
20
+ import { writeTokenAndDeviceCfg } from '../../infrastructure/tokens-and-device-cfg';
21
+ import { logger } from '../../util/logger';
22
+ import { DeviceConfigFile } from 'alwaysai/lib/core/device';
23
+ import { requireLoggedInAndPaidPlan } from '../../util/require-logged-in-and-paid-plan';
26
24
 
27
25
  export const initCliLeaf = CliLeaf({
28
- name: "init",
29
- description: "Initialize device",
26
+ name: 'init',
27
+ description: 'Initialize device',
30
28
  namedInputs: {
31
29
  name: CliStringInput({
32
- description: "Device name",
33
- required: true,
30
+ description: 'Device name',
31
+ required: false
34
32
  }),
35
33
  description: CliStringInput({
36
- description: "Device description",
37
- required: false,
38
- }),
34
+ description: 'Device description',
35
+ required: false
36
+ })
39
37
  },
40
38
  async action(_, opts) {
41
- const { name, description } = opts;
42
- logger.info("Initializing device");
43
- await checkUserIsLoggedInComponent({ yes: true });
44
- if (!(await checkPaidPlan())) {
39
+ let { name } = opts;
40
+ name = name || uuidv4();
41
+
42
+ if (DeviceConfigFile().exists() || existsSync(getPrivateKeyFilePath())) {
45
43
  throw new Error(
46
- `This action only supported for Enterprise alwaysAI accounts!`
44
+ "Device has been previously provisioned. Run 'aai-agent device clean' to re-provision"
47
45
  );
48
46
  }
47
+ logger.info(`Initializing device ${name}`);
48
+ await requireLoggedInAndPaidPlan();
49
49
  const { username } = await CliAuthenticationClient().getInfo();
50
- const spawner = JsSpawner();
51
- const hardwareId = await getTargetHardwareUuid(spawner);
50
+ const hardwareId = await getTargetHardwareUuid(JsSpawner());
52
51
  const device = {
53
- deviceMode: "production",
52
+ deviceMode: 'production',
54
53
  hardwareId,
55
54
  txId: uuidv4(),
56
55
  userName: username,
57
- friendlyName: name,
56
+ friendlyName: name
58
57
  };
59
58
 
60
- const response = await microServiceHttpClient(
61
- "fleet-provision",
62
- "addDevice",
63
- "POST",
64
- JSON.stringify(device)
65
- );
59
+ // FIXME: Use JSON schema to validate input
60
+ const response: { deviceUuid: string; claimCertificate: string[] } =
61
+ await microServiceHttpClient(
62
+ 'fleet-provision',
63
+ 'addDevice',
64
+ 'POST',
65
+ JSON.stringify(device)
66
+ );
67
+ logger.debug(`addDevice Response: ${JSON.stringify(response, null, 2)}`);
66
68
 
69
+ if (!('claimCertificate' in response)) {
70
+ throw new Error(
71
+ "Device cannot be provisioned. Run 'aai-agent device clean' and retry."
72
+ );
73
+ }
67
74
  const ROOT_CERT_AWS = await httpClient(
68
- "https://www.amazontrust.com/repository/AmazonRootCA1.pem",
69
- "GET"
75
+ 'https://www.amazontrust.com/repository/AmazonRootCA1.pem',
76
+ 'GET',
77
+ {}
70
78
  );
71
79
 
72
- await writeCertificateAndToken({ deviceUuid: response.deviceUuid });
80
+ await writeTokenAndDeviceCfg({
81
+ deviceUuid: response.deviceUuid
82
+ });
73
83
 
74
- await JsSpawner().mkdirp(BOOTSTRAP_CERTIFICATES_DIR_PATH);
75
- JsSpawner({ path: LOCAL_CERT_AND_KEY_DIR }).writeFile(
84
+ await JsSpawner().mkdirp(BOOTSTRAP_CERTIFICATES_DIR_PATH());
85
+
86
+ await JsSpawner({ path: LOCAL_CERT_AND_KEY_DIR }).writeFile(
76
87
  AWS_ROOT_CERTIFICATE_FILE_NAME,
77
88
  ROOT_CERT_AWS
78
89
  );
79
- const certSpawner = JsSpawner({ path: BOOTSTRAP_CERTIFICATES_DIR_PATH });
90
+ const certSpawner = JsSpawner({
91
+ path: BOOTSTRAP_CERTIFICATES_DIR_PATH()
92
+ });
80
93
  for (const key in response.claimCertificate) {
81
94
  await certSpawner.writeFile(key, response.claimCertificate[key]);
82
95
  }
83
96
 
84
- logger.info(`Initialized device as ${response.deviceUuid}`);
85
- },
97
+ logger.info(`Initialized device ${name}: UUID=${response.deviceUuid}`);
98
+ }
86
99
  });
87
100
 
88
101
  export const getInfoCliLeaf = CliLeaf({
89
- name: "get-info",
90
- description: "Get device info",
102
+ name: 'get-info',
103
+ description: 'Get device info',
91
104
  namedInputs: {},
92
105
  async action(_, opts) {
93
106
  const deviceInfo = [
94
- ["CPU Utilization", `${String(await getCpuUtil())} %`],
95
- ["Disk Utilization", `${String(await getDiskUtil())} %`],
96
- ["Memory Utilization", `${String(await getMemUtil())} %`],
107
+ ['CPU Utilization', `${String(await getCpuUtil())} %`],
108
+ ['Disk Utilization', `${String(await getDiskUtil())} %`],
109
+ ['Memory Utilization', `${String(await getMemUtil())} %`]
97
110
  ];
98
111
  console.table(deviceInfo);
99
- },
112
+ }
100
113
  });
@@ -1,8 +1,9 @@
1
1
  import { CliBranch } from '@alwaysai/alwayscli';
2
2
  import { getInfoCliLeaf, initCliLeaf } from './device';
3
+ import { cleanCliLeaf } from './clean';
3
4
 
4
5
  export const deviceCliBranch = CliBranch({
5
6
  name: 'device',
6
7
  description: 'Manage current device',
7
- subcommands: [initCliLeaf, getInfoCliLeaf],
8
+ subcommands: [initCliLeaf, getInfoCliLeaf, cleanCliLeaf]
8
9
  });
@@ -10,17 +10,17 @@ export const getModelPackageCliLeaf = CliLeaf({
10
10
  positionalInput: CliStringInput({
11
11
  description: 'For example, "alwaysai/mobilenet_ssd"',
12
12
  required: true,
13
- placeholder: '<id>',
13
+ placeholder: '<id>'
14
14
  }),
15
15
  namedInputs: {
16
16
  version: CliNumberInput({
17
17
  description: 'The version number of the model',
18
- required: false,
18
+ required: false
19
19
  }),
20
20
  path: CliStringInput({
21
21
  description: 'The output path to write model package to',
22
- required: false,
23
- }),
22
+ required: false
23
+ })
24
24
  },
25
25
  async action(id, opts) {
26
26
  const path = opts.path || process.cwd();
@@ -29,5 +29,5 @@ export const getModelPackageCliLeaf = CliLeaf({
29
29
  opts.version || (await CliRpcClient().getModelVersion({ id })).version;
30
30
  await appInstallModel(spawner, id, version);
31
31
  logger.info(`Completed downloading ${id} to ${path}`);
32
- },
32
+ }
33
33
  });