@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.
- package/lib/application-control/backup.d.ts +8 -0
- package/lib/application-control/backup.d.ts.map +1 -0
- package/lib/application-control/backup.js +34 -0
- package/lib/application-control/backup.js.map +1 -0
- package/lib/application-control/environment-variables.d.ts +9 -0
- package/lib/application-control/environment-variables.d.ts.map +1 -0
- package/lib/application-control/environment-variables.js +82 -0
- package/lib/application-control/environment-variables.js.map +1 -0
- package/lib/application-control/index.d.ts +9 -0
- package/lib/application-control/index.d.ts.map +1 -0
- package/lib/application-control/index.js +27 -0
- package/lib/application-control/index.js.map +1 -0
- package/lib/application-control/install.d.ts +16 -0
- package/lib/application-control/install.d.ts.map +1 -0
- package/lib/application-control/install.js +117 -0
- package/lib/application-control/install.js.map +1 -0
- package/lib/application-control/models.d.ts +8 -0
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +44 -11
- package/lib/application-control/models.js.map +1 -1
- package/lib/application-control/status.d.ts +26 -0
- package/lib/application-control/status.d.ts.map +1 -0
- package/lib/application-control/status.js +138 -0
- package/lib/application-control/status.js.map +1 -0
- package/lib/application-control/types.d.ts +5 -0
- package/lib/application-control/types.d.ts.map +1 -0
- package/lib/{util/spawner → application-control}/types.js +0 -0
- package/lib/{util/spawner → application-control}/types.js.map +1 -1
- package/lib/application-control/utils.d.ts +2 -9
- package/lib/application-control/utils.d.ts.map +1 -1
- package/lib/application-control/utils.js +14 -29
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +16 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +239 -9
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/docker/docker-cmd.js +2 -2
- package/lib/docker/docker-cmd.js.map +1 -1
- package/lib/docker/docker-compose-cmd.js +2 -2
- package/lib/docker/docker-compose-cmd.js.map +1 -1
- package/lib/environment.d.ts +2 -0
- package/lib/environment.d.ts.map +1 -1
- package/lib/environment.js +3 -1
- package/lib/environment.js.map +1 -1
- package/lib/index.js +10 -8
- package/lib/index.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts +73 -0
- package/lib/infrastructure/agent-config.d.ts.map +1 -0
- package/lib/infrastructure/agent-config.js +186 -0
- package/lib/infrastructure/agent-config.js.map +1 -0
- package/lib/infrastructure/agent-config.test.d.ts +2 -0
- package/lib/infrastructure/agent-config.test.d.ts.map +1 -0
- package/lib/infrastructure/agent-config.test.js +135 -0
- package/lib/infrastructure/agent-config.test.js.map +1 -0
- package/lib/infrastructure/certificates-and-tokens.d.ts +6 -0
- package/lib/infrastructure/certificates-and-tokens.d.ts.map +1 -0
- package/lib/infrastructure/certificates-and-tokens.js +69 -0
- package/lib/infrastructure/certificates-and-tokens.js.map +1 -0
- package/lib/{util → infrastructure}/urls.d.ts +0 -0
- package/lib/infrastructure/urls.d.ts.map +1 -0
- package/lib/{util → infrastructure}/urls.js +3 -3
- package/lib/infrastructure/urls.js.map +1 -0
- package/lib/root.js +3 -3
- package/lib/root.js.map +1 -1
- package/lib/subcommands/app/app.d.ts +31 -14
- package/lib/subcommands/app/app.d.ts.map +1 -1
- package/lib/subcommands/app/app.js +117 -62
- package/lib/subcommands/app/app.js.map +1 -1
- package/lib/subcommands/app/index.d.ts.map +1 -1
- package/lib/subcommands/app/index.js +6 -1
- package/lib/subcommands/app/index.js.map +1 -1
- package/lib/subcommands/device/device.d.ts +6 -0
- package/lib/subcommands/device/device.d.ts.map +1 -0
- package/lib/subcommands/device/device.js +62 -0
- package/lib/subcommands/device/device.js.map +1 -0
- package/lib/subcommands/device/index.d.ts +2 -0
- package/lib/subcommands/device/index.d.ts.map +1 -0
- package/lib/subcommands/device/index.js +11 -0
- package/lib/subcommands/device/index.js.map +1 -0
- package/lib/subcommands/get-model-package.d.ts +5 -0
- package/lib/subcommands/get-model-package.d.ts.map +1 -0
- package/lib/subcommands/get-model-package.js +51 -0
- package/lib/subcommands/get-model-package.js.map +1 -0
- package/lib/subcommands/index.d.ts +8 -1
- package/lib/subcommands/index.d.ts.map +1 -1
- package/lib/subcommands/index.js +6 -6
- package/lib/subcommands/index.js.map +1 -1
- package/lib/subcommands/login.d.ts +3 -2
- package/lib/subcommands/login.d.ts.map +1 -1
- package/lib/subcommands/login.js +11 -4
- package/lib/subcommands/login.js.map +1 -1
- package/lib/util/copy-dir.js +3 -3
- package/lib/util/copy-dir.js.map +1 -1
- package/lib/util/directories.d.ts +1 -1
- package/lib/util/directories.d.ts.map +1 -1
- package/lib/util/directories.js +9 -14
- package/lib/util/directories.js.map +1 -1
- package/lib/util/get-device-id.d.ts +2 -0
- package/lib/util/get-device-id.d.ts.map +1 -0
- package/lib/util/get-device-id.js +24 -0
- package/lib/util/get-device-id.js.map +1 -0
- package/package.json +19 -14
- package/readme.md +176 -72
- package/src/application-control/backup.ts +32 -0
- package/src/application-control/environment-variables.ts +81 -0
- package/src/application-control/index.ts +40 -0
- package/src/application-control/install.ts +126 -0
- package/src/application-control/models.ts +51 -11
- package/src/application-control/status.ts +156 -0
- package/src/application-control/types.ts +1 -0
- package/src/application-control/utils.ts +12 -27
- package/src/cloud-connection/device-agent-cloud-connection.ts +280 -13
- package/src/docker/docker-cmd.ts +1 -1
- package/src/docker/docker-compose-cmd.ts +1 -1
- package/src/environment.ts +2 -0
- package/src/index.ts +10 -7
- package/src/infrastructure/agent-config.test.ts +143 -0
- package/src/infrastructure/agent-config.ts +217 -0
- package/src/infrastructure/certificates-and-tokens.ts +71 -0
- package/src/{util → infrastructure}/urls.ts +1 -1
- package/src/root.ts +3 -3
- package/src/subcommands/app/app.ts +135 -62
- package/src/subcommands/app/index.ts +11 -1
- package/src/subcommands/device/device.ts +63 -0
- package/src/subcommands/device/index.ts +8 -0
- package/src/subcommands/get-model-package.ts +60 -0
- package/src/subcommands/index.ts +5 -5
- package/src/subcommands/login.ts +11 -4
- package/src/util/copy-dir.ts +1 -1
- package/src/util/directories.ts +12 -17
- package/src/util/get-device-id.ts +22 -0
- package/lib/application-control/application-control.d.ts +0 -46
- package/lib/application-control/application-control.d.ts.map +0 -1
- package/lib/application-control/application-control.js +0 -234
- package/lib/application-control/application-control.js.map +0 -1
- package/lib/constants.d.ts +0 -17
- package/lib/constants.d.ts.map +0 -1
- package/lib/constants.js +0 -24
- package/lib/constants.js.map +0 -1
- package/lib/subcommands/device-control.d.ts +0 -2
- package/lib/subcommands/device-control.d.ts.map +0 -1
- package/lib/subcommands/device-control.js +0 -19
- package/lib/subcommands/device-control.js.map +0 -1
- package/lib/subcommands/test-app.d.ts +0 -2
- package/lib/subcommands/test-app.d.ts.map +0 -1
- package/lib/subcommands/test-app.js +0 -29
- package/lib/subcommands/test-app.js.map +0 -1
- package/lib/util/spawner/gnu-spawner.d.ts +0 -9
- package/lib/util/spawner/gnu-spawner.d.ts.map +0 -1
- package/lib/util/spawner/gnu-spawner.js +0 -102
- package/lib/util/spawner/gnu-spawner.js.map +0 -1
- package/lib/util/spawner/js-spawner.d.ts +0 -5
- package/lib/util/spawner/js-spawner.d.ts.map +0 -1
- package/lib/util/spawner/js-spawner.js +0 -89
- package/lib/util/spawner/js-spawner.js.map +0 -1
- package/lib/util/spawner/types.d.ts +0 -28
- package/lib/util/spawner/types.d.ts.map +0 -1
- package/lib/util/spawner-base/index.d.ts +0 -17
- package/lib/util/spawner-base/index.d.ts.map +0 -1
- package/lib/util/spawner-base/index.js +0 -30
- package/lib/util/spawner-base/index.js.map +0 -1
- package/lib/util/spawner-base/run-foreground-sync.d.ts +0 -3
- package/lib/util/spawner-base/run-foreground-sync.d.ts.map +0 -1
- package/lib/util/spawner-base/run-foreground-sync.js +0 -18
- package/lib/util/spawner-base/run-foreground-sync.js.map +0 -1
- package/lib/util/spawner-base/run-foreground.d.ts +0 -3
- package/lib/util/spawner-base/run-foreground.d.ts.map +0 -1
- package/lib/util/spawner-base/run-foreground.js +0 -49
- package/lib/util/spawner-base/run-foreground.js.map +0 -1
- package/lib/util/spawner-base/run-streaming.d.ts +0 -4
- package/lib/util/spawner-base/run-streaming.d.ts.map +0 -1
- package/lib/util/spawner-base/run-streaming.js +0 -35
- package/lib/util/spawner-base/run-streaming.js.map +0 -1
- package/lib/util/spawner-base/run.d.ts +0 -4
- package/lib/util/spawner-base/run.d.ts.map +0 -1
- package/lib/util/spawner-base/run.js +0 -56
- package/lib/util/spawner-base/run.js.map +0 -1
- package/lib/util/urls.d.ts.map +0 -1
- package/lib/util/urls.js.map +0 -1
- package/lib/web/index.html +0 -229
- package/lib/web/static/Karla.css +0 -18
- package/lib/web/static/bootstrap-4.3.1.min.css +0 -7
- package/lib/web/static/bootstrap-4.3.1.min.js +0 -7
- package/lib/web/static/favicon.ico +0 -0
- package/lib/web/static/jquery-3.3.1.slim.min.js +0 -2
- package/lib/web/static/popper-1.14.7.min.js +0 -5
- package/lib/web/web-interface.d.ts +0 -2
- package/lib/web/web-interface.d.ts.map +0 -1
- package/lib/web/web-interface.js +0 -74
- package/lib/web/web-interface.js.map +0 -1
- package/src/application-control/application-control.ts +0 -273
- package/src/constants.ts +0 -32
- package/src/subcommands/device-control.ts +0 -16
- package/src/subcommands/test-app.ts +0 -30
- package/src/util/spawner/gnu-spawner.ts +0 -114
- package/src/util/spawner/js-spawner.ts +0 -110
- package/src/util/spawner/types.ts +0 -28
- package/src/util/spawner-base/index.ts +0 -28
- package/src/util/spawner-base/run-foreground-sync.ts +0 -16
- package/src/util/spawner-base/run-foreground.ts +0 -49
- package/src/util/spawner-base/run-streaming.ts +0 -40
- package/src/util/spawner-base/run.ts +0 -60
- package/src/web/index.html +0 -229
- package/src/web/static/Karla.css +0 -18
- package/src/web/static/bootstrap-4.3.1.min.css +0 -7
- package/src/web/static/bootstrap-4.3.1.min.js +0 -7
- package/src/web/static/favicon.ico +0 -0
- package/src/web/static/jquery-3.3.1.slim.min.js +0 -2
- package/src/web/static/popper-1.14.7.min.js +0 -5
- 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
|
-
|
|
12
|
-
|
|
13
|
-
} from '../../
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
232
|
+
description: 'Project ID',
|
|
233
|
+
required: true,
|
|
208
234
|
}),
|
|
209
235
|
model: CliStringInput({
|
|
210
|
-
description: 'Model
|
|
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
|
|
251
|
+
description: 'Project ID',
|
|
252
|
+
required: true,
|
|
231
253
|
}),
|
|
232
254
|
model: CliStringInput({
|
|
233
|
-
description: 'Model
|
|
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,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
|
+
});
|
package/src/subcommands/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { appCliBranch } from './app
|
|
2
|
-
import {
|
|
1
|
+
import { appCliBranch } from './app';
|
|
2
|
+
import { deviceCliBranch } from './device';
|
|
3
3
|
import { loginCliLeaf } from './login';
|
|
4
|
-
|
|
4
|
+
import { getModelPackageCliLeaf } from './get-model-package';
|
|
5
5
|
|
|
6
6
|
export const subcommands = [
|
|
7
7
|
loginCliLeaf,
|
|
8
8
|
appCliBranch,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
deviceCliBranch,
|
|
10
|
+
getModelPackageCliLeaf,
|
|
11
11
|
];
|
package/src/subcommands/login.ts
CHANGED
|
@@ -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
|
});
|
package/src/util/copy-dir.ts
CHANGED
package/src/util/directories.ts
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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(
|
|
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(
|
|
16
|
+
return join(LOCAL_CERT_AND_KEY_DIR, DEVICE_CERTIFICATE_FILE_NAME);
|
|
26
17
|
}
|
|
27
18
|
|
|
28
19
|
export function getRootCertificateFilePath() {
|
|
29
|
-
return join(
|
|
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
|
+
}
|