@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.
- package/LICENSE +12 -0
- package/lib/application-control/config.d.ts.map +1 -1
- package/lib/application-control/config.js +6 -1
- package/lib/application-control/config.js.map +1 -1
- package/lib/application-control/index.d.ts +2 -2
- package/lib/application-control/index.d.ts.map +1 -1
- package/lib/application-control/index.js +2 -2
- package/lib/application-control/index.js.map +1 -1
- package/lib/application-control/install.d.ts +2 -2
- package/lib/application-control/install.d.ts.map +1 -1
- package/lib/application-control/install.js +23 -0
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/status.d.ts +3 -3
- package/lib/application-control/status.d.ts.map +1 -1
- package/lib/application-control/status.js +4 -4
- package/lib/application-control/status.js.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +7 -7
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +158 -100
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.d.ts +9 -9
- package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
- package/lib/cloud-connection/live-updates-handler.js +45 -42
- package/lib/cloud-connection/live-updates-handler.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.test.js +6 -5
- package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
- package/lib/cloud-connection/message-builder.d.ts +7 -0
- package/lib/cloud-connection/message-builder.d.ts.map +1 -0
- package/lib/cloud-connection/message-builder.js +63 -0
- package/lib/cloud-connection/message-builder.js.map +1 -0
- package/lib/cloud-connection/messages.d.ts +5 -15
- package/lib/cloud-connection/messages.d.ts.map +1 -1
- package/lib/cloud-connection/messages.js +22 -31
- package/lib/cloud-connection/messages.js.map +1 -1
- package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
- package/lib/cloud-connection/passthrough-handler.js +4 -2
- package/lib/cloud-connection/passthrough-handler.js.map +1 -1
- package/lib/cloud-connection/publisher.d.ts +4 -5
- package/lib/cloud-connection/publisher.d.ts.map +1 -1
- package/lib/cloud-connection/publisher.js +12 -21
- package/lib/cloud-connection/publisher.js.map +1 -1
- package/lib/cloud-connection/transaction-queue.d.ts +12 -0
- package/lib/cloud-connection/transaction-queue.d.ts.map +1 -0
- package/lib/cloud-connection/transaction-queue.js +38 -0
- package/lib/cloud-connection/transaction-queue.js.map +1 -0
- package/lib/cloud-connection/transaction-queue.test.d.ts +2 -0
- package/lib/cloud-connection/transaction-queue.test.d.ts.map +1 -0
- package/lib/cloud-connection/transaction-queue.test.js +46 -0
- package/lib/cloud-connection/transaction-queue.test.js.map +1 -0
- package/lib/environment.d.ts +3 -0
- package/lib/environment.d.ts.map +1 -1
- package/lib/environment.js +4 -1
- package/lib/environment.js.map +1 -1
- package/lib/index.js +0 -0
- package/lib/local-connection/constants.d.ts +4 -0
- package/lib/local-connection/constants.d.ts.map +1 -0
- package/lib/local-connection/constants.js +14 -0
- package/lib/local-connection/constants.js.map +1 -0
- package/lib/local-connection/rabbitmq-connection.d.ts +1 -1
- package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
- package/lib/local-connection/rabbitmq-connection.js +17 -2
- package/lib/local-connection/rabbitmq-connection.js.map +1 -1
- package/lib/secure-tunneling/index.js +1 -4
- package/lib/secure-tunneling/index.js.map +1 -1
- package/lib/subcommands/app/index.d.ts.map +1 -1
- package/lib/subcommands/app/index.js +1 -0
- package/lib/subcommands/app/index.js.map +1 -1
- package/lib/subcommands/app/models.d.ts +5 -0
- package/lib/subcommands/app/models.d.ts.map +1 -1
- package/lib/subcommands/app/models.js +42 -1
- package/lib/subcommands/app/models.js.map +1 -1
- package/lib/subcommands/app/status.js +1 -1
- package/lib/subcommands/app/status.js.map +1 -1
- package/lib/subcommands/app/version.d.ts.map +1 -1
- package/lib/subcommands/app/version.js +9 -11
- package/lib/subcommands/app/version.js.map +1 -1
- package/lib/subcommands/device/clean.d.ts.map +1 -1
- package/lib/subcommands/device/clean.js +13 -0
- package/lib/subcommands/device/clean.js.map +1 -1
- package/lib/subcommands/index.d.ts +2 -2
- package/lib/subcommands/index.d.ts.map +1 -1
- package/lib/urls.d.ts +1 -1
- package/lib/urls.d.ts.map +1 -1
- package/lib/urls.js +2 -1
- package/lib/urls.js.map +1 -1
- package/package.json +5 -4
- package/readme.md +30 -1
- package/src/application-control/config.ts +5 -1
- package/src/application-control/index.ts +2 -2
- package/src/application-control/install.ts +36 -4
- package/src/application-control/status.ts +9 -8
- package/src/cloud-connection/device-agent-cloud-connection.ts +225 -132
- package/src/cloud-connection/live-updates-handler.test.ts +6 -5
- package/src/cloud-connection/live-updates-handler.ts +90 -64
- package/src/cloud-connection/message-builder.ts +117 -0
- package/src/cloud-connection/messages.ts +27 -35
- package/src/cloud-connection/passthrough-handler.ts +12 -2
- package/src/cloud-connection/publisher.ts +17 -30
- package/src/cloud-connection/transaction-queue.test.ts +55 -0
- package/src/cloud-connection/transaction-queue.ts +40 -0
- package/src/environment.ts +7 -0
- package/src/local-connection/constants.ts +16 -0
- package/src/local-connection/rabbitmq-connection.ts +22 -2
- package/src/secure-tunneling/index.ts +1 -4
- package/src/subcommands/app/index.ts +3 -1
- package/src/subcommands/app/models.ts +44 -0
- package/src/subcommands/app/status.ts +2 -2
- package/src/subcommands/app/version.ts +16 -14
- package/src/subcommands/device/clean.ts +21 -1
- package/src/urls.ts +3 -1
- package/lib/docker/secure-tunnel-docker.d.ts +0 -2
- package/lib/docker/secure-tunnel-docker.d.ts.map +0 -1
- package/lib/docker/secure-tunnel-docker.js +0 -49
- 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.
|
|
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
|
|
40
|
+
"@alwaysai/device-agent-schemas": "2.1.2",
|
|
41
41
|
"ajv": "8.11.0",
|
|
42
|
-
"alwaysai": "2.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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<
|
|
44
|
+
export async function getInstalledApps(): Promise<AppDetails[]> {
|
|
39
45
|
const apps = await AgentConfigFile().getApps();
|
|
40
|
-
const appDetails:
|
|
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
|
|
16
|
+
export async function getAppState(props: {
|
|
16
17
|
projectId: string;
|
|
17
|
-
}): Promise<
|
|
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:
|
|
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
|
|
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()
|