@alwaysai/device-agent 1.3.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/lib/application-control/config.js +2 -2
  2. package/lib/application-control/config.js.map +1 -1
  3. package/lib/application-control/environment-variables.d.ts.map +1 -1
  4. package/lib/application-control/environment-variables.js +9 -4
  5. package/lib/application-control/environment-variables.js.map +1 -1
  6. package/lib/application-control/environment-variables.test.js +1 -1
  7. package/lib/application-control/environment-variables.test.js.map +1 -1
  8. package/lib/application-control/install.d.ts.map +1 -1
  9. package/lib/application-control/install.js +7 -2
  10. package/lib/application-control/install.js.map +1 -1
  11. package/lib/application-control/models.d.ts +5 -0
  12. package/lib/application-control/models.d.ts.map +1 -1
  13. package/lib/application-control/models.js +28 -14
  14. package/lib/application-control/models.js.map +1 -1
  15. package/lib/application-control/status.d.ts.map +1 -1
  16. package/lib/application-control/status.js +14 -17
  17. package/lib/application-control/status.js.map +1 -1
  18. package/lib/application-control/utils.js +2 -2
  19. package/lib/application-control/utils.js.map +1 -1
  20. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +5 -5
  21. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  22. package/lib/cloud-connection/device-agent-cloud-connection.js +140 -105
  23. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  24. package/lib/cloud-connection/live-updates-handler.d.ts +4 -2
  25. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  26. package/lib/cloud-connection/live-updates-handler.js +46 -25
  27. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  28. package/lib/cloud-connection/live-updates-handler.test.js +132 -16
  29. package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
  30. package/lib/cloud-connection/messages.d.ts.map +1 -1
  31. package/lib/cloud-connection/messages.js +3 -4
  32. package/lib/cloud-connection/messages.js.map +1 -1
  33. package/lib/cloud-connection/passthrough-handler.d.ts +5 -3
  34. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
  35. package/lib/cloud-connection/passthrough-handler.js +76 -62
  36. package/lib/cloud-connection/passthrough-handler.js.map +1 -1
  37. package/lib/cloud-connection/shadow-handler.d.ts +16 -21
  38. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  39. package/lib/cloud-connection/shadow-handler.js +162 -108
  40. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  41. package/lib/cloud-connection/shadow-handler.test.js +100 -83
  42. package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
  43. package/lib/cloud-connection/transaction-manager.d.ts +3 -0
  44. package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
  45. package/lib/cloud-connection/transaction-manager.js +11 -0
  46. package/lib/cloud-connection/transaction-manager.js.map +1 -1
  47. package/lib/cloud-connection/transaction-manager.test.js +102 -0
  48. package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
  49. package/lib/device-control/device-control.d.ts +16 -15
  50. package/lib/device-control/device-control.d.ts.map +1 -1
  51. package/lib/device-control/device-control.js +117 -18
  52. package/lib/device-control/device-control.js.map +1 -1
  53. package/lib/docker/docker-compose.d.ts +14 -0
  54. package/lib/docker/docker-compose.d.ts.map +1 -0
  55. package/lib/docker/docker-compose.js +56 -0
  56. package/lib/docker/docker-compose.js.map +1 -0
  57. package/lib/index.js +2 -5
  58. package/lib/index.js.map +1 -1
  59. package/lib/infrastructure/agent-config.d.ts +45 -14
  60. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  61. package/lib/infrastructure/agent-config.js +30 -15
  62. package/lib/infrastructure/agent-config.js.map +1 -1
  63. package/lib/infrastructure/agent-config.test.js +3 -0
  64. package/lib/infrastructure/agent-config.test.js.map +1 -1
  65. package/lib/local-connection/rabbitmq-connection.js +11 -11
  66. package/lib/local-connection/rabbitmq-connection.js.map +1 -1
  67. package/lib/secure-tunneling/secure-tunneling.d.ts +97 -0
  68. package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -0
  69. package/lib/secure-tunneling/secure-tunneling.js +435 -0
  70. package/lib/secure-tunneling/secure-tunneling.js.map +1 -0
  71. package/lib/secure-tunneling/secure-tunneling.test.d.ts +2 -0
  72. package/lib/secure-tunneling/secure-tunneling.test.d.ts.map +1 -0
  73. package/lib/secure-tunneling/secure-tunneling.test.js +1070 -0
  74. package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -0
  75. package/lib/secure-tunneling/spawner-detached.d.ts +6 -0
  76. package/lib/secure-tunneling/spawner-detached.d.ts.map +1 -0
  77. package/lib/secure-tunneling/spawner-detached.js +107 -0
  78. package/lib/secure-tunneling/spawner-detached.js.map +1 -0
  79. package/lib/subcommands/app/analytics.d.ts.map +1 -1
  80. package/lib/subcommands/app/analytics.js +9 -13
  81. package/lib/subcommands/app/analytics.js.map +1 -1
  82. package/lib/subcommands/app/env-vars.d.ts.map +1 -1
  83. package/lib/subcommands/app/env-vars.js +11 -16
  84. package/lib/subcommands/app/env-vars.js.map +1 -1
  85. package/lib/subcommands/app/models.d.ts.map +1 -1
  86. package/lib/subcommands/app/models.js +12 -16
  87. package/lib/subcommands/app/models.js.map +1 -1
  88. package/lib/subcommands/device/clean.d.ts.map +1 -1
  89. package/lib/subcommands/device/clean.js +8 -6
  90. package/lib/subcommands/device/clean.js.map +1 -1
  91. package/lib/subcommands/device/get-info.d.ts +2 -0
  92. package/lib/subcommands/device/get-info.d.ts.map +1 -0
  93. package/lib/subcommands/device/get-info.js +36 -0
  94. package/lib/subcommands/device/get-info.js.map +1 -0
  95. package/lib/subcommands/device/index.d.ts.map +1 -1
  96. package/lib/subcommands/device/index.js +11 -2
  97. package/lib/subcommands/device/index.js.map +1 -1
  98. package/lib/subcommands/device/init.d.ts +5 -0
  99. package/lib/subcommands/device/init.d.ts.map +1 -0
  100. package/lib/subcommands/device/{device.js → init.js} +5 -36
  101. package/lib/subcommands/device/init.js.map +1 -0
  102. package/lib/subcommands/device/refresh.d.ts +2 -0
  103. package/lib/subcommands/device/refresh.d.ts.map +1 -0
  104. package/lib/subcommands/device/refresh.js +24 -0
  105. package/lib/subcommands/device/refresh.js.map +1 -0
  106. package/lib/subcommands/device/restart.d.ts +2 -0
  107. package/lib/subcommands/device/restart.d.ts.map +1 -0
  108. package/lib/subcommands/device/restart.js +14 -0
  109. package/lib/subcommands/device/restart.js.map +1 -0
  110. package/lib/util/check-for-updates.d.ts +3 -0
  111. package/lib/util/check-for-updates.d.ts.map +1 -0
  112. package/lib/util/check-for-updates.js +69 -0
  113. package/lib/util/check-for-updates.js.map +1 -0
  114. package/lib/util/cloud-mode-ready.d.ts +1 -0
  115. package/lib/util/cloud-mode-ready.d.ts.map +1 -1
  116. package/lib/util/cloud-mode-ready.js +36 -1
  117. package/lib/util/cloud-mode-ready.js.map +1 -1
  118. package/lib/util/file.d.ts +7 -0
  119. package/lib/util/file.d.ts.map +1 -0
  120. package/lib/util/file.js +66 -0
  121. package/lib/util/file.js.map +1 -0
  122. package/lib/util/file.test.d.ts +2 -0
  123. package/lib/util/file.test.d.ts.map +1 -0
  124. package/lib/util/file.test.js +87 -0
  125. package/lib/util/file.test.js.map +1 -0
  126. package/package.json +8 -7
  127. package/readme.md +3 -3
  128. package/src/application-control/config.ts +1 -1
  129. package/src/application-control/environment-variables.test.ts +1 -1
  130. package/src/application-control/environment-variables.ts +9 -6
  131. package/src/application-control/install.ts +8 -3
  132. package/src/application-control/models.ts +47 -19
  133. package/src/application-control/status.ts +16 -14
  134. package/src/application-control/utils.ts +1 -1
  135. package/src/cloud-connection/device-agent-cloud-connection.ts +202 -148
  136. package/src/cloud-connection/live-updates-handler.test.ts +161 -20
  137. package/src/cloud-connection/live-updates-handler.ts +63 -31
  138. package/src/cloud-connection/messages.ts +3 -4
  139. package/src/cloud-connection/passthrough-handler.ts +98 -76
  140. package/src/cloud-connection/shadow-handler.test.ts +101 -84
  141. package/src/cloud-connection/shadow-handler.ts +287 -133
  142. package/src/cloud-connection/transaction-manager.test.ts +124 -0
  143. package/src/cloud-connection/transaction-manager.ts +15 -0
  144. package/src/device-control/device-control.ts +125 -23
  145. package/src/docker/docker-compose.ts +60 -0
  146. package/src/index.ts +2 -6
  147. package/src/infrastructure/agent-config.test.ts +3 -0
  148. package/src/infrastructure/agent-config.ts +38 -40
  149. package/src/local-connection/rabbitmq-connection.ts +8 -8
  150. package/src/secure-tunneling/secure-tunneling.test.ts +1239 -0
  151. package/src/secure-tunneling/secure-tunneling.ts +599 -0
  152. package/src/secure-tunneling/spawner-detached.ts +123 -0
  153. package/src/subcommands/app/analytics.ts +16 -13
  154. package/src/subcommands/app/env-vars.ts +18 -16
  155. package/src/subcommands/app/models.ts +20 -16
  156. package/src/subcommands/device/clean.ts +5 -2
  157. package/src/subcommands/device/get-info.ts +49 -0
  158. package/src/subcommands/device/index.ts +11 -2
  159. package/src/subcommands/device/{device.ts → init.ts} +5 -47
  160. package/src/subcommands/device/refresh.ts +22 -0
  161. package/src/subcommands/device/restart.ts +11 -0
  162. package/src/util/check-for-updates.ts +69 -0
  163. package/src/util/cloud-mode-ready.ts +36 -0
  164. package/src/util/file.test.ts +90 -0
  165. package/src/util/file.ts +76 -0
  166. package/lib/docker/docker-compose-cmd.d.ts +0 -5
  167. package/lib/docker/docker-compose-cmd.d.ts.map +0 -1
  168. package/lib/docker/docker-compose-cmd.js +0 -16
  169. package/lib/docker/docker-compose-cmd.js.map +0 -1
  170. package/lib/secure-tunneling/index.d.ts +0 -5
  171. package/lib/secure-tunneling/index.d.ts.map +0 -1
  172. package/lib/secure-tunneling/index.js +0 -64
  173. package/lib/secure-tunneling/index.js.map +0 -1
  174. package/lib/subcommands/device/device.d.ts +0 -7
  175. package/lib/subcommands/device/device.d.ts.map +0 -1
  176. package/lib/subcommands/device/device.js.map +0 -1
  177. package/lib/util/safe-rimraf.d.ts +0 -2
  178. package/lib/util/safe-rimraf.d.ts.map +0 -1
  179. package/lib/util/safe-rimraf.js +0 -16
  180. package/lib/util/safe-rimraf.js.map +0 -1
  181. package/src/docker/docker-compose-cmd.ts +0 -15
  182. package/src/secure-tunneling/index.ts +0 -74
  183. package/src/util/safe-rimraf.ts +0 -14
@@ -1,38 +1,50 @@
1
- import { SystemInformationPayload } from '@alwaysai/device-agent-schemas';
1
+ import { SystemInformationShadowUpdate } from '@alwaysai/device-agent-schemas';
2
2
  import { logger } from '../util/logger';
3
3
  import * as osu from 'node-os-utils';
4
4
  import * as si from 'systeminformation';
5
5
  import { exec } from 'child_process';
6
6
  import { promisify } from 'util';
7
+ import { JsSpawner } from 'alwaysai/lib/util';
8
+ import { DeviceStatsPayload } from '@alwaysai/device-agent-schemas';
9
+ import { getDeviceAgentVersion } from '../util/check-for-updates';
7
10
 
8
11
  const exec_promise = promisify(exec);
9
12
 
10
13
  // Device Stats
11
- export async function getCpuDetails() {
14
+ export async function getCpuDetails(): Promise<
15
+ DeviceStatsPayload['cpuDetails']
16
+ > {
12
17
  const cpuFree = await osu.cpu.free();
13
18
  const cpuTemp = await si.cpuTemperature();
14
- return {
15
- usedPerc: 100.0 - cpuFree,
16
- temperature: cpuTemp.main
17
- };
19
+ const cpuDetails: DeviceStatsPayload['cpuDetails'] = {};
20
+ if (cpuFree !== null) cpuDetails.usedPerc = 100 - cpuFree;
21
+ if (cpuTemp?.main !== null) cpuDetails.temperature = cpuTemp.main;
22
+ return cpuDetails;
18
23
  }
19
24
 
20
- export async function getDiskDetails() {
25
+ export async function getDiskDetails(): Promise<
26
+ DeviceStatsPayload['diskDetails']
27
+ > {
21
28
  // Types incorrectly specify diskname as required instead of optional
22
29
  // @ts-expect-error
23
30
  const driveInfo = await osu.drive.info();
24
- return {
25
- usedGb: parseFloat(driveInfo.usedGb),
26
- freeGb: parseFloat(driveInfo.freeGb)
27
- };
31
+ const diskDetails: DeviceStatsPayload['diskDetails'] = {};
32
+ if (driveInfo?.usedGb !== null)
33
+ diskDetails.usedGb = parseFloat(driveInfo.usedGb);
34
+ if (driveInfo?.freeGb !== null) {
35
+ diskDetails.freeGb = parseFloat(driveInfo.freeGb);
36
+ }
37
+ return diskDetails;
28
38
  }
29
39
 
30
- export async function getMemDetails() {
40
+ export async function getMemDetails(): Promise<
41
+ DeviceStatsPayload['memDetails']
42
+ > {
31
43
  const memInfo = await osu.mem.info();
32
- return {
33
- usedMb: memInfo.usedMemMb,
34
- freeMb: memInfo.freeMemMb
35
- };
44
+ const memDetails: DeviceStatsPayload['memDetails'] = {};
45
+ if (memInfo?.usedMemMb !== null) memDetails.usedMb = memInfo.usedMemMb;
46
+ if (memInfo?.freeMemMb !== null) memDetails.freeMb = memInfo.freeMemMb;
47
+ return memDetails;
36
48
  }
37
49
 
38
50
  // System information
@@ -102,26 +114,116 @@ export async function getNetworkInfo() {
102
114
  };
103
115
  }
104
116
 
117
+ export async function getDockerVersion() {
118
+ try {
119
+ const spawner = JsSpawner();
120
+ const result = JSON.parse(
121
+ await spawner.run({
122
+ exe: 'docker',
123
+ args: ['info', '--format', 'json']
124
+ })
125
+ );
126
+ return result.ClientInfo.Version;
127
+ } catch (e) {
128
+ logger.warn(`Cannot get Docker version: ${e}`);
129
+ return 'Not found';
130
+ }
131
+ }
132
+
133
+ export async function getDockerComposeVersion() {
134
+ try {
135
+ const spawner = JsSpawner();
136
+ return await spawner.run({
137
+ exe: 'docker',
138
+ args: ['compose', 'version']
139
+ });
140
+ } catch (e) {
141
+ logger.warn(`Cannot get Docker Compose version: ${e}`);
142
+ return 'Not found';
143
+ }
144
+ }
145
+
146
+ export async function getNpmVersion() {
147
+ try {
148
+ const spawner = JsSpawner();
149
+ return await spawner.run({
150
+ exe: 'npm',
151
+ args: ['--version']
152
+ });
153
+ } catch (e) {
154
+ logger.warn(`Cannot get npm version: ${e}`);
155
+ return 'Not found';
156
+ }
157
+ }
158
+
159
+ export async function getNodeVersion() {
160
+ try {
161
+ const spawner = JsSpawner();
162
+ return await spawner.run({
163
+ exe: 'node',
164
+ args: ['-v']
165
+ });
166
+ } catch (e) {
167
+ logger.warn(`Cannot get Node version: ${e}`);
168
+ return 'Not found';
169
+ }
170
+ }
171
+
105
172
  export async function getPackageVersions() {
106
- // eslint-disable-next-line
107
- const agentJson = require('../../package.json');
173
+ const agentVersion = await getDeviceAgentVersion();
108
174
  // eslint-disable-next-line
109
175
  const deviceAgentSchemasJson = require('../../node_modules/@alwaysai/device-agent-schemas/package.json');
176
+
177
+ // Concurrent asynchronous function call
178
+ const [dockerVersion, dockerComposeVersion, nodeVersion, npmVersion] =
179
+ await Promise.all([
180
+ getDockerVersion(),
181
+ getDockerComposeVersion(),
182
+ getNodeVersion(),
183
+ getNpmVersion()
184
+ ]);
185
+
110
186
  return {
111
- agent: agentJson.version,
112
- deviceAgentSchemas: deviceAgentSchemasJson.version
187
+ agent: agentVersion,
188
+ deviceAgentSchemas: deviceAgentSchemasJson.version,
189
+ docker: dockerVersion,
190
+ dockerCompose: dockerComposeVersion,
191
+ node: nodeVersion,
192
+ npm: npmVersion
113
193
  };
114
194
  }
115
195
 
116
- export async function getSystemInformation(): Promise<SystemInformationPayload> {
196
+ export async function getLastBootTime() {
197
+ try {
198
+ const out = await exec_promise('journalctl --list-boots');
199
+ if (!out || out.stderr) {
200
+ logger.error(`Stderr when getting last boot time: ${out.stderr}`);
201
+ return undefined;
202
+ }
203
+
204
+ const bootTimes = out.stdout.split('\n');
205
+ const latestBootStdout = (bootTimes.pop() || bootTimes.pop())?.trim(); // possible last \n causes '' at end of array
206
+ if (!latestBootStdout) return undefined;
207
+
208
+ const tokens = latestBootStdout.trim().split(' ');
209
+
210
+ return new Date(`${tokens[2]} ${tokens[3]} ${tokens[4]}`);
211
+ } catch (e) {
212
+ logger.error(`Issue getting last boot time: ${e.message}`);
213
+ return undefined;
214
+ }
215
+ }
216
+
217
+ export async function getSystemInformation(): Promise<SystemInformationShadowUpdate> {
117
218
  try {
118
- const systemInfo: SystemInformationPayload = {
219
+ const systemInfo: SystemInformationShadowUpdate = {
119
220
  os: await getOsInfo(),
120
221
  cpu: await getCpuInfo(),
121
222
  disk: await getDiskInfo(),
122
223
  device: await getDeviceInfo(),
123
224
  network: await getNetworkInfo(),
124
- versions: await getPackageVersions()
225
+ versions: await getPackageVersions(),
226
+ lastBootTime: (await getLastBootTime())?.toString()
125
227
  };
126
228
  return systemInfo;
127
229
  } catch (e) {
@@ -0,0 +1,60 @@
1
+ import * as DockerComposeV1 from 'docker-compose';
2
+ import { v2 as DockerComposeV2 } from 'docker-compose';
3
+ import { execSync } from 'child_process';
4
+ import { logger } from '../util/logger';
5
+ import { JsSpawner } from 'alwaysai/lib/util';
6
+
7
+ let dockerCmd = 'docker';
8
+
9
+ export function importDockerCompose():
10
+ | typeof DockerComposeV1
11
+ | typeof DockerComposeV2 {
12
+ try {
13
+ execSync('docker compose version').toString();
14
+ logger.debug('Using Docker Compose V2.');
15
+ return DockerComposeV2;
16
+ } catch (e) {
17
+ try {
18
+ execSync('docker-compose -v').toString();
19
+ logger.warn('Using docker-compose V1. Please consider updating to V2.');
20
+ } catch (e) {
21
+ logger.warn(`Could not determine compose: ${e}`);
22
+ }
23
+ }
24
+ dockerCmd = 'docker-compose';
25
+ return DockerComposeV1;
26
+ }
27
+
28
+ export const compose = importDockerCompose();
29
+
30
+ export async function runDockerComposeCmd(props: {
31
+ args: string[];
32
+ dir: string;
33
+ }) {
34
+ const { args, dir } = props;
35
+ const spawner = JsSpawner();
36
+ if (dockerCmd === 'docker') {
37
+ args.unshift('compose');
38
+ }
39
+ const output = await spawner.run({
40
+ exe: dockerCmd,
41
+ args,
42
+ cwd: dir
43
+ });
44
+ return output;
45
+ }
46
+
47
+ export async function runStreamingDockerComposeCmd(props: {
48
+ args: string[];
49
+ dir: string;
50
+ }) {
51
+ const { args, dir } = props;
52
+ if (dockerCmd === 'docker') {
53
+ args.unshift('compose');
54
+ }
55
+ return await JsSpawner().runStreaming({
56
+ exe: dockerCmd,
57
+ args,
58
+ cwd: dir
59
+ });
60
+ }
package/src/index.ts CHANGED
@@ -10,13 +10,9 @@ import { root } from './root';
10
10
  import { runDeviceAgentCloudInterface } from './cloud-connection/device-agent-cloud-connection';
11
11
  import { AgentConfigFile } from './infrastructure/agent-config';
12
12
  import { ALWAYSAI_DEVICE_AGENT_MODE } from './environment';
13
- import { logger } from './util/logger';
14
-
15
- // eslint-disable-next-line @typescript-eslint/no-var-requires
16
- const { version } = require('../package.json');
13
+ import { checkForUpdatesAndPrompt } from './util/check-for-updates';
17
14
 
18
15
  if (module === require.main) {
19
- logger.info(`Starting alwaysAI Device Agent v${version}`);
20
16
  if (!AgentConfigFile().exists()) {
21
17
  AgentConfigFile().initialize();
22
18
  }
@@ -24,6 +20,6 @@ if (module === require.main) {
24
20
  if (ALWAYSAI_DEVICE_AGENT_MODE === 'cloud') {
25
21
  void runDeviceAgentCloudInterface();
26
22
  } else {
27
- void runCliAndExit(root, {});
23
+ void runCliAndExit(root, { postRun: checkForUpdatesAndPrompt });
28
24
  }
29
25
  }
@@ -95,6 +95,9 @@ describe('Test Agent Config', () => {
95
95
  expect(await configFile.getAppVersion({ projectId })).toEqual(version);
96
96
  await configFile.setAppInstalled({ projectId, version });
97
97
  expect(await configFile.getAppVersion({ projectId })).toEqual(version);
98
+ expect(await configFile.isAppReady({ projectId })).toEqual(true);
99
+ await configFile.setAppUninstalling({ projectId });
100
+ expect(await configFile.isAppReady({ projectId })).toEqual(false);
98
101
  await configFile.setAppUninstalled({ projectId });
99
102
  const apps = await configFile.getApps();
100
103
  expect(apps).toEqual([]);
@@ -58,26 +58,7 @@ const ALWAYSAI_CONFIG_DIR = join(homedir(), '.config', 'alwaysai');
58
58
 
59
59
  const AGENT_CONFIG_FILE_NAME = 'alwaysai.agent.json';
60
60
 
61
- export interface AgentJsonFileReturnType
62
- extends ConfigFileSchemaReturnType<AgentConfig> {
63
- name: string;
64
- getApps: () => Promise<InstalledAppConfig[]>;
65
- getReadyApps;
66
- getApp;
67
- isAppPresent;
68
- isAppReady;
69
- removeApp;
70
- setAppInstalling;
71
- setAppInstalled;
72
- setAppUninstalled;
73
- getAppVersion: (props: { projectId: string }) => Promise<string>;
74
- setAppBackup;
75
- getAppBackup;
76
- }
77
-
78
- export function AgentConfigFile(
79
- dir = ALWAYSAI_CONFIG_DIR
80
- ): AgentJsonFileReturnType {
61
+ export function AgentConfigFile(dir = ALWAYSAI_CONFIG_DIR) {
81
62
  const path = join(dir, AGENT_CONFIG_FILE_NAME);
82
63
  const initialValue: AgentConfig = {
83
64
  applications: []
@@ -88,31 +69,14 @@ export function AgentConfigFile(
88
69
  initialValue
89
70
  });
90
71
 
91
- return {
92
- ...configFile,
93
- name: AGENT_CONFIG_FILE_NAME,
94
- getApps,
95
- getReadyApps,
96
- getApp,
97
- isAppPresent,
98
- isAppReady,
99
- removeApp,
100
- setAppInstalling,
101
- setAppInstalled,
102
- setAppUninstalled,
103
- getAppVersion,
104
- setAppBackup,
105
- getAppBackup
106
- };
107
-
108
72
  async function getApps() {
109
73
  const config = configFile.read();
110
- return config && config.applications ? config.applications : [];
74
+ return config?.applications ? config.applications : [];
111
75
  }
112
76
 
113
77
  async function getReadyApps() {
114
78
  const config = configFile.read();
115
- return config && config.applications
79
+ return config?.applications
116
80
  ? config.applications.filter((app) => {
117
81
  return app.ready;
118
82
  })
@@ -205,6 +169,23 @@ export function AgentConfigFile(
205
169
  }
206
170
  }
207
171
 
172
+ async function setAppUninstalling(props: { projectId: string }) {
173
+ const { projectId } = props;
174
+ const app = await getApp({ projectId });
175
+ if (app) {
176
+ await removeApp({ projectId });
177
+ const config = configFile.read();
178
+ config.applications.push({ ...app, ...{ ready: false } });
179
+ configFile.write(config);
180
+ } else {
181
+ // NOTE: we should never be setting an app as installed
182
+ // if it doesn't exist (setAppInstalling was never called)
183
+ throw new Error(
184
+ `App ${projectId} was not previously configured and could not be set to installed!`
185
+ );
186
+ }
187
+ }
188
+
208
189
  async function setAppUninstalled(props: { projectId: string }) {
209
190
  const { projectId } = props;
210
191
  await removeApp({ projectId });
@@ -235,9 +216,26 @@ export function AgentConfigFile(
235
216
  async function getAppBackup(props: { projectId: string }) {
236
217
  const { projectId } = props;
237
218
  const app = await getApp({ projectId });
238
- if (app && app.backup) {
219
+ if (app?.backup) {
239
220
  return app.backup;
240
221
  }
241
222
  return null;
242
223
  }
224
+
225
+ return {
226
+ ...configFile,
227
+ name: AGENT_CONFIG_FILE_NAME,
228
+ getApps,
229
+ getReadyApps,
230
+ getApp,
231
+ isAppPresent,
232
+ isAppReady,
233
+ setAppInstalling,
234
+ setAppInstalled,
235
+ setAppUninstalling,
236
+ setAppUninstalled,
237
+ getAppVersion,
238
+ setAppBackup,
239
+ getAppBackup
240
+ };
243
241
  }
@@ -1,6 +1,6 @@
1
1
  import { logger } from '../util/logger';
2
2
  import sleep from '../util/sleep';
3
- import compose from 'docker-compose';
3
+ import { compose } from '../docker/docker-compose';
4
4
  import * as YAML from 'yaml';
5
5
 
6
6
  import {
@@ -23,19 +23,19 @@ export async function checkRabbitMQContainerRunning() {
23
23
  return false;
24
24
  }
25
25
  const containerData = await compose.ps({ cwd: DEVICE_AGENT_CFG_PATH });
26
- if (!(containerData === undefined)) {
26
+ if (containerData !== undefined) {
27
27
  const rabbitmqService = containerData.data.services[0];
28
28
  if (
29
- rabbitmqService.name === rabbitMQContainerName &&
30
- rabbitmqService.state === 'Up'
29
+ rabbitmqService?.name === rabbitMQContainerName &&
30
+ rabbitmqService.state.includes('Up')
31
31
  ) {
32
- logger.debug('alwaysAI Local Connection is running');
32
+ logger.debug('alwaysAI Local Connection Container is up');
33
33
  return true;
34
34
  }
35
- logger.debug('alwaysAI Local Connection is not running');
35
+ logger.debug('alwaysAI Local Connection Container is not up');
36
36
  return false;
37
37
  }
38
- logger.warn('alwaysAI Local Connection container was undefined');
38
+ logger.warn('alwaysAI Local Connection Container is undefined');
39
39
  return false;
40
40
  }
41
41
 
@@ -97,7 +97,7 @@ export async function setupRabbitMQContainer() {
97
97
  }
98
98
  } catch (e) {
99
99
  logger.error(
100
- `Unable to start alwaysAI Device Agent Local Connection Container:\n${e.messaage}`
100
+ `Unable to start alwaysAI Device Agent Local Connection Container:\n${e}`
101
101
  );
102
102
  }
103
103
  }