@alwaysai/device-agent 0.0.3 → 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 (210) hide show
  1. package/lib/application-control/backup.d.ts +8 -0
  2. package/lib/application-control/backup.d.ts.map +1 -0
  3. package/lib/application-control/backup.js +34 -0
  4. package/lib/application-control/backup.js.map +1 -0
  5. package/lib/application-control/environment-variables.d.ts +9 -0
  6. package/lib/application-control/environment-variables.d.ts.map +1 -0
  7. package/lib/application-control/environment-variables.js +82 -0
  8. package/lib/application-control/environment-variables.js.map +1 -0
  9. package/lib/application-control/index.d.ts +9 -0
  10. package/lib/application-control/index.d.ts.map +1 -0
  11. package/lib/application-control/index.js +27 -0
  12. package/lib/application-control/index.js.map +1 -0
  13. package/lib/application-control/install.d.ts +16 -0
  14. package/lib/application-control/install.d.ts.map +1 -0
  15. package/lib/application-control/install.js +117 -0
  16. package/lib/application-control/install.js.map +1 -0
  17. package/lib/application-control/models.d.ts +8 -0
  18. package/lib/application-control/models.d.ts.map +1 -1
  19. package/lib/application-control/models.js +44 -11
  20. package/lib/application-control/models.js.map +1 -1
  21. package/lib/application-control/status.d.ts +26 -0
  22. package/lib/application-control/status.d.ts.map +1 -0
  23. package/lib/application-control/status.js +138 -0
  24. package/lib/application-control/status.js.map +1 -0
  25. package/lib/application-control/types.d.ts +5 -0
  26. package/lib/application-control/types.d.ts.map +1 -0
  27. package/lib/{util/spawner → application-control}/types.js +0 -0
  28. package/lib/{util/spawner → application-control}/types.js.map +1 -1
  29. package/lib/application-control/utils.d.ts +2 -9
  30. package/lib/application-control/utils.d.ts.map +1 -1
  31. package/lib/application-control/utils.js +14 -29
  32. package/lib/application-control/utils.js.map +1 -1
  33. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +16 -1
  34. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  35. package/lib/cloud-connection/device-agent-cloud-connection.js +239 -9
  36. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  37. package/lib/docker/docker-cmd.js +2 -2
  38. package/lib/docker/docker-cmd.js.map +1 -1
  39. package/lib/docker/docker-compose-cmd.js +2 -2
  40. package/lib/docker/docker-compose-cmd.js.map +1 -1
  41. package/lib/environment.d.ts +2 -0
  42. package/lib/environment.d.ts.map +1 -1
  43. package/lib/environment.js +3 -1
  44. package/lib/environment.js.map +1 -1
  45. package/lib/index.js +10 -8
  46. package/lib/index.js.map +1 -1
  47. package/lib/infrastructure/agent-config.d.ts +73 -0
  48. package/lib/infrastructure/agent-config.d.ts.map +1 -0
  49. package/lib/infrastructure/agent-config.js +186 -0
  50. package/lib/infrastructure/agent-config.js.map +1 -0
  51. package/lib/infrastructure/agent-config.test.d.ts +2 -0
  52. package/lib/infrastructure/agent-config.test.d.ts.map +1 -0
  53. package/lib/infrastructure/agent-config.test.js +135 -0
  54. package/lib/infrastructure/agent-config.test.js.map +1 -0
  55. package/lib/infrastructure/certificates-and-tokens.d.ts +6 -0
  56. package/lib/infrastructure/certificates-and-tokens.d.ts.map +1 -0
  57. package/lib/infrastructure/certificates-and-tokens.js +69 -0
  58. package/lib/infrastructure/certificates-and-tokens.js.map +1 -0
  59. package/lib/{util → infrastructure}/urls.d.ts +0 -0
  60. package/lib/infrastructure/urls.d.ts.map +1 -0
  61. package/lib/{util → infrastructure}/urls.js +3 -3
  62. package/lib/infrastructure/urls.js.map +1 -0
  63. package/lib/root.js +3 -3
  64. package/lib/root.js.map +1 -1
  65. package/lib/subcommands/app/app.d.ts +31 -14
  66. package/lib/subcommands/app/app.d.ts.map +1 -1
  67. package/lib/subcommands/app/app.js +117 -62
  68. package/lib/subcommands/app/app.js.map +1 -1
  69. package/lib/subcommands/app/index.d.ts.map +1 -1
  70. package/lib/subcommands/app/index.js +6 -1
  71. package/lib/subcommands/app/index.js.map +1 -1
  72. package/lib/subcommands/device/device.d.ts +6 -0
  73. package/lib/subcommands/device/device.d.ts.map +1 -0
  74. package/lib/subcommands/device/device.js +62 -0
  75. package/lib/subcommands/device/device.js.map +1 -0
  76. package/lib/subcommands/device/index.d.ts +2 -0
  77. package/lib/subcommands/device/index.d.ts.map +1 -0
  78. package/lib/subcommands/device/index.js +11 -0
  79. package/lib/subcommands/device/index.js.map +1 -0
  80. package/lib/subcommands/get-model-package.d.ts +5 -0
  81. package/lib/subcommands/get-model-package.d.ts.map +1 -0
  82. package/lib/subcommands/get-model-package.js +51 -0
  83. package/lib/subcommands/get-model-package.js.map +1 -0
  84. package/lib/subcommands/index.d.ts +8 -1
  85. package/lib/subcommands/index.d.ts.map +1 -1
  86. package/lib/subcommands/index.js +6 -6
  87. package/lib/subcommands/index.js.map +1 -1
  88. package/lib/subcommands/login.d.ts +3 -2
  89. package/lib/subcommands/login.d.ts.map +1 -1
  90. package/lib/subcommands/login.js +11 -4
  91. package/lib/subcommands/login.js.map +1 -1
  92. package/lib/util/copy-dir.js +3 -3
  93. package/lib/util/copy-dir.js.map +1 -1
  94. package/lib/util/directories.d.ts +1 -1
  95. package/lib/util/directories.d.ts.map +1 -1
  96. package/lib/util/directories.js +9 -14
  97. package/lib/util/directories.js.map +1 -1
  98. package/lib/util/get-device-id.d.ts +2 -0
  99. package/lib/util/get-device-id.d.ts.map +1 -0
  100. package/lib/util/get-device-id.js +24 -0
  101. package/lib/util/get-device-id.js.map +1 -0
  102. package/package.json +19 -14
  103. package/readme.md +176 -72
  104. package/src/application-control/backup.ts +32 -0
  105. package/src/application-control/environment-variables.ts +81 -0
  106. package/src/application-control/index.ts +40 -0
  107. package/src/application-control/install.ts +126 -0
  108. package/src/application-control/models.ts +51 -11
  109. package/src/application-control/status.ts +156 -0
  110. package/src/application-control/types.ts +1 -0
  111. package/src/application-control/utils.ts +12 -27
  112. package/src/cloud-connection/device-agent-cloud-connection.ts +280 -13
  113. package/src/docker/docker-cmd.ts +1 -1
  114. package/src/docker/docker-compose-cmd.ts +1 -1
  115. package/src/environment.ts +2 -0
  116. package/src/index.ts +10 -7
  117. package/src/infrastructure/agent-config.test.ts +143 -0
  118. package/src/infrastructure/agent-config.ts +217 -0
  119. package/src/infrastructure/certificates-and-tokens.ts +71 -0
  120. package/src/{util → infrastructure}/urls.ts +1 -1
  121. package/src/root.ts +3 -3
  122. package/src/subcommands/app/app.ts +135 -62
  123. package/src/subcommands/app/index.ts +11 -1
  124. package/src/subcommands/device/device.ts +63 -0
  125. package/src/subcommands/device/index.ts +8 -0
  126. package/src/subcommands/get-model-package.ts +60 -0
  127. package/src/subcommands/index.ts +5 -5
  128. package/src/subcommands/login.ts +11 -4
  129. package/src/util/copy-dir.ts +1 -1
  130. package/src/util/directories.ts +12 -17
  131. package/src/util/get-device-id.ts +22 -0
  132. package/lib/application-control/application-control.d.ts +0 -46
  133. package/lib/application-control/application-control.d.ts.map +0 -1
  134. package/lib/application-control/application-control.js +0 -234
  135. package/lib/application-control/application-control.js.map +0 -1
  136. package/lib/constants.d.ts +0 -17
  137. package/lib/constants.d.ts.map +0 -1
  138. package/lib/constants.js +0 -24
  139. package/lib/constants.js.map +0 -1
  140. package/lib/subcommands/device-control.d.ts +0 -2
  141. package/lib/subcommands/device-control.d.ts.map +0 -1
  142. package/lib/subcommands/device-control.js +0 -19
  143. package/lib/subcommands/device-control.js.map +0 -1
  144. package/lib/subcommands/test-app.d.ts +0 -2
  145. package/lib/subcommands/test-app.d.ts.map +0 -1
  146. package/lib/subcommands/test-app.js +0 -29
  147. package/lib/subcommands/test-app.js.map +0 -1
  148. package/lib/util/spawner/gnu-spawner.d.ts +0 -9
  149. package/lib/util/spawner/gnu-spawner.d.ts.map +0 -1
  150. package/lib/util/spawner/gnu-spawner.js +0 -102
  151. package/lib/util/spawner/gnu-spawner.js.map +0 -1
  152. package/lib/util/spawner/js-spawner.d.ts +0 -5
  153. package/lib/util/spawner/js-spawner.d.ts.map +0 -1
  154. package/lib/util/spawner/js-spawner.js +0 -89
  155. package/lib/util/spawner/js-spawner.js.map +0 -1
  156. package/lib/util/spawner/types.d.ts +0 -28
  157. package/lib/util/spawner/types.d.ts.map +0 -1
  158. package/lib/util/spawner-base/index.d.ts +0 -17
  159. package/lib/util/spawner-base/index.d.ts.map +0 -1
  160. package/lib/util/spawner-base/index.js +0 -30
  161. package/lib/util/spawner-base/index.js.map +0 -1
  162. package/lib/util/spawner-base/run-foreground-sync.d.ts +0 -3
  163. package/lib/util/spawner-base/run-foreground-sync.d.ts.map +0 -1
  164. package/lib/util/spawner-base/run-foreground-sync.js +0 -18
  165. package/lib/util/spawner-base/run-foreground-sync.js.map +0 -1
  166. package/lib/util/spawner-base/run-foreground.d.ts +0 -3
  167. package/lib/util/spawner-base/run-foreground.d.ts.map +0 -1
  168. package/lib/util/spawner-base/run-foreground.js +0 -49
  169. package/lib/util/spawner-base/run-foreground.js.map +0 -1
  170. package/lib/util/spawner-base/run-streaming.d.ts +0 -4
  171. package/lib/util/spawner-base/run-streaming.d.ts.map +0 -1
  172. package/lib/util/spawner-base/run-streaming.js +0 -35
  173. package/lib/util/spawner-base/run-streaming.js.map +0 -1
  174. package/lib/util/spawner-base/run.d.ts +0 -4
  175. package/lib/util/spawner-base/run.d.ts.map +0 -1
  176. package/lib/util/spawner-base/run.js +0 -56
  177. package/lib/util/spawner-base/run.js.map +0 -1
  178. package/lib/util/urls.d.ts.map +0 -1
  179. package/lib/util/urls.js.map +0 -1
  180. package/lib/web/index.html +0 -229
  181. package/lib/web/static/Karla.css +0 -18
  182. package/lib/web/static/bootstrap-4.3.1.min.css +0 -7
  183. package/lib/web/static/bootstrap-4.3.1.min.js +0 -7
  184. package/lib/web/static/favicon.ico +0 -0
  185. package/lib/web/static/jquery-3.3.1.slim.min.js +0 -2
  186. package/lib/web/static/popper-1.14.7.min.js +0 -5
  187. package/lib/web/web-interface.d.ts +0 -2
  188. package/lib/web/web-interface.d.ts.map +0 -1
  189. package/lib/web/web-interface.js +0 -74
  190. package/lib/web/web-interface.js.map +0 -1
  191. package/src/application-control/application-control.ts +0 -273
  192. package/src/constants.ts +0 -32
  193. package/src/subcommands/device-control.ts +0 -16
  194. package/src/subcommands/test-app.ts +0 -30
  195. package/src/util/spawner/gnu-spawner.ts +0 -114
  196. package/src/util/spawner/js-spawner.ts +0 -110
  197. package/src/util/spawner/types.ts +0 -28
  198. package/src/util/spawner-base/index.ts +0 -28
  199. package/src/util/spawner-base/run-foreground-sync.ts +0 -16
  200. package/src/util/spawner-base/run-foreground.ts +0 -49
  201. package/src/util/spawner-base/run-streaming.ts +0 -40
  202. package/src/util/spawner-base/run.ts +0 -60
  203. package/src/web/index.html +0 -229
  204. package/src/web/static/Karla.css +0 -18
  205. package/src/web/static/bootstrap-4.3.1.min.css +0 -7
  206. package/src/web/static/bootstrap-4.3.1.min.js +0 -7
  207. package/src/web/static/favicon.ico +0 -0
  208. package/src/web/static/jquery-3.3.1.slim.min.js +0 -2
  209. package/src/web/static/popper-1.14.7.min.js +0 -5
  210. package/src/web/web-interface.ts +0 -89
@@ -1,24 +1,36 @@
1
- import { CliLeaf, CliStringInput, CliTerseError } from '@alwaysai/alwayscli';
2
1
  import {
2
+ CliLeaf,
3
+ CliStringArrayInput,
4
+ CliStringInput,
5
+ CliTerseError,
6
+ } from '@alwaysai/alwayscli';
7
+ import {
8
+ addModel,
9
+ getAllEnvs,
3
10
  getAppLogs,
11
+ getAppModels,
4
12
  getAppStatus,
5
- getInstalledApps,
6
13
  installApp,
14
+ listAppLatestRelease,
15
+ listAppReleases,
16
+ removeModel,
17
+ replaceModels,
18
+ restartApp,
7
19
  rollbackApp,
20
+ setEnv,
8
21
  startApp,
9
22
  stopApp,
10
23
  uninstallApp,
11
- listAppReleases,
12
- listAppLatestRelease,
13
- } from '../../application-control/application-control';
14
- import { addModel, removeModel, updateModels } from '../../application-control/models';
24
+ updateModels,
25
+ } from '../../application-control';
26
+ import { AgentConfigFile } from '../../infrastructure/agent-config';
15
27
 
16
28
  export const listAppsCliLeaf = CliLeaf({
17
29
  name: 'list',
18
30
  description: 'List all installed apps',
19
31
  namedInputs: {},
20
32
  async action(_, opts) {
21
- const apps = await getInstalledApps();
33
+ const apps = await AgentConfigFile().getApps();
22
34
  console.table(apps);
23
35
  },
24
36
  });
@@ -28,14 +40,12 @@ export const listAppReleasesCliLeaf = CliLeaf({
28
40
  description: 'List all releases for a given app',
29
41
  namedInputs: {
30
42
  project: CliStringInput({
31
- description: 'Project Id',
43
+ description: 'Project ID',
44
+ required: true,
32
45
  }),
33
46
  },
34
47
  async action(_, opts) {
35
48
  const { project } = opts;
36
- if (project === undefined) {
37
- throw new CliTerseError('--project is required');
38
- }
39
49
  const releaseHistory = await listAppReleases({ projectId: project });
40
50
  console.log(releaseHistory);
41
51
  },
@@ -46,14 +56,12 @@ export const listAppLatestReleaseCliLeaf = CliLeaf({
46
56
  description: 'List the latest release hash for a given app',
47
57
  namedInputs: {
48
58
  project: CliStringInput({
49
- description: 'Project Id',
59
+ description: 'Project ID',
60
+ required: true,
50
61
  }),
51
62
  },
52
63
  async action(_, opts) {
53
64
  const { project } = opts;
54
- if (project === undefined) {
55
- throw new CliTerseError('--project is required');
56
- }
57
65
  const latestReleaseHash = await listAppLatestRelease({ projectId: project });
58
66
  if (latestReleaseHash === undefined) {
59
67
  throw new CliTerseError('This application has not been published yet');
@@ -67,7 +75,8 @@ export const installAppCliLeaf = CliLeaf({
67
75
  description: 'Install an alwaysAI app from a project',
68
76
  namedInputs: {
69
77
  project: CliStringInput({
70
- description: 'Project Id',
78
+ description: 'Project ID',
79
+ required: true,
71
80
  }),
72
81
  releaseHash: CliStringInput({
73
82
  description: 'Release Hash',
@@ -76,9 +85,6 @@ export const installAppCliLeaf = CliLeaf({
76
85
  async action(_, opts) {
77
86
  const project = opts.project;
78
87
  let releaseHash = opts.releaseHash;
79
- if (project === undefined) {
80
- throw new CliTerseError('--project is required');
81
- }
82
88
  if (releaseHash === undefined) {
83
89
  releaseHash = await listAppLatestRelease({ projectId: project });
84
90
  }
@@ -94,14 +100,12 @@ export const getAppStatusCliLeaf = CliLeaf({
94
100
  description: 'Get the status of an installed alwaysAI app',
95
101
  namedInputs: {
96
102
  project: CliStringInput({
97
- description: 'Project Id',
103
+ description: 'Project ID',
104
+ required: true,
98
105
  }),
99
106
  },
100
107
  async action(_, opts) {
101
108
  const { project } = opts;
102
- if (project === undefined) {
103
- throw new CliTerseError('--project is required');
104
- }
105
109
  const appStatus = await getAppStatus({ projectId: project });
106
110
  console.log(appStatus);
107
111
  },
@@ -112,7 +116,8 @@ export const startAppCliLeaf = CliLeaf({
112
116
  description: 'Start an installed alwaysAI app',
113
117
  namedInputs: {
114
118
  project: CliStringInput({
115
- description: 'Project Id',
119
+ description: 'Project ID',
120
+ required: true,
116
121
  }),
117
122
  dockerLoginToken: CliStringInput({
118
123
  description: 'Docker login token',
@@ -120,9 +125,6 @@ export const startAppCliLeaf = CliLeaf({
120
125
  },
121
126
  async action(_, opts) {
122
127
  const { project, dockerLoginToken } = opts;
123
- if (project === undefined) {
124
- throw new CliTerseError('--project is required');
125
- }
126
128
  await startApp({ projectId: project, dockerLoginToken });
127
129
  },
128
130
  });
@@ -132,14 +134,12 @@ export const getAppLogsCliLeaf = CliLeaf({
132
134
  description: 'Get logs for an application',
133
135
  namedInputs: {
134
136
  project: CliStringInput({
135
- description: 'Project Id',
137
+ description: 'Project ID',
138
+ required: true,
136
139
  }),
137
140
  },
138
141
  async action(_, opts) {
139
142
  const { project } = opts;
140
- if (project === undefined) {
141
- throw new CliTerseError('--project is required');
142
- }
143
143
  const readable = await getAppLogs({ projectId: project });
144
144
  readable.setEncoding('utf8');
145
145
  for await (const chunk of readable) {
@@ -153,31 +153,42 @@ export const stopAppCliLeaf = CliLeaf({
153
153
  description: 'Stop a running alwaysAI app',
154
154
  namedInputs: {
155
155
  project: CliStringInput({
156
- description: 'Project Id',
156
+ description: 'Project ID',
157
+ required: true,
157
158
  }),
158
159
  },
159
160
  async action(_, opts) {
160
161
  const { project } = opts;
161
- if (project === undefined) {
162
- throw new CliTerseError('Project ID is required');
163
- }
164
162
  await stopApp({ projectId: project });
165
163
  },
166
164
  });
167
165
 
166
+ export const restartAppCliLeaf = CliLeaf({
167
+ name: 'restart',
168
+ description: 'Restart running alwaysAI app',
169
+ namedInputs: {
170
+ project: CliStringInput({
171
+ description: 'Project ID',
172
+ required: true,
173
+ }),
174
+ },
175
+ async action(_, opts) {
176
+ const { project } = opts;
177
+ await restartApp({ projectId: project });
178
+ },
179
+ });
180
+
168
181
  export const uninstallAppCliLeaf = CliLeaf({
169
182
  name: 'uninstall',
170
183
  description: 'Remove an alwaysAI app',
171
184
  namedInputs: {
172
185
  project: CliStringInput({
173
- description: 'Project Id',
186
+ description: 'Project ID',
187
+ required: true,
174
188
  }),
175
189
  },
176
190
  async action(_, opts) {
177
191
  const { project } = opts;
178
- if (project === undefined) {
179
- throw new CliTerseError('Project ID is required');
180
- }
181
192
  await uninstallApp({ projectId: project });
182
193
  },
183
194
  });
@@ -187,37 +198,47 @@ export const rollbackAppCliLeaf = CliLeaf({
187
198
  description: 'Rollback an alwaysAI app to the previous version',
188
199
  namedInputs: {
189
200
  project: CliStringInput({
190
- description: 'Project Id',
201
+ description: 'Project ID',
202
+ required: true,
191
203
  }),
192
204
  },
193
205
  async action(_, opts) {
194
206
  const { project } = opts;
195
- if (project === undefined) {
196
- throw new CliTerseError('Project ID is required');
197
- }
198
207
  await rollbackApp({ projectId: project });
199
208
  },
200
209
  });
201
210
 
211
+ export const showAppModelsCliLeaf = CliLeaf({
212
+ name: 'show-models',
213
+ description: 'Show the application models',
214
+ namedInputs: {
215
+ project: CliStringInput({
216
+ description: 'Project ID',
217
+ required: true,
218
+ }),
219
+ },
220
+ async action(_, opts) {
221
+ const { project } = opts;
222
+ const appModels = await getAppModels({ projectId: project });
223
+ console.table(appModels);
224
+ },
225
+ });
226
+
202
227
  export const addModelCliLeaf = CliLeaf({
203
228
  name: 'add-model',
204
229
  description: 'Add a model to an alwaysAI app',
205
230
  namedInputs: {
206
231
  project: CliStringInput({
207
- description: 'Project Id',
232
+ description: 'Project ID',
233
+ required: true,
208
234
  }),
209
235
  model: CliStringInput({
210
- description: 'Model Id',
236
+ description: 'Model ID',
237
+ required: true,
211
238
  }),
212
239
  },
213
240
  async action(_, opts) {
214
241
  const { project, model } = opts;
215
- if (project === undefined) {
216
- throw new CliTerseError('--project is required');
217
- }
218
- if (model === undefined) {
219
- throw new CliTerseError('--model is required');
220
- }
221
242
  await addModel({ projectId: project, modelId: model });
222
243
  },
223
244
  });
@@ -227,37 +248,89 @@ export const removeModelCliLeaf = CliLeaf({
227
248
  description: 'Remove a model from an alwaysAI app',
228
249
  namedInputs: {
229
250
  project: CliStringInput({
230
- description: 'Project Id',
251
+ description: 'Project ID',
252
+ required: true,
231
253
  }),
232
254
  model: CliStringInput({
233
- description: 'Model Id',
255
+ description: 'Model ID',
256
+ required: true,
234
257
  }),
235
258
  },
236
259
  async action(_, opts) {
237
260
  const { project, model } = opts;
238
- if (project === undefined) {
239
- throw new CliTerseError('--project is required');
240
- }
241
- if (model === undefined) {
242
- throw new CliTerseError('--model is required');
243
- }
244
261
  await removeModel({ projectId: project, modelId: model });
245
262
  },
246
263
  });
247
264
 
265
+ export const replaceModelsCliLeaf = CliLeaf({
266
+ name: 'replace-models',
267
+ description: 'Replace all models of an alwaysAI app with new models',
268
+ namedInputs: {
269
+ project: CliStringInput({
270
+ description: 'Project Id',
271
+ required: true,
272
+ }),
273
+ models: CliStringArrayInput({
274
+ description: 'One or more model IDs',
275
+ required: true,
276
+ }),
277
+ },
278
+ async action(_, opts) {
279
+ const { project, models } = opts;
280
+ await replaceModels({ projectId: project, modelIds: models });
281
+ },
282
+ });
283
+
248
284
  export const updateModelsCliLeaf = CliLeaf({
249
285
  name: 'update-models',
250
286
  description: 'Update all models for an alwaysAI app',
251
287
  namedInputs: {
252
288
  project: CliStringInput({
253
289
  description: 'Project Id',
290
+ required: true,
254
291
  }),
255
292
  },
256
293
  async action(_, opts) {
257
294
  const { project } = opts;
258
- if (project === undefined) {
259
- throw new CliTerseError('--project is required');
260
- }
261
295
  await updateModels({ projectId: project });
262
296
  },
263
297
  });
298
+
299
+ export const getAllEnvsCLiLeaf = CliLeaf({
300
+ name: 'get-all-envs',
301
+ description: 'Get environment variables for an application',
302
+ namedInputs: {
303
+ project: CliStringInput({
304
+ description: 'Project Id',
305
+ required: true,
306
+ }),
307
+ },
308
+ async action(_, opts) {
309
+ const { project } = opts;
310
+ console.log(await getAllEnvs({ projectId: project }));
311
+ },
312
+ });
313
+
314
+ export const setEnvCLiLeaf = CliLeaf({
315
+ name: 'set-env',
316
+ description: 'Set environment variables for a service',
317
+ positionalInput: CliStringArrayInput({
318
+ placeholder: '<NAME=VALUE> [<NAME=VALUE> ...]',
319
+ required: true,
320
+ }),
321
+ namedInputs: {
322
+ project: CliStringInput({
323
+ description: 'Project Id',
324
+ required: true,
325
+ }),
326
+ service: CliStringInput({
327
+ description:
328
+ 'The name of the docker-compose service to apply environment variable to',
329
+ required: false,
330
+ }),
331
+ },
332
+ async action(args, opts) {
333
+ const { project, service } = opts;
334
+ await setEnv({ projectId: project, vars: args, service });
335
+ },
336
+ });
@@ -13,6 +13,11 @@ import {
13
13
  getAppLogsCliLeaf,
14
14
  listAppReleasesCliLeaf,
15
15
  listAppLatestReleaseCliLeaf,
16
+ restartAppCliLeaf,
17
+ replaceModelsCliLeaf,
18
+ showAppModelsCliLeaf,
19
+ getAllEnvsCLiLeaf,
20
+ setEnvCLiLeaf,
16
21
  } from './app';
17
22
 
18
23
  export const appCliBranch = CliBranch({
@@ -25,12 +30,17 @@ export const appCliBranch = CliBranch({
25
30
  installAppCliLeaf,
26
31
  getAppStatusCliLeaf,
27
32
  startAppCliLeaf,
28
- getAppLogsCliLeaf,
29
33
  stopAppCliLeaf,
34
+ restartAppCliLeaf,
35
+ getAppLogsCliLeaf,
30
36
  uninstallAppCliLeaf,
31
37
  rollbackAppCliLeaf,
38
+ showAppModelsCliLeaf,
32
39
  addModelCliLeaf,
33
40
  removeModelCliLeaf,
41
+ replaceModelsCliLeaf,
34
42
  updateModelsCliLeaf,
43
+ getAllEnvsCLiLeaf,
44
+ setEnvCLiLeaf,
35
45
  ],
36
46
  });
@@ -0,0 +1,63 @@
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 { addDevice, CliAuthenticationClient } from 'alwaysai/lib/infrastructure';
5
+ import { JsSpawner } from 'alwaysai/lib/util';
6
+ import { getCpuUtil, getDiskUtil, getMemUtil } from '../../device-control/device-control';
7
+ import {
8
+ getTargetHardwareUuid,
9
+ writeCertificateAndToken,
10
+ } from '../../infrastructure/certificates-and-tokens';
11
+
12
+ export const initCliLeaf = CliLeaf({
13
+ name: 'init',
14
+ description: 'Initialize device',
15
+ namedInputs: {
16
+ name: CliStringInput({
17
+ description: 'Device name',
18
+ required: true,
19
+ }),
20
+ description: CliStringInput({
21
+ description: 'Device description',
22
+ required: false,
23
+ }),
24
+ },
25
+ async action(_, opts) {
26
+ const { name, description } = opts;
27
+ console.log('Initializing device');
28
+ await checkUserIsLoggedInComponent({ yes: true });
29
+ if (!(await checkPaidPlan())) {
30
+ throw new Error(`This action only supported for Enterprise alwaysAI accounts!`);
31
+ }
32
+ const { username } = await CliAuthenticationClient().getInfo();
33
+ const spawner = JsSpawner();
34
+ const hardwareId = await getTargetHardwareUuid(spawner);
35
+ const deviceToAdd = {
36
+ owner: username,
37
+ friendly_name: name,
38
+ host_name: '',
39
+ device_user_name: '',
40
+ description: description || '',
41
+ hardware_ids: hardwareId,
42
+ device_hash: '',
43
+ iotKeys: '',
44
+ };
45
+ const response = await addDevice(deviceToAdd, 'production');
46
+ await writeCertificateAndToken({ deviceUuid: response.deviceUUID });
47
+ console.log(`Initialized device as ${response.deviceUUID}`);
48
+ },
49
+ });
50
+
51
+ export const getInfoCliLeaf = CliLeaf({
52
+ name: 'get-info',
53
+ description: 'Get device info',
54
+ namedInputs: {},
55
+ async action(_, opts) {
56
+ const deviceInfo = [
57
+ ['CPU Utilization', `${String(await getCpuUtil())} %`],
58
+ ['Disk Utilization', `${String(await getDiskUtil())} %`],
59
+ ['Memory Utilization', `${String(await getMemUtil())} %`],
60
+ ];
61
+ console.table(deviceInfo);
62
+ },
63
+ });
@@ -0,0 +1,8 @@
1
+ import { CliBranch } from '@alwaysai/alwayscli';
2
+ import { getInfoCliLeaf, initCliLeaf } from './device';
3
+
4
+ export const deviceCliBranch = CliBranch({
5
+ name: 'device',
6
+ description: 'Manage current device',
7
+ subcommands: [initCliLeaf, getInfoCliLeaf],
8
+ });
@@ -0,0 +1,60 @@
1
+ import { CliLeaf, CliNumberInput, CliStringInput } from '@alwaysai/alwayscli';
2
+ import { checkUserIsLoggedInComponent } from 'alwaysai/lib/components/user';
3
+ import {
4
+ downloadModelPackageToCache,
5
+ ModelId,
6
+ modelPackageCache,
7
+ } from 'alwaysai/lib/core/model';
8
+ import { CliRpcClient } from 'alwaysai/lib/infrastructure';
9
+ import { JsSpawner } from 'alwaysai/lib/util';
10
+ import { join } from 'path';
11
+
12
+ export const getModelPackageCliLeaf = CliLeaf({
13
+ name: 'get-model-package',
14
+ description: 'Download and unpack a model package',
15
+ positionalInput: CliStringInput({
16
+ description: 'For example, "alwaysai/mobilenet_ssd"',
17
+ required: true,
18
+ placeholder: '<id>',
19
+ }),
20
+ namedInputs: {
21
+ version: CliNumberInput({
22
+ description: 'The version number of the model',
23
+ required: false,
24
+ }),
25
+ path: CliStringInput({
26
+ description: 'The output path to write model package to',
27
+ required: false,
28
+ }),
29
+ },
30
+ async action(id, opts) {
31
+ // NOTE: This code closely follows 'get-model-package.ts' in the CLI
32
+ const { publisher, name } = ModelId.parse(id);
33
+ const path = opts.path ? opts.path : process.cwd();
34
+ // untar will unpack model package contents to <name> so append publisher to path
35
+ const publisherPath = join(path, publisher);
36
+ const spawner = JsSpawner({ path: publisherPath });
37
+
38
+ if (await spawner.exists(name)) {
39
+ console.log(
40
+ `Found existing version of ${id} at ${join(
41
+ publisherPath,
42
+ name,
43
+ )}, removing prior to download`,
44
+ );
45
+ spawner.rimraf(name);
46
+ }
47
+
48
+ console.log(`Downloading ${id} to ${path}`);
49
+ await checkUserIsLoggedInComponent({ yes: true });
50
+ const version =
51
+ opts.version || (await CliRpcClient().getModelVersion({ id })).version;
52
+ if (!modelPackageCache.has(id, version)) {
53
+ await downloadModelPackageToCache(id, version);
54
+ }
55
+ const modelPackageStream = modelPackageCache.read(id, version);
56
+ await spawner.mkdirp();
57
+ await spawner.untar(modelPackageStream);
58
+ console.log(`Completed downloading ${id} to ${path}`);
59
+ },
60
+ });
@@ -1,11 +1,11 @@
1
- import { appCliBranch } from './app/index';
2
- import { getDeviceInfoCliLeaf } from './device-control';
1
+ import { appCliBranch } from './app';
2
+ import { deviceCliBranch } from './device';
3
3
  import { loginCliLeaf } from './login';
4
- // import { installTestAppCliLeaf } from './test-app';
4
+ import { getModelPackageCliLeaf } from './get-model-package';
5
5
 
6
6
  export const subcommands = [
7
7
  loginCliLeaf,
8
8
  appCliBranch,
9
- getDeviceInfoCliLeaf,
10
- // installTestAppCliLeaf,
9
+ deviceCliBranch,
10
+ getModelPackageCliLeaf,
11
11
  ];
@@ -1,4 +1,5 @@
1
1
  import { CliLeaf, CliStringInput, CliUsageError } from '@alwaysai/alwayscli';
2
+ import { writeCertificateAndToken } from '../infrastructure/certificates-and-tokens';
2
3
  import { runCliCmd } from '../util/run-cli-cmd';
3
4
 
4
5
  export const loginCliLeaf = CliLeaf({
@@ -7,18 +8,24 @@ export const loginCliLeaf = CliLeaf({
7
8
  namedInputs: {
8
9
  email: CliStringInput({
9
10
  description: 'alwaysAI email',
11
+ required: true,
10
12
  }),
11
13
  password: CliStringInput({
12
14
  description: 'Account password',
15
+ required: true,
16
+ }),
17
+ device: CliStringInput({
18
+ description: 'The device UUID',
19
+ required: false,
13
20
  }),
14
21
  },
15
22
  async action(_, opts) {
16
- const { email, password } = opts;
17
- if (!email || !password) {
18
- throw new CliUsageError('--email and --password are required!');
19
- }
23
+ const { email, password, device } = opts;
20
24
  await runCliCmd({
21
25
  cmd: ['user', 'login', '--yes', '--email', email, '--password', password],
22
26
  });
27
+ if (device) {
28
+ await writeCertificateAndToken({ deviceUuid: device });
29
+ }
23
30
  },
24
31
  });
@@ -1,4 +1,4 @@
1
- import { JsSpawner } from '../util/spawner/js-spawner';
1
+ import { JsSpawner } from 'alwaysai/lib/util';
2
2
 
3
3
  export async function copyDir(props: { srcPath: string; destPath: string }) {
4
4
  const { srcPath, destPath } = props;
@@ -1,30 +1,25 @@
1
- const os = require('os');
2
- import { join } from 'path';
3
1
  import {
4
- DEVICE_CERT_AND_KEY_DIR_LINUX,
5
- DEV_HOST_CERT_AND_KEY_DIR,
6
2
  DEVICE_CERTIFICATE_FILE_NAME,
7
3
  DEVICE_PRIVATE_KEY_FILE_NAME,
8
4
  DEVICE_ROOT_CERT_FILE_NAME,
9
- } from '../constants';
10
-
11
- const certAndKeyDir = getCertAndKeyDir();
12
-
13
- export function getCertAndKeyDir() {
14
- if (os.type() === 'Darwin' || os.type() === 'Windows_NT') {
15
- return DEV_HOST_CERT_AND_KEY_DIR;
16
- }
17
- return DEVICE_CERT_AND_KEY_DIR_LINUX;
18
- }
5
+ DEVICE_TOKEN_FILE_NAME,
6
+ LOCAL_AAI_CFG_DIR,
7
+ LOCAL_CERT_AND_KEY_DIR,
8
+ } from 'alwaysai/lib/constants';
9
+ import { join } from 'path';
19
10
 
20
11
  export function getPrivateKeyFilePath() {
21
- return join(certAndKeyDir, DEVICE_PRIVATE_KEY_FILE_NAME);
12
+ return join(LOCAL_CERT_AND_KEY_DIR, DEVICE_PRIVATE_KEY_FILE_NAME);
22
13
  }
23
14
 
24
15
  export function getCertificateFilePath() {
25
- return join(certAndKeyDir, DEVICE_CERTIFICATE_FILE_NAME);
16
+ return join(LOCAL_CERT_AND_KEY_DIR, DEVICE_CERTIFICATE_FILE_NAME);
26
17
  }
27
18
 
28
19
  export function getRootCertificateFilePath() {
29
- return join(certAndKeyDir, DEVICE_ROOT_CERT_FILE_NAME);
20
+ return join(LOCAL_CERT_AND_KEY_DIR, DEVICE_ROOT_CERT_FILE_NAME);
21
+ }
22
+
23
+ export function getCredentialsFilePath() {
24
+ return join(LOCAL_AAI_CFG_DIR, DEVICE_TOKEN_FILE_NAME);
30
25
  }
@@ -0,0 +1,22 @@
1
+ import { getCredentialsFilePath } from '../util/directories';
2
+ import { CliTerseError } from '@alwaysai/alwayscli';
3
+ import { ConfigFile } from '@alwaysai/config-nodejs';
4
+ import * as t from 'io-ts';
5
+
6
+ export function getDeviceId() {
7
+ const path = getCredentialsFilePath();
8
+ const codec = t.type({
9
+ deviceId: t.union([t.string, t.undefined]),
10
+ });
11
+ const credentialsJsonFile = ConfigFile({
12
+ path,
13
+ codec,
14
+ });
15
+ const config = credentialsJsonFile.readIfExists();
16
+ if (!config || !config.deviceId) {
17
+ throw new CliTerseError(
18
+ 'Invalid device credentials! Please ensure you are using the device agent on a valid device.',
19
+ );
20
+ }
21
+ return config.deviceId;
22
+ }