@openserv-labs/client 2.5.1 → 2.5.3
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/README.md +0 -1
- package/dist/cli/banner.d.ts +2 -0
- package/dist/cli/banner.d.ts.map +1 -0
- package/dist/cli/banner.js +31 -0
- package/dist/cli/deploy/api-client.d.ts +44 -0
- package/dist/cli/deploy/api-client.d.ts.map +1 -0
- package/dist/cli/deploy/api-client.js +84 -0
- package/dist/cli/deploy/deploy.d.ts +2 -0
- package/dist/cli/deploy/deploy.d.ts.map +1 -0
- package/dist/cli/deploy/deploy.js +127 -0
- package/dist/cli/deploy/env.d.ts +8 -0
- package/dist/cli/deploy/env.d.ts.map +1 -0
- package/dist/cli/deploy/env.js +38 -0
- package/dist/cli/deploy/index.d.ts +2 -0
- package/dist/cli/deploy/index.d.ts.map +1 -0
- package/dist/cli/deploy/index.js +43 -0
- package/dist/cli/deploy/logger.d.ts +22 -0
- package/dist/cli/deploy/logger.d.ts.map +1 -0
- package/dist/cli/deploy/logger.js +81 -0
- package/dist/cli/deploy/tar.d.ts +6 -0
- package/dist/cli/deploy/tar.d.ts.map +1 -0
- package/dist/cli/deploy/tar.js +59 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/deploy/api-client.d.ts +0 -2
- package/dist/deploy/api-client.d.ts.map +1 -1
- package/dist/deploy/api-client.js +0 -19
- package/dist/deploy/deploy.d.ts.map +1 -1
- package/dist/deploy/deploy.js +3 -25
- package/package.json +3 -3
- package/dist/deploy/openserv-json.d.ts +0 -6
- package/dist/deploy/openserv-json.d.ts.map +0 -1
- package/dist/deploy/openserv-json.js +0 -27
package/README.md
CHANGED
|
@@ -757,7 +757,6 @@ The deploy command:
|
|
|
757
757
|
3. Archives your source code (respects `.gitignore`, excludes `node_modules`, `.git`, `.env`, `dist`)
|
|
758
758
|
4. Uploads and installs dependencies in the container
|
|
759
759
|
5. Starts (or restarts) the agent and exposes a public URL
|
|
760
|
-
6. Updates the agent's endpoint URL on the platform automatically
|
|
761
760
|
|
|
762
761
|
### Deploy Workflow
|
|
763
762
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/cli/banner.ts"],"names":[],"mappings":"AAiBA,wBAAgB,WAAW,IAAI,IAAI,CAalC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.printBanner = printBanner;
|
|
4
|
+
const BANNER = [
|
|
5
|
+
` ███████╗███████╗██████╗ ██╗ ██╗`,
|
|
6
|
+
` ██╔════╝██╔════╝██╔══██╗██║ ██║`,
|
|
7
|
+
` ███████╗█████╗ ██████╔╝██║ ██║`,
|
|
8
|
+
` ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝`,
|
|
9
|
+
` ███████║███████╗██║ ██║ ╚████╔╝`,
|
|
10
|
+
` ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝`,
|
|
11
|
+
];
|
|
12
|
+
const TAGLINE = " OpenServ Platform Client";
|
|
13
|
+
function supportsColor() {
|
|
14
|
+
if (process.env.NO_COLOR || process.env.TERM === "dumb")
|
|
15
|
+
return false;
|
|
16
|
+
if (process.env.FORCE_COLOR)
|
|
17
|
+
return true;
|
|
18
|
+
return process.stdout.isTTY === true;
|
|
19
|
+
}
|
|
20
|
+
function printBanner() {
|
|
21
|
+
const color = supportsColor();
|
|
22
|
+
const cyan = color ? "\x1b[38;2;1;254;147;1m" : "";
|
|
23
|
+
const dim = color ? "\x1b[2m" : "";
|
|
24
|
+
const reset = color ? "\x1b[0m" : "";
|
|
25
|
+
console.log();
|
|
26
|
+
for (const line of BANNER) {
|
|
27
|
+
console.log(`${cyan}${line}${reset}`);
|
|
28
|
+
}
|
|
29
|
+
console.log(`${dim}${TAGLINE}${reset}`);
|
|
30
|
+
console.log();
|
|
31
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare class ApiError extends Error {
|
|
2
|
+
readonly statusCode: number | undefined;
|
|
3
|
+
constructor(message: string, statusCode: number | undefined);
|
|
4
|
+
}
|
|
5
|
+
export interface ApiClientOptions {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
orchestratorUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ContainerInfo {
|
|
10
|
+
id: string;
|
|
11
|
+
appName: string;
|
|
12
|
+
machineId: string;
|
|
13
|
+
status: string;
|
|
14
|
+
}
|
|
15
|
+
export interface StatusInfo {
|
|
16
|
+
id: string;
|
|
17
|
+
appName: string;
|
|
18
|
+
machineId: string;
|
|
19
|
+
status: string;
|
|
20
|
+
machineState: string;
|
|
21
|
+
metadata: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
export interface ExecResult {
|
|
24
|
+
stdout: string;
|
|
25
|
+
stderr: string;
|
|
26
|
+
exitCode: number;
|
|
27
|
+
}
|
|
28
|
+
export interface GoLiveResult {
|
|
29
|
+
publicUrl: string;
|
|
30
|
+
}
|
|
31
|
+
export declare class ApiClient {
|
|
32
|
+
private client;
|
|
33
|
+
constructor(opts: ApiClientOptions);
|
|
34
|
+
createContainer(): Promise<ContainerInfo>;
|
|
35
|
+
getStatus(id: string): Promise<StatusInfo>;
|
|
36
|
+
upload(id: string, tarBuffer: Buffer): Promise<void>;
|
|
37
|
+
exec(id: string, command: string[], timeout?: number): Promise<ExecResult>;
|
|
38
|
+
start(id: string, entrypoint?: string): Promise<void>;
|
|
39
|
+
restart(id: string): Promise<void>;
|
|
40
|
+
goLive(id: string, mode?: string): Promise<GoLiveResult>;
|
|
41
|
+
updateEndpointUrl(agentId: number, agentApiKey: string, endpointUrl: string): Promise<void>;
|
|
42
|
+
private request;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../src/cli/deploy/api-client.ts"],"names":[],"mappings":"AAIA,qBAAa,QAAS,SAAQ,KAAK;aAGf,UAAU,EAAE,MAAM,GAAG,SAAS;gBAD9C,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,GAAG,SAAS;CAKjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;gBAElB,IAAI,EAAE,gBAAgB;IAa5B,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAIzC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD,IAAI,CACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAOhB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,SAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAM7D,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;YAUF,OAAO;CAyBtB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ApiClient = exports.ApiError = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const DEFAULT_ORCHESTRATOR_URL = "https://agent-orchestrator.openserv.ai";
|
|
9
|
+
class ApiError extends Error {
|
|
10
|
+
statusCode;
|
|
11
|
+
constructor(message, statusCode) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.statusCode = statusCode;
|
|
14
|
+
this.name = "ApiError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.ApiError = ApiError;
|
|
18
|
+
class ApiClient {
|
|
19
|
+
client;
|
|
20
|
+
constructor(opts) {
|
|
21
|
+
const headers = {
|
|
22
|
+
"x-openserv-key": opts.apiKey,
|
|
23
|
+
};
|
|
24
|
+
this.client = axios_1.default.create({
|
|
25
|
+
baseURL: opts.orchestratorUrl || DEFAULT_ORCHESTRATOR_URL,
|
|
26
|
+
headers,
|
|
27
|
+
maxBodyLength: 100 * 1024 * 1024,
|
|
28
|
+
maxContentLength: 100 * 1024 * 1024,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async createContainer() {
|
|
32
|
+
return this.request("POST", "/container/create");
|
|
33
|
+
}
|
|
34
|
+
async getStatus(id) {
|
|
35
|
+
return this.request("GET", `/container/${id}/status`);
|
|
36
|
+
}
|
|
37
|
+
async upload(id, tarBuffer) {
|
|
38
|
+
await this.request("POST", `/container/${id}/upload`, tarBuffer, {
|
|
39
|
+
headers: { "Content-Type": "application/gzip" },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async exec(id, command, timeout) {
|
|
43
|
+
return this.request("POST", `/container/${id}/exec`, {
|
|
44
|
+
command,
|
|
45
|
+
timeout,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async start(id, entrypoint) {
|
|
49
|
+
await this.request("POST", `/container/${id}/start`, {
|
|
50
|
+
entrypoint: entrypoint || "npx tsx src/agent.ts",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async restart(id) {
|
|
54
|
+
await this.request("POST", `/container/${id}/restart`);
|
|
55
|
+
}
|
|
56
|
+
async goLive(id, mode = "on-demand") {
|
|
57
|
+
return this.request("POST", `/container/${id}/go-live`, {
|
|
58
|
+
mode,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async updateEndpointUrl(agentId, agentApiKey, endpointUrl) {
|
|
62
|
+
const platformUrl = process.env.OPENSERV_API_URL || "https://api.openserv.ai";
|
|
63
|
+
await axios_1.default.put(`${platformUrl}/agents/${agentId}/endpoint-url`, { endpoint_url: endpointUrl }, { headers: { "x-openserv-key": agentApiKey } });
|
|
64
|
+
}
|
|
65
|
+
async request(method, path, body, config) {
|
|
66
|
+
try {
|
|
67
|
+
const res = await this.client.request({
|
|
68
|
+
method,
|
|
69
|
+
url: path,
|
|
70
|
+
data: body,
|
|
71
|
+
...config,
|
|
72
|
+
});
|
|
73
|
+
return res.data;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
const axiosErr = err;
|
|
77
|
+
const statusCode = axiosErr.response?.status;
|
|
78
|
+
const data = axiosErr.response?.data ?? axiosErr.message;
|
|
79
|
+
const detail = typeof data === "string" ? data : JSON.stringify(data);
|
|
80
|
+
throw new ApiError(`${method} ${path} failed (${statusCode ?? "unknown"}): ${detail}`, statusCode);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.ApiClient = ApiClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/cli/deploy/deploy.ts"],"names":[],"mappings":"AAmCA,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4G9D"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deploy = deploy;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const api_client_js_1 = require("./api-client.js");
|
|
9
|
+
const env_js_1 = require("./env.js");
|
|
10
|
+
const logger_js_1 = require("./logger.js");
|
|
11
|
+
const tar_js_1 = require("./tar.js");
|
|
12
|
+
async function resolveContainer(client, dir, containerId) {
|
|
13
|
+
if (containerId) {
|
|
14
|
+
logger_js_1.logger.step("Resolving container...");
|
|
15
|
+
logger_js_1.logger.detail(`Container ID: ${containerId}`);
|
|
16
|
+
return { id: containerId, isFirstDeploy: false };
|
|
17
|
+
}
|
|
18
|
+
const spin = logger_js_1.logger.spin("Creating new container...");
|
|
19
|
+
try {
|
|
20
|
+
const container = await client.createContainer();
|
|
21
|
+
(0, env_js_1.writeContainerId)(dir, container.id);
|
|
22
|
+
spin.stop(`Container ID: ${container.id}`);
|
|
23
|
+
logger_js_1.logger.detail("Written to .env");
|
|
24
|
+
return { id: container.id, isFirstDeploy: true };
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
spin.fail("Failed to create container");
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function deploy(targetPath) {
|
|
32
|
+
const deployStart = Date.now();
|
|
33
|
+
const dir = node_path_1.default.resolve(targetPath);
|
|
34
|
+
logger_js_1.logger.step(`Deploying from ${dir}`);
|
|
35
|
+
const env = (0, env_js_1.readEnv)(dir);
|
|
36
|
+
if (!env.apiKey) {
|
|
37
|
+
throw new Error("OPENSERV_USER_API_KEY not found. Set it in your .env file or as an environment variable.");
|
|
38
|
+
}
|
|
39
|
+
const client = new api_client_js_1.ApiClient({
|
|
40
|
+
apiKey: env.apiKey,
|
|
41
|
+
orchestratorUrl: env.orchestratorUrl,
|
|
42
|
+
});
|
|
43
|
+
const { id: targetId, isFirstDeploy } = await resolveContainer(client, dir, env.containerId);
|
|
44
|
+
let currentStatus;
|
|
45
|
+
if (!isFirstDeploy) {
|
|
46
|
+
try {
|
|
47
|
+
const status = await client.getStatus(targetId);
|
|
48
|
+
currentStatus = status.status;
|
|
49
|
+
logger_js_1.logger.detail(`Current status: ${currentStatus}`);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Container might not be reachable yet
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
logger_js_1.logger.step("Creating archive...");
|
|
56
|
+
const { buffer: tarBuffer, files } = await (0, tar_js_1.createTarBuffer)(dir);
|
|
57
|
+
logger_js_1.logger.detail(`${files.length} files, ${(tarBuffer.length / 1024).toFixed(1)} KB`);
|
|
58
|
+
const uploadSpin = logger_js_1.logger.spin("Uploading files...");
|
|
59
|
+
try {
|
|
60
|
+
await client.upload(targetId, tarBuffer);
|
|
61
|
+
const verify = await client.exec(targetId, ["ls", "-la", "/app"], 30);
|
|
62
|
+
if (verify.exitCode === 0) {
|
|
63
|
+
uploadSpin.stop("Upload verified");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
uploadSpin.warn("Could not verify upload");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
uploadSpin.fail("Upload failed");
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
const installSpin = logger_js_1.logger.spin("Installing dependencies...");
|
|
74
|
+
const installStart = Date.now();
|
|
75
|
+
try {
|
|
76
|
+
const installResult = await client.exec(targetId, ["npm", "install"], 600);
|
|
77
|
+
if (installResult.exitCode !== 0) {
|
|
78
|
+
const msg = `npm install failed (exit code ${installResult.exitCode})`;
|
|
79
|
+
const parts = [msg];
|
|
80
|
+
if (installResult.stdout)
|
|
81
|
+
parts.push(`stdout: ${installResult.stdout.slice(0, 500)}`);
|
|
82
|
+
if (installResult.stderr)
|
|
83
|
+
parts.push(`stderr: ${installResult.stderr.slice(0, 500)}`);
|
|
84
|
+
installSpin.fail(msg);
|
|
85
|
+
throw new Error(parts.join("\n"));
|
|
86
|
+
}
|
|
87
|
+
installSpin.stop(`Done (${(0, logger_js_1.elapsed)(installStart)})`);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
if (installSpin.isSpinning)
|
|
91
|
+
installSpin.fail("Install failed");
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
if (isFirstDeploy || !currentStatus || currentStatus === "ready") {
|
|
95
|
+
const startSpin = logger_js_1.logger.spin("Starting agent...");
|
|
96
|
+
try {
|
|
97
|
+
await client.start(targetId);
|
|
98
|
+
startSpin.stop("Agent started");
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
startSpin.fail("Start failed");
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const restartSpin = logger_js_1.logger.spin("Restarting container...");
|
|
107
|
+
try {
|
|
108
|
+
await client.restart(targetId);
|
|
109
|
+
restartSpin.stop("Container restarted");
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
restartSpin.fail("Restart failed");
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const goLiveSpin = logger_js_1.logger.spin("Going live...");
|
|
117
|
+
const goLiveStart = Date.now();
|
|
118
|
+
try {
|
|
119
|
+
await client.goLive(targetId, "continuous");
|
|
120
|
+
goLiveSpin.stop(`Done (${(0, logger_js_1.elapsed)(goLiveStart)})`);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
goLiveSpin.fail("Going live failed");
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
logger_js_1.logger.success(`Deploy complete! (${(0, logger_js_1.elapsed)(deployStart)})`);
|
|
127
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface EnvValues {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
containerId?: string;
|
|
4
|
+
orchestratorUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function readEnv(dir: string): EnvValues;
|
|
7
|
+
export declare function writeContainerId(dir: string, containerId: string): void;
|
|
8
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/cli/deploy/env.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAY9C;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAoBvE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readEnv = readEnv;
|
|
7
|
+
exports.writeContainerId = writeContainerId;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const dotenv_1 = require("dotenv");
|
|
11
|
+
function readEnv(dir) {
|
|
12
|
+
const envPath = node_path_1.default.join(dir, ".env");
|
|
13
|
+
const parsed = (0, dotenv_1.config)({ path: envPath });
|
|
14
|
+
const env = parsed.parsed ?? {};
|
|
15
|
+
return {
|
|
16
|
+
apiKey: env.OPENSERV_USER_API_KEY || process.env.OPENSERV_USER_API_KEY,
|
|
17
|
+
containerId: env.OPENSERV_CONTAINER_ID || process.env.OPENSERV_CONTAINER_ID,
|
|
18
|
+
orchestratorUrl: env.OPENSERV_ORCHESTRATOR_URL || process.env.OPENSERV_ORCHESTRATOR_URL,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function writeContainerId(dir, containerId) {
|
|
22
|
+
const envPath = node_path_1.default.join(dir, ".env");
|
|
23
|
+
let content = "";
|
|
24
|
+
if (node_fs_1.default.existsSync(envPath)) {
|
|
25
|
+
content = node_fs_1.default.readFileSync(envPath, "utf8");
|
|
26
|
+
}
|
|
27
|
+
const key = "OPENSERV_CONTAINER_ID";
|
|
28
|
+
const line = `${key}=${containerId}`;
|
|
29
|
+
const regex = new RegExp(`^${key}=.*$`, "m");
|
|
30
|
+
if (regex.test(content)) {
|
|
31
|
+
content = content.replace(regex, line);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const separator = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
|
|
35
|
+
content = `${content}${separator}${line}\n`;
|
|
36
|
+
}
|
|
37
|
+
node_fs_1.default.writeFileSync(envPath, content, "utf8");
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/deploy/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const banner_js_1 = require("../banner.js");
|
|
4
|
+
const deploy_js_1 = require("./deploy.js");
|
|
5
|
+
const logger_js_1 = require("./logger.js");
|
|
6
|
+
const HELP = `
|
|
7
|
+
Usage: serv <command> [path]
|
|
8
|
+
|
|
9
|
+
Commands:
|
|
10
|
+
deploy [path] Deploy an agent to OpenServ (default path: .)
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
--help, -h Show this help message
|
|
14
|
+
|
|
15
|
+
Environment variables (set in .env or shell):
|
|
16
|
+
OPENSERV_USER_API_KEY Your OpenServ API key (required)
|
|
17
|
+
OPENSERV_CONTAINER_ID Container ID for redeployment (auto-set after first deploy)
|
|
18
|
+
OPENSERV_ORCHESTRATOR_URL Custom orchestrator URL (optional)
|
|
19
|
+
`.trim();
|
|
20
|
+
async function main() {
|
|
21
|
+
(0, banner_js_1.printBanner)();
|
|
22
|
+
const args = process.argv.slice(2);
|
|
23
|
+
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
24
|
+
console.log(HELP);
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
const command = args[0];
|
|
28
|
+
switch (command) {
|
|
29
|
+
case "deploy": {
|
|
30
|
+
const targetPath = args[1] || ".";
|
|
31
|
+
await (0, deploy_js_1.deploy)(targetPath);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
default:
|
|
35
|
+
console.error(`Unknown command: ${command}\n`);
|
|
36
|
+
console.log(HELP);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
main().catch((err) => {
|
|
41
|
+
logger_js_1.logger.error(err instanceof Error ? err.message : String(err));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare class Spinner {
|
|
2
|
+
private msg;
|
|
3
|
+
private timer;
|
|
4
|
+
private i;
|
|
5
|
+
constructor(msg: string);
|
|
6
|
+
get isSpinning(): boolean;
|
|
7
|
+
private clear;
|
|
8
|
+
stop(detail?: string): void;
|
|
9
|
+
fail(msg: string): void;
|
|
10
|
+
warn(msg: string): void;
|
|
11
|
+
}
|
|
12
|
+
export declare const logger: {
|
|
13
|
+
step: (msg: string) => void;
|
|
14
|
+
detail: (msg: string) => void;
|
|
15
|
+
success: (msg: string) => void;
|
|
16
|
+
warn: (msg: string) => void;
|
|
17
|
+
error: (msg: string) => void;
|
|
18
|
+
info: (...args: unknown[]) => void;
|
|
19
|
+
spin: (msg: string) => Spinner;
|
|
20
|
+
};
|
|
21
|
+
export declare function elapsed(startMs: number): string;
|
|
22
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/cli/deploy/logger.ts"],"names":[],"mappings":"AAkBA,qBAAa,OAAO;IAIN,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,CAAC,CAAK;gBAEM,GAAG,EAAE,MAAM;IAe/B,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,OAAO,CAAC,KAAK;IAUb,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKvB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAKxB;AAED,eAAO,MAAM,MAAM;gBACL,MAAM;kBACJ,MAAM;mBACL,MAAM;gBACT,MAAM;iBACL,MAAM;oBACH,OAAO,EAAE;gBACb,MAAM;CACnB,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG/C"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = exports.Spinner = void 0;
|
|
4
|
+
exports.elapsed = elapsed;
|
|
5
|
+
function supportsColor() {
|
|
6
|
+
if (process.env.NO_COLOR || process.env.TERM === "dumb")
|
|
7
|
+
return false;
|
|
8
|
+
if (process.env.FORCE_COLOR)
|
|
9
|
+
return true;
|
|
10
|
+
return process.stderr.isTTY === true || process.stdout.isTTY === true;
|
|
11
|
+
}
|
|
12
|
+
const color = supportsColor();
|
|
13
|
+
const isTTY = process.stdout.isTTY === true;
|
|
14
|
+
const green = color ? "\x1b[38;2;1;254;147;1m" : "";
|
|
15
|
+
const red = color ? "\x1b[1;31m" : "";
|
|
16
|
+
const yellow = color ? "\x1b[1;33m" : "";
|
|
17
|
+
const dim = color ? "\x1b[2m" : "";
|
|
18
|
+
const reset = color ? "\x1b[0m" : "";
|
|
19
|
+
const clearLine = "\x1b[2K\r";
|
|
20
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
21
|
+
class Spinner {
|
|
22
|
+
msg;
|
|
23
|
+
timer = null;
|
|
24
|
+
i = 0;
|
|
25
|
+
constructor(msg) {
|
|
26
|
+
this.msg = msg;
|
|
27
|
+
if (isTTY) {
|
|
28
|
+
process.stdout.write(`\n${green} ${frames[0]} ${msg}${reset}`);
|
|
29
|
+
this.timer = setInterval(() => {
|
|
30
|
+
this.i++;
|
|
31
|
+
const frame = frames[this.i % frames.length];
|
|
32
|
+
process.stdout.write(`${clearLine}${green} ${frame} ${this.msg}${reset}`);
|
|
33
|
+
}, 80);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(`\n => ${msg}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
get isSpinning() {
|
|
40
|
+
return this.timer !== null;
|
|
41
|
+
}
|
|
42
|
+
clear() {
|
|
43
|
+
if (this.timer) {
|
|
44
|
+
clearInterval(this.timer);
|
|
45
|
+
this.timer = null;
|
|
46
|
+
}
|
|
47
|
+
if (isTTY) {
|
|
48
|
+
process.stdout.write(clearLine);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
stop(detail) {
|
|
52
|
+
this.clear();
|
|
53
|
+
console.log(`${green} => ${this.msg}${reset}`);
|
|
54
|
+
if (detail) {
|
|
55
|
+
console.log(`${dim} ${detail}${reset}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
fail(msg) {
|
|
59
|
+
this.clear();
|
|
60
|
+
console.error(`${red} ✖ ${msg}${reset}`);
|
|
61
|
+
}
|
|
62
|
+
warn(msg) {
|
|
63
|
+
this.clear();
|
|
64
|
+
console.log(`${green} => ${this.msg}${reset}`);
|
|
65
|
+
console.warn(`${yellow} ⚠ ${msg}${reset}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.Spinner = Spinner;
|
|
69
|
+
exports.logger = {
|
|
70
|
+
step: (msg) => console.log(`\n${green} => ${msg}${reset}`),
|
|
71
|
+
detail: (msg) => console.log(`${dim} ${msg}${reset}`),
|
|
72
|
+
success: (msg) => console.log(`\n${green} ✔ ${msg}${reset}`),
|
|
73
|
+
warn: (msg) => console.warn(`${yellow} ⚠ ${msg}${reset}`),
|
|
74
|
+
error: (msg) => console.error(`${red} ✖ ${msg}${reset}`),
|
|
75
|
+
info: (...args) => console.log(...args),
|
|
76
|
+
spin: (msg) => new Spinner(msg),
|
|
77
|
+
};
|
|
78
|
+
function elapsed(startMs) {
|
|
79
|
+
const sec = (Date.now() - startMs) / 1000;
|
|
80
|
+
return sec < 1 ? `${(sec * 1000).toFixed(0)}ms` : `${sec.toFixed(1)}s`;
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../../../src/cli/deploy/tar.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAerE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createTarBuffer = createTarBuffer;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const ignore_1 = __importDefault(require("ignore"));
|
|
10
|
+
const nanotar_1 = require("nanotar");
|
|
11
|
+
const ALWAYS_EXCLUDE = [
|
|
12
|
+
"node_modules",
|
|
13
|
+
".git",
|
|
14
|
+
"dist",
|
|
15
|
+
".next",
|
|
16
|
+
".turbo",
|
|
17
|
+
".env.example",
|
|
18
|
+
".env.local",
|
|
19
|
+
".env.*.local",
|
|
20
|
+
];
|
|
21
|
+
const ALWAYS_EXCLUDE_EXTENSIONS = [".tsbuildinfo"];
|
|
22
|
+
async function createTarBuffer(dir) {
|
|
23
|
+
const ig = (0, ignore_1.default)();
|
|
24
|
+
ig.add(ALWAYS_EXCLUDE);
|
|
25
|
+
const gitignorePath = node_path_1.default.join(dir, ".gitignore");
|
|
26
|
+
if (node_fs_1.default.existsSync(gitignorePath)) {
|
|
27
|
+
const content = node_fs_1.default.readFileSync(gitignorePath, "utf8");
|
|
28
|
+
ig.add(content);
|
|
29
|
+
}
|
|
30
|
+
const entries = collectEntries(dir, dir, ig);
|
|
31
|
+
const files = entries.map((e) => e.name);
|
|
32
|
+
const gzipped = await (0, nanotar_1.createTarGzip)(entries);
|
|
33
|
+
return { buffer: Buffer.from(gzipped), files };
|
|
34
|
+
}
|
|
35
|
+
function collectEntries(baseDir, currentDir, ig) {
|
|
36
|
+
const entries = [];
|
|
37
|
+
const items = node_fs_1.default.readdirSync(currentDir, { withFileTypes: true });
|
|
38
|
+
for (const item of items) {
|
|
39
|
+
const fullPath = node_path_1.default.join(currentDir, item.name);
|
|
40
|
+
const relativePath = node_path_1.default.relative(baseDir, fullPath);
|
|
41
|
+
if (ALWAYS_EXCLUDE_EXTENSIONS.some((ext) => item.name.endsWith(ext))) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const testPath = item.isDirectory() ? `${relativePath}/` : relativePath;
|
|
45
|
+
if (ig.ignores(testPath)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (item.isDirectory()) {
|
|
49
|
+
entries.push(...collectEntries(baseDir, fullPath, ig));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
entries.push({
|
|
53
|
+
name: relativePath,
|
|
54
|
+
data: new Uint8Array(node_fs_1.default.readFileSync(fullPath)),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return entries;
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,mBAAmB,CAAC"}
|
|
@@ -4,7 +4,6 @@ export declare class ApiError extends Error {
|
|
|
4
4
|
}
|
|
5
5
|
export interface ApiClientOptions {
|
|
6
6
|
apiKey: string;
|
|
7
|
-
agentId?: number;
|
|
8
7
|
orchestratorUrl?: string;
|
|
9
8
|
}
|
|
10
9
|
export interface ContainerInfo {
|
|
@@ -34,7 +33,6 @@ export declare class ApiClient {
|
|
|
34
33
|
constructor(opts: ApiClientOptions);
|
|
35
34
|
createContainer(): Promise<ContainerInfo>;
|
|
36
35
|
getStatus(id: string): Promise<StatusInfo>;
|
|
37
|
-
findContainerByAgent(agentId: number): Promise<ContainerInfo | null>;
|
|
38
36
|
upload(id: string, tarBuffer: Buffer): Promise<void>;
|
|
39
37
|
exec(id: string, command: string[], timeout?: number): Promise<ExecResult>;
|
|
40
38
|
start(id: string, entrypoint?: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/deploy/api-client.ts"],"names":[],"mappings":"AAIA,qBAAa,QAAS,SAAQ,KAAK;aAGf,UAAU,EAAE,MAAM,GAAG,SAAS;gBAD9C,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,GAAG,SAAS;CAKjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/deploy/api-client.ts"],"names":[],"mappings":"AAIA,qBAAa,QAAS,SAAQ,KAAK;aAGf,UAAU,EAAE,MAAM,GAAG,SAAS;gBAD9C,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,GAAG,SAAS;CAKjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;gBAElB,IAAI,EAAE,gBAAgB;IAa5B,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC;IAIzC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD,IAAI,CACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAOhB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,SAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAM7D,iBAAiB,CACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;YAUF,OAAO;CAyBtB"}
|
|
@@ -21,9 +21,6 @@ class ApiClient {
|
|
|
21
21
|
const headers = {
|
|
22
22
|
"x-openserv-key": opts.apiKey,
|
|
23
23
|
};
|
|
24
|
-
if (opts.agentId != null) {
|
|
25
|
-
headers["x-openserv-agent-id"] = String(opts.agentId);
|
|
26
|
-
}
|
|
27
24
|
this.client = axios_1.default.create({
|
|
28
25
|
baseURL: opts.orchestratorUrl || DEFAULT_ORCHESTRATOR_URL,
|
|
29
26
|
headers,
|
|
@@ -37,22 +34,6 @@ class ApiClient {
|
|
|
37
34
|
async getStatus(id) {
|
|
38
35
|
return this.request("GET", `/container/${id}/status`);
|
|
39
36
|
}
|
|
40
|
-
async findContainerByAgent(agentId) {
|
|
41
|
-
try {
|
|
42
|
-
const status = await this.getStatus(String(agentId));
|
|
43
|
-
return {
|
|
44
|
-
id: status.id,
|
|
45
|
-
appName: status.appName,
|
|
46
|
-
machineId: status.machineId,
|
|
47
|
-
status: status.status,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
if (err instanceof ApiError && err.statusCode === 404)
|
|
52
|
-
return null;
|
|
53
|
-
throw err;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
37
|
async upload(id, tarBuffer) {
|
|
57
38
|
await this.request("POST", `/container/${id}/upload`, tarBuffer, {
|
|
58
39
|
headers: { "Content-Type": "application/gzip" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/deploy/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/deploy/deploy.ts"],"names":[],"mappings":"AA8BA,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkG9D"}
|
package/dist/deploy/deploy.js
CHANGED
|
@@ -8,27 +8,13 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
8
8
|
const api_client_js_1 = require("./api-client.js");
|
|
9
9
|
const env_js_1 = require("./env.js");
|
|
10
10
|
const logger_js_1 = require("./logger.js");
|
|
11
|
-
const openserv_json_js_1 = require("./openserv-json.js");
|
|
12
11
|
const tar_js_1 = require("./tar.js");
|
|
13
|
-
async function resolveContainer(client, dir, containerId
|
|
12
|
+
async function resolveContainer(client, dir, containerId) {
|
|
14
13
|
if (containerId) {
|
|
15
14
|
logger_js_1.logger.info(`Using existing container: ${containerId}`);
|
|
16
15
|
return { id: containerId, isFirstDeploy: false };
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
logger_js_1.logger.info(`Agent ID found: ${agentId}. Checking for existing container...`);
|
|
20
|
-
const existing = await client.findContainerByAgent(agentId);
|
|
21
|
-
if (existing) {
|
|
22
|
-
(0, env_js_1.writeContainerId)(dir, existing.id);
|
|
23
|
-
logger_js_1.logger.info(` Found container: ${existing.id}`);
|
|
24
|
-
logger_js_1.logger.info(" Saved to .env\n");
|
|
25
|
-
return { id: existing.id, isFirstDeploy: false };
|
|
26
|
-
}
|
|
27
|
-
logger_js_1.logger.info(" No container found. Creating new container...");
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
logger_js_1.logger.info("Creating new container...");
|
|
31
|
-
}
|
|
17
|
+
logger_js_1.logger.info("Creating new container...");
|
|
32
18
|
const container = await client.createContainer();
|
|
33
19
|
(0, env_js_1.writeContainerId)(dir, container.id);
|
|
34
20
|
logger_js_1.logger.info(` Container ID: ${container.id}`);
|
|
@@ -39,17 +25,14 @@ async function deploy(targetPath) {
|
|
|
39
25
|
const dir = node_path_1.default.resolve(targetPath);
|
|
40
26
|
logger_js_1.logger.info(`Deploying from ${dir}\n`);
|
|
41
27
|
const env = (0, env_js_1.readEnv)(dir);
|
|
42
|
-
const agentConfig = (0, openserv_json_js_1.readAgentConfig)(dir);
|
|
43
|
-
const agentId = agentConfig?.id;
|
|
44
28
|
if (!env.apiKey) {
|
|
45
29
|
throw new Error("OPENSERV_USER_API_KEY not found. Set it in your .env file or as an environment variable.");
|
|
46
30
|
}
|
|
47
31
|
const client = new api_client_js_1.ApiClient({
|
|
48
32
|
apiKey: env.apiKey,
|
|
49
|
-
agentId,
|
|
50
33
|
orchestratorUrl: env.orchestratorUrl,
|
|
51
34
|
});
|
|
52
|
-
const { id: targetId, isFirstDeploy } = await resolveContainer(client, dir, env.containerId
|
|
35
|
+
const { id: targetId, isFirstDeploy } = await resolveContainer(client, dir, env.containerId);
|
|
53
36
|
let currentStatus;
|
|
54
37
|
let appName;
|
|
55
38
|
if (!isFirstDeploy) {
|
|
@@ -119,10 +102,5 @@ async function deploy(targetPath) {
|
|
|
119
102
|
}
|
|
120
103
|
logger_js_1.logger.info("\nAlready live.");
|
|
121
104
|
}
|
|
122
|
-
if (agentConfig?.apiKey && agentConfig.id && publicUrl) {
|
|
123
|
-
logger_js_1.logger.info("\nUpdating agent endpoint URL...");
|
|
124
|
-
await client.updateEndpointUrl(agentConfig.id, agentConfig.apiKey, publicUrl);
|
|
125
|
-
logger_js_1.logger.info(` Agent endpoint set to ${publicUrl}`);
|
|
126
|
-
}
|
|
127
105
|
logger_js_1.logger.info("\nDeploy complete!");
|
|
128
106
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openserv-labs/client",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.3",
|
|
4
4
|
"description": "OpenServ Platform Client - Manage agents, workflows, tasks, and triggers via the OpenServ API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
8
|
-
"serv": "./dist/cli.js"
|
|
8
|
+
"serv": "./dist/cli/index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"format:check": "prettier --check \"**/*.{ts,json,md}\"",
|
|
20
20
|
"test": "node --import tsx --test test/**/*.test.ts",
|
|
21
21
|
"test:unit": "node --import tsx --test test/unit/**/*.test.ts",
|
|
22
|
-
"deploy": "tsx src/cli.ts deploy"
|
|
22
|
+
"deploy": "tsx src/cli/index.ts deploy"
|
|
23
23
|
},
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openserv-json.d.ts","sourceRoot":"","sources":["../../src/deploy/openserv-json.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAmBpE"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.readAgentConfig = readAgentConfig;
|
|
7
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
function readAgentConfig(dir) {
|
|
10
|
-
const filePath = node_path_1.default.join(dir, ".openserv.json");
|
|
11
|
-
if (!node_fs_1.default.existsSync(filePath)) {
|
|
12
|
-
return undefined;
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
const raw = node_fs_1.default.readFileSync(filePath, "utf8");
|
|
16
|
-
const data = JSON.parse(raw);
|
|
17
|
-
if (!data.agents)
|
|
18
|
-
return undefined;
|
|
19
|
-
const firstAgent = Object.values(data.agents)[0];
|
|
20
|
-
if (!firstAgent)
|
|
21
|
-
return undefined;
|
|
22
|
-
return { id: firstAgent.id, apiKey: firstAgent.apiKey };
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
}
|