@alwaysai/device-agent 1.4.0 → 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.
- package/lib/application-control/config.js +2 -2
- package/lib/application-control/config.js.map +1 -1
- package/lib/application-control/install.d.ts.map +1 -1
- package/lib/application-control/install.js +1 -0
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/models.d.ts +5 -0
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +24 -12
- package/lib/application-control/models.js.map +1 -1
- package/lib/application-control/status.d.ts.map +1 -1
- package/lib/application-control/status.js +10 -12
- package/lib/application-control/status.js.map +1 -1
- package/lib/application-control/utils.js +2 -2
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +2 -2
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +35 -15
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.d.ts +3 -2
- package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
- package/lib/cloud-connection/live-updates-handler.js +24 -21
- package/lib/cloud-connection/live-updates-handler.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.test.js +132 -16
- package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
- package/lib/cloud-connection/passthrough-handler.d.ts +5 -3
- package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
- package/lib/cloud-connection/passthrough-handler.js +76 -62
- package/lib/cloud-connection/passthrough-handler.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.d.ts +2 -0
- package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
- package/lib/cloud-connection/shadow-handler.js +5 -5
- package/lib/cloud-connection/shadow-handler.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.d.ts +3 -0
- package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
- package/lib/cloud-connection/transaction-manager.js +11 -0
- package/lib/cloud-connection/transaction-manager.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.test.js +102 -0
- package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
- package/lib/device-control/device-control.d.ts +10 -2
- package/lib/device-control/device-control.d.ts.map +1 -1
- package/lib/device-control/device-control.js +86 -10
- package/lib/device-control/device-control.js.map +1 -1
- package/lib/docker/docker-compose.d.ts +14 -0
- package/lib/docker/docker-compose.d.ts.map +1 -0
- package/lib/docker/docker-compose.js +56 -0
- package/lib/docker/docker-compose.js.map +1 -0
- package/lib/index.js +2 -5
- package/lib/index.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts +45 -14
- package/lib/infrastructure/agent-config.d.ts.map +1 -1
- package/lib/infrastructure/agent-config.js +30 -15
- package/lib/infrastructure/agent-config.js.map +1 -1
- package/lib/infrastructure/agent-config.test.js +3 -0
- package/lib/infrastructure/agent-config.test.js.map +1 -1
- package/lib/local-connection/rabbitmq-connection.js +11 -11
- package/lib/local-connection/rabbitmq-connection.js.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.d.ts +14 -22
- package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.js +34 -34
- package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.test.js +18 -18
- package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
- package/lib/subcommands/device/clean.js +5 -5
- package/lib/subcommands/device/clean.js.map +1 -1
- package/lib/subcommands/device/get-info.d.ts +2 -0
- package/lib/subcommands/device/get-info.d.ts.map +1 -0
- package/lib/subcommands/device/get-info.js +36 -0
- package/lib/subcommands/device/get-info.js.map +1 -0
- package/lib/subcommands/device/index.d.ts.map +1 -1
- package/lib/subcommands/device/index.js +11 -2
- package/lib/subcommands/device/index.js.map +1 -1
- package/lib/subcommands/device/init.d.ts +5 -0
- package/lib/subcommands/device/init.d.ts.map +1 -0
- package/lib/subcommands/device/{device.js → init.js} +2 -41
- package/lib/subcommands/device/init.js.map +1 -0
- package/lib/subcommands/device/refresh.d.ts +2 -0
- package/lib/subcommands/device/refresh.d.ts.map +1 -0
- package/lib/subcommands/device/refresh.js +24 -0
- package/lib/subcommands/device/refresh.js.map +1 -0
- package/lib/subcommands/device/restart.d.ts +2 -0
- package/lib/subcommands/device/restart.d.ts.map +1 -0
- package/lib/subcommands/device/restart.js +14 -0
- package/lib/subcommands/device/restart.js.map +1 -0
- package/lib/util/check-for-updates.d.ts +3 -0
- package/lib/util/check-for-updates.d.ts.map +1 -0
- package/lib/util/check-for-updates.js +69 -0
- package/lib/util/check-for-updates.js.map +1 -0
- package/lib/util/file.d.ts +7 -0
- package/lib/util/file.d.ts.map +1 -0
- package/lib/util/file.js +66 -0
- package/lib/util/file.js.map +1 -0
- package/lib/util/file.test.d.ts +2 -0
- package/lib/util/file.test.d.ts.map +1 -0
- package/lib/util/file.test.js +87 -0
- package/lib/util/file.test.js.map +1 -0
- package/package.json +8 -7
- package/readme.md +3 -3
- package/src/application-control/config.ts +1 -1
- package/src/application-control/install.ts +1 -0
- package/src/application-control/models.ts +36 -13
- package/src/application-control/status.ts +9 -7
- package/src/application-control/utils.ts +1 -1
- package/src/cloud-connection/device-agent-cloud-connection.ts +54 -30
- package/src/cloud-connection/live-updates-handler.test.ts +161 -20
- package/src/cloud-connection/live-updates-handler.ts +30 -26
- package/src/cloud-connection/passthrough-handler.ts +98 -76
- package/src/cloud-connection/shadow-handler.ts +19 -7
- package/src/cloud-connection/transaction-manager.test.ts +124 -0
- package/src/cloud-connection/transaction-manager.ts +15 -0
- package/src/device-control/device-control.ts +86 -11
- package/src/docker/docker-compose.ts +60 -0
- package/src/index.ts +2 -6
- package/src/infrastructure/agent-config.test.ts +3 -0
- package/src/infrastructure/agent-config.ts +38 -40
- package/src/local-connection/rabbitmq-connection.ts +8 -8
- package/src/secure-tunneling/secure-tunneling.test.ts +26 -26
- package/src/secure-tunneling/secure-tunneling.ts +48 -55
- package/src/subcommands/device/clean.ts +1 -1
- package/src/subcommands/device/get-info.ts +49 -0
- package/src/subcommands/device/index.ts +11 -2
- package/src/subcommands/device/{device.ts → init.ts} +0 -58
- package/src/subcommands/device/refresh.ts +22 -0
- package/src/subcommands/device/restart.ts +11 -0
- package/src/util/check-for-updates.ts +69 -0
- package/src/util/file.test.ts +90 -0
- package/src/util/file.ts +76 -0
- package/lib/docker/docker-compose-cmd.d.ts +0 -5
- package/lib/docker/docker-compose-cmd.d.ts.map +0 -1
- package/lib/docker/docker-compose-cmd.js +0 -16
- package/lib/docker/docker-compose-cmd.js.map +0 -1
- package/lib/subcommands/device/device.d.ts +0 -7
- package/lib/subcommands/device/device.d.ts.map +0 -1
- package/lib/subcommands/device/device.js.map +0 -1
- package/lib/util/safe-rimraf.d.ts +0 -2
- package/lib/util/safe-rimraf.d.ts.map +0 -1
- package/lib/util/safe-rimraf.js +0 -16
- package/lib/util/safe-rimraf.js.map +0 -1
- package/src/docker/docker-compose-cmd.ts +0 -15
- package/src/util/safe-rimraf.ts +0 -14
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../src/subcommands/device/restart.ts"],"names":[],"mappings":";;;AAAA,mDAA8C;AAC9C,wEAA6D;AAEhD,QAAA,cAAc,GAAG,IAAA,mBAAO,EAAC;IACpC,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,oBAAoB;IACjC,WAAW,EAAE,EAAE;IACf,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI;QAClB,MAAM,IAAA,uBAAM,GAAE,CAAC;IACjB,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-for-updates.d.ts","sourceRoot":"","sources":["../../src/util/check-for-updates.ts"],"names":[],"mappings":"AAgCA,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,CAY7D;AAQD,wBAAsB,wBAAwB,kBAgB7C"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkForUpdatesAndPrompt = exports.getDeviceAgentVersion = void 0;
|
|
4
|
+
const logger_1 = require("../util/logger");
|
|
5
|
+
const util_1 = require("alwaysai/lib/util");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const https_1 = require("https");
|
|
8
|
+
const appPrompt = 'Please restart the Device Agent or reboot the device to update. ';
|
|
9
|
+
const updatePrompt = `A new version of the Device Agent is available! \n\n`;
|
|
10
|
+
function getLatestVersion(packageName) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const url = `https://registry.npmjs.org/${packageName}/latest`;
|
|
13
|
+
(0, https_1.get)(url, (res) => {
|
|
14
|
+
let data = '';
|
|
15
|
+
res.on('data', (chunk) => {
|
|
16
|
+
data += chunk;
|
|
17
|
+
});
|
|
18
|
+
res.on('end', () => {
|
|
19
|
+
try {
|
|
20
|
+
const latestPackage = JSON.parse(data);
|
|
21
|
+
resolve(latestPackage.version);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
reject(error);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}).on('error', (error) => {
|
|
28
|
+
reject(error);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function getDeviceAgentVersion() {
|
|
33
|
+
let daVersion = '';
|
|
34
|
+
try {
|
|
35
|
+
const packagePath = path.join(__dirname, '../../');
|
|
36
|
+
const spawner = (0, util_1.JsSpawner)({ path: packagePath });
|
|
37
|
+
const output = await spawner.readFile('package.json');
|
|
38
|
+
const parsed = JSON.parse(output);
|
|
39
|
+
daVersion = parsed.version;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
logger_1.logger.error(`Could not retrieve the Device Agent version: $ {e}`);
|
|
43
|
+
}
|
|
44
|
+
return daVersion;
|
|
45
|
+
}
|
|
46
|
+
exports.getDeviceAgentVersion = getDeviceAgentVersion;
|
|
47
|
+
function constructPrompt(props) {
|
|
48
|
+
const { currentVer, latestVer } = props;
|
|
49
|
+
const prompt = `${updatePrompt}${appPrompt}\nYour version: ${currentVer}. Newest version: ${latestVer}`;
|
|
50
|
+
return prompt;
|
|
51
|
+
}
|
|
52
|
+
async function checkForUpdatesAndPrompt() {
|
|
53
|
+
try {
|
|
54
|
+
logger_1.logger.debug('Checking for updates...');
|
|
55
|
+
const latestVersion = await getLatestVersion('@alwaysai/device-agent');
|
|
56
|
+
const version = await getDeviceAgentVersion();
|
|
57
|
+
if (version !== latestVersion) {
|
|
58
|
+
logger_1.logger.warn(constructPrompt({
|
|
59
|
+
currentVer: version,
|
|
60
|
+
latestVer: latestVersion
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
logger_1.logger.error(`Could not check for updates: ${error}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.checkForUpdatesAndPrompt = checkForUpdatesAndPrompt;
|
|
69
|
+
//# sourceMappingURL=check-for-updates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-for-updates.js","sourceRoot":"","sources":["../../src/util/check-for-updates.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AACxC,4CAA8C;AAC9C,6BAA6B;AAC7B,iCAA4B;AAE5B,MAAM,SAAS,GACb,kEAAkE,CAAC;AACrE,MAAM,YAAY,GAAG,sDAAsD,CAAC;AAE5E,SAAS,gBAAgB,CAAC,WAAmB;IAC3C,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,GAAG,GAAG,8BAA8B,WAAW,SAAS,CAAC;QAE/D,IAAA,WAAG,EAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACf,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBACvB,IAAI,IAAI,KAAK,CAAC;YAChB,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI;oBACF,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACvC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;iBAChC;gBAAC,OAAO,KAAK,EAAE;oBACd,MAAM,CAAC,KAAK,CAAC,CAAC;iBACf;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACvB,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,qBAAqB;IACzC,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI;QACF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,IAAA,gBAAS,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC;KAC5B;IAAC,OAAO,CAAC,EAAE;QACV,eAAM,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;KACpE;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAZD,sDAYC;AAED,SAAS,eAAe,CAAC,KAAgD;IACvE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACxC,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG,SAAS,mBAAmB,UAAU,qBAAqB,SAAS,EAAE,CAAC;IACxG,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,KAAK,UAAU,wBAAwB;IAC5C,IAAI;QACF,eAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACxC,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,MAAM,qBAAqB,EAAE,CAAC;QAC9C,IAAI,OAAO,KAAK,aAAa,EAAE;YAC7B,eAAM,CAAC,IAAI,CACT,eAAe,CAAC;gBACd,UAAU,EAAE,OAAO;gBACnB,SAAS,EAAE,aAAa;aACzB,CAAC,CACH,CAAC;SACH;KACF;IAAC,OAAO,KAAK,EAAE;QACd,eAAM,CAAC,KAAK,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAC;KACvD;AACH,CAAC;AAhBD,4DAgBC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/util/file.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,iBAU5C;AAED,wBAAsB,QAAQ,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,OAAO,EACR,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,oBAkDA"}
|
package/lib/util/file.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pruneDir = exports.safeRimraf = void 0;
|
|
4
|
+
const rimraf_1 = require("rimraf");
|
|
5
|
+
const logger_1 = require("../util/logger");
|
|
6
|
+
const promises_1 = require("fs/promises");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
async function safeRimraf(path) {
|
|
9
|
+
logger_1.logger.debug(`Removing ${path}`);
|
|
10
|
+
try {
|
|
11
|
+
await (0, rimraf_1.rimraf)(path);
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
logger_1.logger.error(`Failed to remove ${path}. Please manually delete the file or directory.`);
|
|
15
|
+
logger_1.logger.debug(`Error removing ${path}: ${e}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.safeRimraf = safeRimraf;
|
|
19
|
+
async function pruneDir({ path, exclude, recurse }) {
|
|
20
|
+
/**
|
|
21
|
+
* Deletes all files and directories in a given directory path, excluding specific paths.
|
|
22
|
+
* Will not delete top-level directory
|
|
23
|
+
* @param {string} path path of directory to prune.
|
|
24
|
+
* @param {string[]} exclude list of paths to exclude when pruning
|
|
25
|
+
* @param {boolean} recurse flag to prune recursively into directories
|
|
26
|
+
*/
|
|
27
|
+
try {
|
|
28
|
+
const files = await (0, promises_1.readdir)(path);
|
|
29
|
+
let canPruneParent = true;
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
const filePath = (0, path_1.join)(path, file);
|
|
32
|
+
const isExcluded = exclude === null || exclude === void 0 ? void 0 : exclude.some((excludePath) => filePath.endsWith(excludePath));
|
|
33
|
+
if (isExcluded) {
|
|
34
|
+
logger_1.logger.debug(`Excluding file ${filePath} during pruning.`);
|
|
35
|
+
canPruneParent = false;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const fileStats = await (0, promises_1.stat)(filePath);
|
|
39
|
+
if (fileStats.isDirectory()) {
|
|
40
|
+
if (recurse) {
|
|
41
|
+
const dirIsEmpty = await pruneDir({
|
|
42
|
+
path: filePath,
|
|
43
|
+
exclude,
|
|
44
|
+
recurse
|
|
45
|
+
});
|
|
46
|
+
if (dirIsEmpty) {
|
|
47
|
+
await (0, promises_1.rmdir)(filePath);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
canPruneParent = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
await (0, promises_1.unlink)(filePath);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return canPruneParent;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger_1.logger.error(`Error pruning directory ${path}: ${JSON.stringify(error)}`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.pruneDir = pruneDir;
|
|
66
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/util/file.ts"],"names":[],"mappings":";;;AAAA,mCAAgC;AAChC,2CAAwC;AACxC,0CAA2D;AAC3D,+BAA4B;AAErB,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,eAAM,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IACjC,IAAI;QACF,MAAM,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC;KACpB;IAAC,OAAO,CAAC,EAAE;QACV,eAAM,CAAC,KAAK,CACV,oBAAoB,IAAI,iDAAiD,CAC1E,CAAC;QACF,eAAM,CAAC,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC;KAC9C;AACH,CAAC;AAVD,gCAUC;AAEM,KAAK,UAAU,QAAQ,CAAC,EAC7B,IAAI,EACJ,OAAO,EACP,OAAO,EAKR;IACC;;;;;;OAMG;IACH,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;QAElC,IAAI,cAAc,GAAG,IAAI,CAAC;QAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAElC,MAAM,UAAU,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAC/C,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC/B,CAAC;YAEF,IAAI,UAAU,EAAE;gBACd,eAAM,CAAC,KAAK,CAAC,kBAAkB,QAAQ,kBAAkB,CAAC,CAAC;gBAC3D,cAAc,GAAG,KAAK,CAAC;gBACvB,SAAS;aACV;YAED,MAAM,SAAS,GAAG,MAAM,IAAA,eAAI,EAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE;gBAC3B,IAAI,OAAO,EAAE;oBACX,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC;wBAChC,IAAI,EAAE,QAAQ;wBACd,OAAO;wBACP,OAAO;qBACR,CAAC,CAAC;oBAEH,IAAI,UAAU,EAAE;wBACd,MAAM,IAAA,gBAAK,EAAC,QAAQ,CAAC,CAAC;qBACvB;yBAAM;wBACL,cAAc,GAAG,KAAK,CAAC;qBACxB;iBACF;aACF;iBAAM;gBACL,MAAM,IAAA,iBAAM,EAAC,QAAQ,CAAC,CAAC;aACxB;SACF;QACD,OAAO,cAAc,CAAC;KACvB;IAAC,OAAO,KAAK,EAAE;QACd,eAAM,CAAC,KAAK,CAAC,2BAA2B,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1E,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AA1DD,4BA0DC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.test.d.ts","sourceRoot":"","sources":["../../src/util/file.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const file_1 = require("../../src/util/file");
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
jest.mock('fs/promises');
|
|
6
|
+
describe('pruneDir function', () => {
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
jest.clearAllMocks();
|
|
9
|
+
});
|
|
10
|
+
it('should return true if directory is successfully pruned', async () => {
|
|
11
|
+
const path = '/path/to/directory';
|
|
12
|
+
const files = ['file1.txt', 'file2.txt'];
|
|
13
|
+
promises_1.readdir.mockResolvedValue(files);
|
|
14
|
+
promises_1.stat.mockResolvedValue({ isDirectory: () => false });
|
|
15
|
+
const result = await (0, file_1.pruneDir)({ path });
|
|
16
|
+
expect(result).toBe(true);
|
|
17
|
+
expect(promises_1.readdir).toHaveBeenCalledWith(path);
|
|
18
|
+
expect(promises_1.stat).toHaveBeenCalledTimes(2); // Called for each file
|
|
19
|
+
expect(promises_1.unlink).toHaveBeenCalledTimes(2); // Called for each file
|
|
20
|
+
});
|
|
21
|
+
it('should exclude specified files from pruning', async () => {
|
|
22
|
+
const path = '/path/to/directory';
|
|
23
|
+
const files = ['file1.txt', 'file2.txt'];
|
|
24
|
+
const exclude = ['file1.txt']; // Exclude file1.txt
|
|
25
|
+
promises_1.readdir.mockResolvedValue(files);
|
|
26
|
+
promises_1.stat.mockResolvedValue({ isDirectory: () => false });
|
|
27
|
+
const result = await (0, file_1.pruneDir)({ path, exclude });
|
|
28
|
+
expect(result).toBe(false);
|
|
29
|
+
expect(promises_1.readdir).toHaveBeenCalledWith(path);
|
|
30
|
+
expect(promises_1.stat).toHaveBeenCalledTimes(1); // Called only for file2.txt
|
|
31
|
+
expect(promises_1.unlink).toHaveBeenCalledTimes(1); // Called only for file2.txt
|
|
32
|
+
});
|
|
33
|
+
it('should recursively prune directories if recurse option is true', async () => {
|
|
34
|
+
const rootPath = '/path/to/directory';
|
|
35
|
+
const subDirPath = '/path/to/directory/subdir';
|
|
36
|
+
const files = ['file1.txt', 'subdir'];
|
|
37
|
+
const subDirFiles = ['file2.txt'];
|
|
38
|
+
promises_1.readdir.mockImplementation((path) => {
|
|
39
|
+
if (path === rootPath)
|
|
40
|
+
return files;
|
|
41
|
+
if (path === subDirPath)
|
|
42
|
+
return subDirFiles;
|
|
43
|
+
});
|
|
44
|
+
promises_1.stat.mockImplementation((path) => {
|
|
45
|
+
if (path === `${rootPath}/file1.txt`)
|
|
46
|
+
return { isDirectory: () => false };
|
|
47
|
+
if (path === subDirPath)
|
|
48
|
+
return { isDirectory: () => true };
|
|
49
|
+
if (path === `${subDirPath}/file2.txt`)
|
|
50
|
+
return { isDirectory: () => false };
|
|
51
|
+
});
|
|
52
|
+
const result = await (0, file_1.pruneDir)({ path: rootPath, recurse: true });
|
|
53
|
+
expect(result).toBe(true);
|
|
54
|
+
expect(promises_1.readdir).toHaveBeenCalledWith(rootPath);
|
|
55
|
+
expect(promises_1.readdir).toHaveBeenCalledWith(subDirPath);
|
|
56
|
+
expect(promises_1.stat).toHaveBeenCalledTimes(3); // Called for file1.txt, subdir, and file2.txt
|
|
57
|
+
expect(promises_1.unlink).toHaveBeenCalledWith(`${rootPath}/file1.txt`);
|
|
58
|
+
expect(promises_1.unlink).toHaveBeenCalledWith(`${subDirPath}/file2.txt`);
|
|
59
|
+
expect(promises_1.rmdir).toHaveBeenCalledWith(subDirPath);
|
|
60
|
+
});
|
|
61
|
+
it('should not recurse into directories if recurse option is false', async () => {
|
|
62
|
+
const rootPath = '/path/to/directory';
|
|
63
|
+
const subDirPath = '/path/to/directory/subdir';
|
|
64
|
+
const files = ['file1.txt', 'subdir'];
|
|
65
|
+
const subDirFiles = ['file2.txt'];
|
|
66
|
+
promises_1.readdir.mockImplementation((path) => {
|
|
67
|
+
if (path === rootPath)
|
|
68
|
+
return files;
|
|
69
|
+
if (path === subDirPath)
|
|
70
|
+
return subDirFiles;
|
|
71
|
+
});
|
|
72
|
+
promises_1.stat.mockImplementation((path) => {
|
|
73
|
+
if (path === `${rootPath}/file1.txt`)
|
|
74
|
+
return { isDirectory: () => false };
|
|
75
|
+
if (path === subDirPath)
|
|
76
|
+
return { isDirectory: () => true };
|
|
77
|
+
});
|
|
78
|
+
const result = await (0, file_1.pruneDir)({ path: rootPath, recurse: false });
|
|
79
|
+
expect(result).toBe(true);
|
|
80
|
+
expect(promises_1.readdir).toHaveBeenCalledWith(rootPath);
|
|
81
|
+
expect(promises_1.stat).toHaveBeenCalledTimes(2); // Called for file1.txt and subdir
|
|
82
|
+
expect(promises_1.unlink).toHaveBeenCalledWith(`${rootPath}/file1.txt`);
|
|
83
|
+
expect(promises_1.unlink).not.toHaveBeenCalledWith(`${subDirPath}/file2.txt`);
|
|
84
|
+
expect(promises_1.rmdir).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=file.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.test.js","sourceRoot":"","sources":["../../src/util/file.test.ts"],"names":[],"mappings":"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"}
|
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": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"publishConfig": {
|
|
@@ -37,26 +37,27 @@
|
|
|
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": "2.3.
|
|
40
|
+
"@alwaysai/device-agent-schemas": "2.3.3",
|
|
41
41
|
"@carnesen/coded-error": "0.4.0",
|
|
42
42
|
"ajv": "8.11.0",
|
|
43
|
-
"alwaysai": "2.
|
|
43
|
+
"alwaysai": "2.5.3",
|
|
44
44
|
"amqplib": "0.10.3",
|
|
45
45
|
"aws-iot-device-sdk": "2.2.12",
|
|
46
|
-
"docker-compose": "0.
|
|
46
|
+
"docker-compose": "0.24.3",
|
|
47
47
|
"lodash": "4.17.21",
|
|
48
48
|
"node-fetch": "2.6.1",
|
|
49
49
|
"node-os-utils": "1.3.7",
|
|
50
50
|
"rimraf": "4.4.0",
|
|
51
51
|
"systeminformation": "5.21.13",
|
|
52
52
|
"uuid": "9.0.0",
|
|
53
|
-
"winston": "3.
|
|
54
|
-
"winston-daily-rotate-file": "
|
|
53
|
+
"winston": "3.13.0",
|
|
54
|
+
"winston-daily-rotate-file": "5.0.0",
|
|
55
55
|
"yaml": "2.2.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@alwaysai/tsconfig": "0.0.1",
|
|
59
58
|
"@alwaysai/eslint-config": "0.1.0",
|
|
59
|
+
"@alwaysai/tsconfig": "0.0.1",
|
|
60
|
+
"@types/amqplib": "0.10.5",
|
|
60
61
|
"@types/destroy": "1.0.0",
|
|
61
62
|
"@types/jest": "28.1.2",
|
|
62
63
|
"@types/node": "16.11.12",
|
package/readme.md
CHANGED
|
@@ -42,13 +42,13 @@ change.
|
|
|
42
42
|
|
|
43
43
|
* Supported OS:
|
|
44
44
|
* Debian Bookworm, Bullseye
|
|
45
|
-
* Ubuntu 23.10, 22.04, 20.04
|
|
46
|
-
* NVIDIA
|
|
45
|
+
* Ubuntu 24.04, 23.10, 22.04, 20.04
|
|
46
|
+
* NVIDIA JetPack 5.1.1, 5.1
|
|
47
47
|
* Supported target architecture
|
|
48
48
|
* amd64
|
|
49
49
|
* aarch64
|
|
50
50
|
* `docker` >= 19.03
|
|
51
|
-
* `docker-compose` >= 1.29.0
|
|
51
|
+
* `docker-compose` >= 1.29.0
|
|
52
52
|
* `curl` installed (required to download provisioning scripts)
|
|
53
53
|
* Passwordless `sudo` for `npm` if using `pm2`
|
|
54
54
|
* Passwordless `sudo` for `/sbin/shutdown` for device restart functionality
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
requireAppReady
|
|
8
8
|
} from './utils';
|
|
9
9
|
import { JsSpawner } from 'alwaysai/lib/util';
|
|
10
|
-
import compose from 'docker-compose';
|
|
10
|
+
import { compose } from '../docker/docker-compose';
|
|
11
11
|
import { assign, merge } from 'lodash';
|
|
12
12
|
import { AppJsonFile } from 'alwaysai/lib/core/app';
|
|
13
13
|
import { AppConfig } from '@alwaysai/app-configuration-schemas';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
1
|
import { ModelInstallPayload } from '@alwaysai/device-agent-schemas';
|
|
3
2
|
import {
|
|
4
3
|
appModelsAddComponent,
|
|
@@ -23,8 +22,9 @@ import {
|
|
|
23
22
|
} from './utils';
|
|
24
23
|
import { MODEL_JSON_FILE_NAME } from 'alwaysai/lib/core/model';
|
|
25
24
|
import { writeAppCfgFile } from './config';
|
|
26
|
-
import { AppConfig } from '@alwaysai/app-configuration-schemas';
|
|
27
25
|
import { APP_MODELS_DIRECTORY_NAME } from 'alwaysai/lib/paths';
|
|
26
|
+
import { pruneDir } from '../util/file';
|
|
27
|
+
import { AppConfig } from '@alwaysai/app-configuration-schemas';
|
|
28
28
|
|
|
29
29
|
export async function getAppModels(props: { projectId: string }) {
|
|
30
30
|
const { projectId } = props;
|
|
@@ -127,9 +127,9 @@ export async function installModelsWithPresignedURLs(
|
|
|
127
127
|
modelPayloads.map(async (payload: ModelInstallPayload) => {
|
|
128
128
|
logger.info(`Installing ${payload.id}: ${payload.version}`);
|
|
129
129
|
const version = payload.version;
|
|
130
|
-
const modelDest =
|
|
130
|
+
const modelDest = join(targetDir, payload.id);
|
|
131
131
|
await spawner.mkdirp(modelDest);
|
|
132
|
-
const localDest =
|
|
132
|
+
const localDest = join(modelDest, `${payload.version}.tar.gz`);
|
|
133
133
|
await downloadPackageUsingPresignedUrl({
|
|
134
134
|
localDest,
|
|
135
135
|
presignedUrl: payload.modelSignedUrl
|
|
@@ -178,20 +178,21 @@ export async function updateModelsWithPresignedUrls(props: {
|
|
|
178
178
|
version: appReleaseHash
|
|
179
179
|
});
|
|
180
180
|
|
|
181
|
-
const ogDir =
|
|
182
|
-
// Copy all current models to restore dir in case of failure
|
|
183
|
-
const restoreDir = `${ogDir}.restore`;
|
|
184
|
-
await spawner.rimraf(restoreDir);
|
|
185
|
-
await copyDir({ srcPath: ogDir, destPath: restoreDir });
|
|
186
|
-
|
|
187
|
-
// Create temp dir to install new models
|
|
181
|
+
const ogDir = join(appDir, APP_MODELS_DIRECTORY_NAME);
|
|
188
182
|
const tmpDir = `${ogDir}.tmp`;
|
|
189
183
|
|
|
190
184
|
try {
|
|
191
185
|
await spawner.rimraf(tmpDir);
|
|
192
186
|
await copyDir({ srcPath: ogDir, destPath: tmpDir });
|
|
187
|
+
|
|
188
|
+
await pruneModels({
|
|
189
|
+
projectId,
|
|
190
|
+
appCfg: newAppCfg,
|
|
191
|
+
path: tmpDir
|
|
192
|
+
});
|
|
193
|
+
|
|
193
194
|
await installModelsWithPresignedURLs(modelInstallPayloads, tmpDir);
|
|
194
|
-
|
|
195
|
+
|
|
195
196
|
await spawner.rimraf(ogDir);
|
|
196
197
|
await copyDir({ srcPath: tmpDir, destPath: ogDir });
|
|
197
198
|
await spawner.rimraf(tmpDir);
|
|
@@ -211,6 +212,28 @@ export async function updateModelsWithPresignedUrls(props: {
|
|
|
211
212
|
logger.info(`Models installed for project ${projectId}`);
|
|
212
213
|
} finally {
|
|
213
214
|
await spawner.rimraf(tmpDir);
|
|
214
|
-
await spawner.rimraf(restoreDir);
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
|
+
|
|
218
|
+
export async function pruneModels(props: {
|
|
219
|
+
projectId: string;
|
|
220
|
+
appCfg: AppConfig;
|
|
221
|
+
path?: string;
|
|
222
|
+
}) {
|
|
223
|
+
const { projectId, appCfg, path } = props;
|
|
224
|
+
|
|
225
|
+
const modelsPath = path || join(getAppDir(projectId), 'models');
|
|
226
|
+
|
|
227
|
+
if (!existsSync(modelsPath)) {
|
|
228
|
+
logger.error(
|
|
229
|
+
`Attempted to prune models from ${modelsPath} for project app ${projectId} that does not exist or has no models dir.`
|
|
230
|
+
);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
await pruneDir({
|
|
235
|
+
path: modelsPath,
|
|
236
|
+
exclude: Object.keys(appCfg.models),
|
|
237
|
+
recurse: true
|
|
238
|
+
});
|
|
239
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
compose,
|
|
3
|
+
runStreamingDockerComposeCmd,
|
|
4
|
+
runDockerComposeCmd
|
|
5
|
+
} from '../docker/docker-compose';
|
|
2
6
|
import { JsSpawner } from 'alwaysai/lib/util';
|
|
3
7
|
|
|
4
8
|
import { runDockerLogin } from '../docker/docker-cmd';
|
|
@@ -48,9 +52,8 @@ export async function getAppState(props: {
|
|
|
48
52
|
const spawner = JsSpawner({ path: appDir });
|
|
49
53
|
for (const name of composeServices.data.services) {
|
|
50
54
|
// Get container name for service
|
|
51
|
-
const containerId = await
|
|
52
|
-
|
|
53
|
-
cwd: appDir,
|
|
55
|
+
const containerId = await runDockerComposeCmd({
|
|
56
|
+
dir: appDir,
|
|
54
57
|
args: ['ps', '-q', name]
|
|
55
58
|
});
|
|
56
59
|
if (containerId === '') {
|
|
@@ -136,10 +139,9 @@ export async function getAppLogs(props: {
|
|
|
136
139
|
const argsList = args || [];
|
|
137
140
|
|
|
138
141
|
// Use direct command with spawner in order to get a readable stream
|
|
139
|
-
return await
|
|
140
|
-
exe: 'docker-compose',
|
|
142
|
+
return await runStreamingDockerComposeCmd({
|
|
141
143
|
args: ['logs', '-f', ...argsList, ...serviceList],
|
|
142
|
-
|
|
144
|
+
dir: appDir
|
|
143
145
|
});
|
|
144
146
|
}
|
|
145
147
|
|