@openserv-labs/client 2.5.0 → 2.5.2
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 +76 -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/dist/deploy/tar.d.ts.map +1 -1
- package/dist/deploy/tar.js +0 -1
- package/package.json +1 -1
- 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
|
@@ -719,6 +719,82 @@ triggers.manual({
|
|
|
719
719
|
// { type: 'manual', name: '...', description: '...' }
|
|
720
720
|
```
|
|
721
721
|
|
|
722
|
+
## Deploy to OpenServ Cloud
|
|
723
|
+
|
|
724
|
+
Deploy your agent to the OpenServ managed cloud with a single command:
|
|
725
|
+
|
|
726
|
+
```bash
|
|
727
|
+
npx @openserv-labs/client deploy [path]
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
Where `[path]` is the directory containing your agent code (defaults to current directory).
|
|
731
|
+
|
|
732
|
+
### Prerequisites
|
|
733
|
+
|
|
734
|
+
1. **`OPENSERV_USER_API_KEY` in `.env`** — The deploy CLI needs this key to authenticate with the platform. If you've already run `provision()` at least once, check your `.openserv.json` file — it contains a `userApiKey` field you can use:
|
|
735
|
+
|
|
736
|
+
```bash
|
|
737
|
+
# Look for the userApiKey in .openserv.json
|
|
738
|
+
cat .openserv.json | grep userApiKey
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
Copy that value into your `.env`:
|
|
742
|
+
|
|
743
|
+
```env
|
|
744
|
+
OPENSERV_USER_API_KEY=<userApiKey from .openserv.json>
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
If you haven't provisioned yet, get the key from the [OpenServ platform dashboard](https://platform.openserv.ai/profile/api-keys) instead.
|
|
748
|
+
|
|
749
|
+
2. **Run `provision()` first** — Your agent must be provisioned at least once before deploying. `provision()` registers the agent on the platform and writes credentials to `.openserv.json`. Starting the agent locally (`npm run dev`) is enough if your code calls `provision()` before `run(agent)`.
|
|
750
|
+
|
|
751
|
+
### How It Works
|
|
752
|
+
|
|
753
|
+
The deploy command:
|
|
754
|
+
|
|
755
|
+
1. Reads `.openserv.json` to find the provisioned agent ID
|
|
756
|
+
2. Creates or reuses a cloud container (saves `OPENSERV_CONTAINER_ID` to `.env`)
|
|
757
|
+
3. Archives your source code (respects `.gitignore`, excludes `node_modules`, `.git`, `.env`, `dist`)
|
|
758
|
+
4. Uploads and installs dependencies in the container
|
|
759
|
+
5. Starts (or restarts) the agent and exposes a public URL
|
|
760
|
+
|
|
761
|
+
### Deploy Workflow
|
|
762
|
+
|
|
763
|
+
```bash
|
|
764
|
+
# 1. Run locally once to provision (registers agent + writes .openserv.json)
|
|
765
|
+
npm run dev
|
|
766
|
+
|
|
767
|
+
# 2. Set OPENSERV_USER_API_KEY in .env
|
|
768
|
+
# - If you already provisioned: grab userApiKey from .openserv.json
|
|
769
|
+
# - Otherwise: get it from the platform dashboard
|
|
770
|
+
echo "OPENSERV_USER_API_KEY=your-key" >> .env
|
|
771
|
+
|
|
772
|
+
# 3. Deploy to cloud
|
|
773
|
+
npx @openserv-labs/client deploy .
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
On subsequent deploys, the CLI reuses the existing container — it uploads your latest code, reinstalls dependencies, and restarts the agent.
|
|
777
|
+
|
|
778
|
+
### Environment Variables for Deploy
|
|
779
|
+
|
|
780
|
+
| Variable | Description | Required |
|
|
781
|
+
| --------------------------- | ---------------------------------------- | -------- |
|
|
782
|
+
| `OPENSERV_USER_API_KEY` | Your OpenServ user API key | Yes |
|
|
783
|
+
| `OPENSERV_CONTAINER_ID` | Container ID (auto-set after first deploy) | No |
|
|
784
|
+
|
|
785
|
+
### CLI Reference
|
|
786
|
+
|
|
787
|
+
The package also exposes a `serv` binary:
|
|
788
|
+
|
|
789
|
+
```bash
|
|
790
|
+
# Via npx
|
|
791
|
+
npx @openserv-labs/client deploy [path]
|
|
792
|
+
|
|
793
|
+
# Or if installed globally / as a dependency
|
|
794
|
+
serv deploy [path]
|
|
795
|
+
serv --help
|
|
796
|
+
```
|
|
797
|
+
|
|
722
798
|
## Environment Variables
|
|
723
799
|
|
|
724
800
|
| Variable | Description | Required |
|
|
@@ -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/dist/deploy/tar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../../src/deploy/tar.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../../src/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"}
|
package/dist/deploy/tar.js
CHANGED
package/package.json
CHANGED
|
@@ -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
|
-
}
|