@alwaysai/device-agent 0.1.6 → 1.0.0-pre-release

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 (114) hide show
  1. package/LICENSE +12 -0
  2. package/lib/application-control/config.d.ts.map +1 -1
  3. package/lib/application-control/config.js +6 -1
  4. package/lib/application-control/config.js.map +1 -1
  5. package/lib/application-control/index.d.ts +2 -2
  6. package/lib/application-control/index.d.ts.map +1 -1
  7. package/lib/application-control/index.js +2 -2
  8. package/lib/application-control/index.js.map +1 -1
  9. package/lib/application-control/install.d.ts +2 -2
  10. package/lib/application-control/install.d.ts.map +1 -1
  11. package/lib/application-control/install.js +23 -0
  12. package/lib/application-control/install.js.map +1 -1
  13. package/lib/application-control/status.d.ts +3 -3
  14. package/lib/application-control/status.d.ts.map +1 -1
  15. package/lib/application-control/status.js +4 -4
  16. package/lib/application-control/status.js.map +1 -1
  17. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +7 -7
  18. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  19. package/lib/cloud-connection/device-agent-cloud-connection.js +158 -100
  20. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  21. package/lib/cloud-connection/live-updates-handler.d.ts +9 -9
  22. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  23. package/lib/cloud-connection/live-updates-handler.js +45 -42
  24. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  25. package/lib/cloud-connection/live-updates-handler.test.js +6 -5
  26. package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
  27. package/lib/cloud-connection/message-builder.d.ts +7 -0
  28. package/lib/cloud-connection/message-builder.d.ts.map +1 -0
  29. package/lib/cloud-connection/message-builder.js +63 -0
  30. package/lib/cloud-connection/message-builder.js.map +1 -0
  31. package/lib/cloud-connection/messages.d.ts +5 -15
  32. package/lib/cloud-connection/messages.d.ts.map +1 -1
  33. package/lib/cloud-connection/messages.js +22 -31
  34. package/lib/cloud-connection/messages.js.map +1 -1
  35. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
  36. package/lib/cloud-connection/passthrough-handler.js +4 -2
  37. package/lib/cloud-connection/passthrough-handler.js.map +1 -1
  38. package/lib/cloud-connection/publisher.d.ts +4 -5
  39. package/lib/cloud-connection/publisher.d.ts.map +1 -1
  40. package/lib/cloud-connection/publisher.js +12 -21
  41. package/lib/cloud-connection/publisher.js.map +1 -1
  42. package/lib/cloud-connection/transaction-queue.d.ts +12 -0
  43. package/lib/cloud-connection/transaction-queue.d.ts.map +1 -0
  44. package/lib/cloud-connection/transaction-queue.js +38 -0
  45. package/lib/cloud-connection/transaction-queue.js.map +1 -0
  46. package/lib/cloud-connection/transaction-queue.test.d.ts +2 -0
  47. package/lib/cloud-connection/transaction-queue.test.d.ts.map +1 -0
  48. package/lib/cloud-connection/transaction-queue.test.js +46 -0
  49. package/lib/cloud-connection/transaction-queue.test.js.map +1 -0
  50. package/lib/environment.d.ts +3 -0
  51. package/lib/environment.d.ts.map +1 -1
  52. package/lib/environment.js +4 -1
  53. package/lib/environment.js.map +1 -1
  54. package/lib/index.js +0 -0
  55. package/lib/local-connection/constants.d.ts +4 -0
  56. package/lib/local-connection/constants.d.ts.map +1 -0
  57. package/lib/local-connection/constants.js +14 -0
  58. package/lib/local-connection/constants.js.map +1 -0
  59. package/lib/local-connection/rabbitmq-connection.d.ts +1 -1
  60. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
  61. package/lib/local-connection/rabbitmq-connection.js +17 -2
  62. package/lib/local-connection/rabbitmq-connection.js.map +1 -1
  63. package/lib/secure-tunneling/index.js +1 -4
  64. package/lib/secure-tunneling/index.js.map +1 -1
  65. package/lib/subcommands/app/index.d.ts.map +1 -1
  66. package/lib/subcommands/app/index.js +1 -0
  67. package/lib/subcommands/app/index.js.map +1 -1
  68. package/lib/subcommands/app/models.d.ts +5 -0
  69. package/lib/subcommands/app/models.d.ts.map +1 -1
  70. package/lib/subcommands/app/models.js +42 -1
  71. package/lib/subcommands/app/models.js.map +1 -1
  72. package/lib/subcommands/app/status.js +1 -1
  73. package/lib/subcommands/app/status.js.map +1 -1
  74. package/lib/subcommands/app/version.d.ts.map +1 -1
  75. package/lib/subcommands/app/version.js +9 -11
  76. package/lib/subcommands/app/version.js.map +1 -1
  77. package/lib/subcommands/device/clean.d.ts.map +1 -1
  78. package/lib/subcommands/device/clean.js +13 -0
  79. package/lib/subcommands/device/clean.js.map +1 -1
  80. package/lib/subcommands/index.d.ts +2 -2
  81. package/lib/subcommands/index.d.ts.map +1 -1
  82. package/lib/urls.d.ts +1 -1
  83. package/lib/urls.d.ts.map +1 -1
  84. package/lib/urls.js +2 -1
  85. package/lib/urls.js.map +1 -1
  86. package/package.json +5 -4
  87. package/readme.md +30 -1
  88. package/src/application-control/config.ts +5 -1
  89. package/src/application-control/index.ts +2 -2
  90. package/src/application-control/install.ts +36 -4
  91. package/src/application-control/status.ts +9 -8
  92. package/src/cloud-connection/device-agent-cloud-connection.ts +225 -132
  93. package/src/cloud-connection/live-updates-handler.test.ts +6 -5
  94. package/src/cloud-connection/live-updates-handler.ts +90 -64
  95. package/src/cloud-connection/message-builder.ts +117 -0
  96. package/src/cloud-connection/messages.ts +27 -35
  97. package/src/cloud-connection/passthrough-handler.ts +12 -2
  98. package/src/cloud-connection/publisher.ts +17 -30
  99. package/src/cloud-connection/transaction-queue.test.ts +55 -0
  100. package/src/cloud-connection/transaction-queue.ts +40 -0
  101. package/src/environment.ts +7 -0
  102. package/src/local-connection/constants.ts +16 -0
  103. package/src/local-connection/rabbitmq-connection.ts +22 -2
  104. package/src/secure-tunneling/index.ts +1 -4
  105. package/src/subcommands/app/index.ts +3 -1
  106. package/src/subcommands/app/models.ts +44 -0
  107. package/src/subcommands/app/status.ts +2 -2
  108. package/src/subcommands/app/version.ts +16 -14
  109. package/src/subcommands/device/clean.ts +21 -1
  110. package/src/urls.ts +3 -1
  111. package/lib/docker/secure-tunnel-docker.d.ts +0 -2
  112. package/lib/docker/secure-tunnel-docker.d.ts.map +0 -1
  113. package/lib/docker/secure-tunnel-docker.js +0 -49
  114. package/lib/docker/secure-tunnel-docker.js.map +0 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@alwaysai/device-agent",
3
3
  "description": "The alwaysAI Device Agent",
4
- "version": "0.1.6",
4
+ "version": "1.0.0-pre-release",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "publishConfig": {
@@ -37,9 +37,9 @@
37
37
  "@alwaysai/alwayscli": "0.3.2",
38
38
  "@alwaysai/app-configuration-schemas": "0.1.0",
39
39
  "@alwaysai/config-nodejs": "0.3.0",
40
- "@alwaysai/device-agent-schemas": "1.2.0",
40
+ "@alwaysai/device-agent-schemas": "2.1.2",
41
41
  "ajv": "8.11.0",
42
- "alwaysai": "2.1.0",
42
+ "alwaysai": "2.2.0",
43
43
  "amqplib": "0.10.3",
44
44
  "aws-iot-device-sdk": "2.2.12",
45
45
  "docker-compose": "0.23.17",
@@ -91,5 +91,6 @@
91
91
  "name": "alwaysAI, Inc.",
92
92
  "email": "contact@alwaysai.co"
93
93
  },
94
- "homepage": "https://alwaysai.co"
94
+ "homepage": "https://alwaysai.co",
95
+ "license": "SEE LICENSE IN LICENSE"
95
96
  }
package/readme.md CHANGED
@@ -63,7 +63,7 @@ Where:
63
63
  devices page of the alwaysAI Dashboard. If a device name is not provided, one
64
64
  will be generated for you and logged to the console for reference.
65
65
 
66
- **Important note**: If your password contains one or more special characters and you receive an error message that your password does not match your username but you are sure that it is correctly entered, please try enclosing your password with double quotes and re-running the provisioning command. You can also reset your password at https://console.alwaysai.co/dashboard by logging out, navigating to the sign in page, and clicking '`Forgot Password?`'.
66
+ **Important note**: If your password contains one or more special characters and you receive an error message that your password does not match your username but you are sure that it is correctly entered, please try preceding every special character in your password with a backslash, and re-running the provisioning command. You can also reset your password at https://console.alwaysai.co/dashboard by logging out, navigating to the sign in page, and clicking '`Forgot Password?`'.
67
67
 
68
68
  Confirm the Device Agent is running with the following command:
69
69
 
@@ -379,3 +379,32 @@ service run the following command on the device:
379
379
  ```bash
380
380
  $ aai-agent app set-env TEST_ENV=1 --project <project_id> --service alwaysai
381
381
  ```
382
+ ## Device Cleaning and Uninstalling
383
+ In order to fully clean the device and uninstall the agent, use the following steps:
384
+
385
+ ### 1. Stop PM2 instance of the device agent
386
+ Using `pm2 list`, display the list of current pm2 instances. The output should look like this:
387
+ ```bash
388
+ $ pm2 list
389
+ ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
390
+ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │
391
+ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
392
+ │ 0 │ aai-agent │ fork │ 15 │ online │ 0% │ 2.8mb │
393
+ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
394
+ ```
395
+ Start with `pm2 stop <id>` where `<id>` is the id of the aai-agent.
396
+ Then, run `pm2 delete 0`.
397
+ Follow it with these two commands:
398
+ `pm2 flush`, `pm2 unstartup`
399
+
400
+ ### 2. Remove alwaysAI Provisioned Device
401
+ Open a new terminal.
402
+ Run `aai-agent device clean`
403
+
404
+ ### 3. Uninstall aai Device Agent from the device
405
+ Run `sudo npm uninstall -g @alwaysai/device-agent`
406
+ Verify successful removal by running `aai-agent`. You should see a response similar to `-bash: /usr/bin/aai-agent: No such file or directory`.
407
+
408
+ ### 4. Remove the device from the aai Dashboard
409
+ Go to https://console.alwaysai.co/dashboard/devices, Go to Devices, find the device in question, and remove the device using the trashcan icon.
410
+
@@ -121,6 +121,10 @@ export async function writeDockerCompose(props: {
121
121
  const spawner = JsSpawner({ path: appDir });
122
122
  const composeOutput = stringify(dockerCompose);
123
123
  // Validate new contents
124
- await compose.config({ cwd: appDir, configAsString: composeOutput });
124
+ try {
125
+ await compose.config({ cwd: appDir, configAsString: composeOutput });
126
+ } catch (e) {
127
+ logger.error(JSON.stringify(e));
128
+ }
125
129
  await spawner.writeFile('docker-compose.yaml', composeOutput);
126
130
  }
@@ -2,7 +2,7 @@ import { readAppCfgFile, updateAppCfg } from './config';
2
2
  import { installApp, uninstallApp } from './install';
3
3
  import { rollbackApp } from './backup';
4
4
  import {
5
- getAppStatus,
5
+ getAppState,
6
6
  startApp,
7
7
  getAppLogs,
8
8
  stopApp,
@@ -17,7 +17,7 @@ export {
17
17
  installApp,
18
18
  uninstallApp,
19
19
  rollbackApp,
20
- getAppStatus,
20
+ getAppState,
21
21
  startApp,
22
22
  getAppLogs,
23
23
  stopApp,
@@ -4,9 +4,9 @@ import * as path from 'path';
4
4
  import { buildDockerImage } from 'alwaysai/lib/util/docker';
5
5
  import { JsSpawner, Spawner } from 'alwaysai/lib/util';
6
6
  import { getAppDir, downloadPackageUsingPresignedUrl, buildApp } from './utils';
7
- import { AppDetailsPacket } from '@alwaysai/device-agent-schemas';
7
+ import { AppDetails } from '@alwaysai/device-agent-schemas';
8
8
  import { BACKUP_EXT } from './backup';
9
- import { startApp, stopApp } from './status';
9
+ import { startApp, stopApp, isAppStarted } from './status';
10
10
  import { AgentConfigFile } from '../infrastructure/agent-config';
11
11
  import { ProjectJsonFile } from 'alwaysai/lib/core/project';
12
12
  import {
@@ -22,6 +22,12 @@ import { DOCKER_IMAGE_ID_INITIAL_VALUE } from 'alwaysai/lib/constants';
22
22
  import { runInDir } from '../util/run-in-dir';
23
23
  import { installModelsWithPresignedURLs } from './models';
24
24
  import { logger } from '../util/logger';
25
+ import { updateAppCfgFile } from './config';
26
+ import {
27
+ LOCAL_CONNECTION_HOST,
28
+ LOCAL_CONNECTION_PORT,
29
+ LOCAL_CONNECTION_ROUTING_KEY
30
+ } from '../local-connection/constants';
25
31
  import { DOCKERFILE, PYTHON_REQUIREMENTS_FILE_NAME } from 'alwaysai/lib/paths';
26
32
 
27
33
  type SignedUrlPayloadType = {
@@ -35,9 +41,9 @@ type SignedUrlPayloadType = {
35
41
  }[];
36
42
  };
37
43
 
38
- export async function getInstalledApps(): Promise<AppDetailsPacket[]> {
44
+ export async function getInstalledApps(): Promise<AppDetails[]> {
39
45
  const apps = await AgentConfigFile().getApps();
40
- const appDetails: AppDetailsPacket[] = [];
46
+ const appDetails: AppDetails[] = [];
41
47
  for (const app of apps) {
42
48
  const { projectId, version } = app;
43
49
  appDetails.push({ projectId, version });
@@ -60,6 +66,19 @@ export async function installApp(props: {
60
66
  throw new Error('Application already has installation in progress!');
61
67
  }
62
68
  logger.info('Application is already installed, updating');
69
+
70
+ // make sure the app is stopped if it's running, to clear the docker container.
71
+ if (await isAppStarted({ projectId })) {
72
+ logger.info('Application currently running. Stopping...');
73
+ try {
74
+ await stopApp({ projectId });
75
+ } catch (error) {
76
+ logger.error(
77
+ 'Could not stop the application. Old container might still be present after installation.'
78
+ );
79
+ }
80
+ }
81
+
63
82
  await AgentConfigFile().setAppInstalling({
64
83
  projectId,
65
84
  version: appReleaseHash
@@ -91,6 +110,9 @@ export async function installApp(props: {
91
110
  // NOTE: this process no longer checks project collaboration
92
111
  await checkValidProjectFiles({ appDir });
93
112
 
113
+ const DACfg = await createAppCfgDeviceAgentConnection();
114
+ await updateAppCfgFile({ projectId, newAppCfg: DACfg });
115
+
94
116
  await installAppBuildReqs({ appDir });
95
117
  await installModelsWithPresignedURLs(
96
118
  signedUrlsPayload.modelsInstallPayload,
@@ -109,6 +131,16 @@ export async function installApp(props: {
109
131
  logger.info(`Completed installing ${projectId}:${appReleaseHash}`);
110
132
  }
111
133
 
134
+ async function createAppCfgDeviceAgentConnection() {
135
+ return {
136
+ device_agent_connection: {
137
+ host: `${LOCAL_CONNECTION_HOST}`,
138
+ port: LOCAL_CONNECTION_PORT,
139
+ routing_key: `${LOCAL_CONNECTION_ROUTING_KEY}`
140
+ }
141
+ };
142
+ }
143
+
112
144
  async function installAppBuildReqs(props: { appDir: string }) {
113
145
  const { appDir } = props;
114
146
  const targetJsonFile = TargetJsonFile(appDir);
@@ -4,23 +4,24 @@ import { JsSpawner } from 'alwaysai/lib/util';
4
4
  import { runDockerLogin } from '../docker/docker-cmd';
5
5
  import { getAppDir, requireAppInstalled, requireAppReady } from './utils';
6
6
  import {
7
- ServiceStatusPacket,
8
- AppStatePacket,
9
7
  keyMirrors,
10
- AppStateValue
8
+ AppStateValue,
9
+ AppDetails,
10
+ AppState,
11
+ ServiceStatus
11
12
  } from '@alwaysai/device-agent-schemas';
12
13
  import { AgentConfigFile } from '../infrastructure/agent-config';
13
14
  import { logger } from '../util/logger';
14
15
 
15
- export async function getAppStatus(props: {
16
+ export async function getAppState(props: {
16
17
  projectId: string;
17
- }): Promise<AppStatePacket> {
18
+ }): Promise<AppState> {
18
19
  const { projectId } = props;
19
20
  if (!(await AgentConfigFile().isAppPresent({ projectId }))) {
20
21
  throw new Error('Application is not installed');
21
22
  }
22
23
 
23
- const appDetails = {
24
+ const appDetails: AppDetails = {
24
25
  projectId,
25
26
  version: await AgentConfigFile().getAppVersion({ projectId })
26
27
  };
@@ -43,7 +44,7 @@ export async function getAppStatus(props: {
43
44
  );
44
45
  }
45
46
 
46
- const services: ServiceStatusPacket[] = [];
47
+ const services: ServiceStatus[] = [];
47
48
  const spawner = JsSpawner({ path: appDir });
48
49
  for (const name of composeServices.data.services) {
49
50
  // Get container name for service
@@ -101,7 +102,7 @@ export async function isAppStarted(props: {
101
102
  projectId: string;
102
103
  }): Promise<boolean> {
103
104
  const { projectId } = props;
104
- const appStatus = await getAppStatus({ projectId });
105
+ const appStatus = await getAppState({ projectId });
105
106
  if (appStatus.services.length === 0) {
106
107
  // Services list will be empty if app has not yet been started.
107
108
  // NOTE: This depends on internal handling in getAppStatus()