@openserv-labs/client 2.5.2 → 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.
@@ -0,0 +1,2 @@
1
+ export declare function printBanner(): void;
2
+ //# sourceMappingURL=banner.d.ts.map
@@ -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,2 @@
1
+ export declare function deploy(targetPath: string): Promise<void>;
2
+ //# sourceMappingURL=deploy.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,6 @@
1
+ export interface TarResult {
2
+ buffer: Buffer;
3
+ files: string[];
4
+ }
5
+ export declare function createTarBuffer(dir: string): Promise<TarResult>;
6
+ //# sourceMappingURL=tar.d.ts.map
@@ -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,3 @@
1
+ #!/usr/bin/env node
2
+ import "./deploy/index.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,mBAAmB,CAAC"}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ require("./deploy/index.js");
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@openserv-labs/client",
3
- "version": "2.5.2",
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",