@blaxel/core 0.2.0-preview3 → 0.2.0-preview5

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.
Files changed (39) hide show
  1. package/dist/client/sdk.gen.d.ts +32 -2
  2. package/dist/client/sdk.gen.js +112 -2
  3. package/dist/client/types.gen.d.ts +237 -17
  4. package/dist/common/env.js +3 -7
  5. package/dist/common/internal.d.ts +1 -1
  6. package/dist/common/internal.js +3 -6
  7. package/dist/common/settings.d.ts +2 -0
  8. package/dist/common/settings.js +9 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +1 -0
  11. package/dist/jobs/index.d.ts +1 -0
  12. package/dist/jobs/index.js +17 -0
  13. package/dist/jobs/jobs.d.ts +10 -0
  14. package/dist/jobs/jobs.js +42 -0
  15. package/dist/mcp/client.js +0 -3
  16. package/dist/mcp/server/http.d.ts +8 -0
  17. package/dist/mcp/server/http.js +16 -0
  18. package/dist/mcp/server/index.d.ts +4 -0
  19. package/dist/mcp/server/index.js +21 -0
  20. package/dist/mcp/server/websocket.d.ts +24 -0
  21. package/dist/mcp/server/websocket.js +213 -0
  22. package/dist/sandbox/action.d.ts +4 -3
  23. package/dist/sandbox/action.js +16 -2
  24. package/dist/sandbox/client/sdk.gen.d.ts +9 -6
  25. package/dist/sandbox/client/sdk.gen.js +14 -3
  26. package/dist/sandbox/client/types.gen.d.ts +33 -17
  27. package/dist/sandbox/filesystem.d.ts +6 -0
  28. package/dist/sandbox/filesystem.js +77 -0
  29. package/dist/sandbox/process.d.ts +11 -0
  30. package/dist/sandbox/process.js +77 -0
  31. package/dist/sandbox/sandbox.d.ts +5 -1
  32. package/dist/sandbox/sandbox.js +6 -0
  33. package/dist/sandbox/session.d.ts +21 -0
  34. package/dist/sandbox/session.js +97 -0
  35. package/dist/sandbox/types.d.ts +15 -0
  36. package/dist/sandbox/types.js +2 -0
  37. package/dist/telemetry/telemetry.d.ts +1 -0
  38. package/dist/telemetry/telemetry.js +14 -0
  39. package/package.json +5 -1
@@ -13,6 +13,7 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
13
13
  path: { path },
14
14
  body: { isDirectory: true, permissions },
15
15
  baseUrl: this.url,
16
+ client: this.client,
16
17
  });
17
18
  this.handleResponseError(response, data, error);
18
19
  return data;
@@ -23,6 +24,7 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
23
24
  path: { path },
24
25
  body: { content },
25
26
  baseUrl: this.url,
27
+ client: this.client,
26
28
  });
27
29
  this.handleResponseError(response, data, error);
28
30
  return data;
@@ -32,6 +34,7 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
32
34
  const { response, data, error } = await (0, index_js_1.getFilesystemByPath)({
33
35
  path: { path },
34
36
  baseUrl: this.url,
37
+ client: this.client,
35
38
  });
36
39
  this.handleResponseError(response, data, error);
37
40
  if (data && 'content' in data) {
@@ -45,6 +48,7 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
45
48
  path: { path },
46
49
  query: { recursive },
47
50
  baseUrl: this.url,
51
+ client: this.client,
48
52
  });
49
53
  this.handleResponseError(response, data, error);
50
54
  return data;
@@ -54,6 +58,7 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
54
58
  const { response, data, error } = await (0, index_js_1.getFilesystemByPath)({
55
59
  path: { path },
56
60
  baseUrl: this.url,
61
+ client: this.client,
57
62
  });
58
63
  this.handleResponseError(response, data, error);
59
64
  if (!data || !('files' in data || 'subdirectories' in data)) {
@@ -67,6 +72,7 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
67
72
  const { response, data, error } = await (0, index_js_1.getFilesystemByPath)({
68
73
  path: { path: source },
69
74
  baseUrl: this.url,
75
+ client: this.client,
70
76
  });
71
77
  this.handleResponseError(response, data, error);
72
78
  if (data && ('files' in data || 'subdirectories' in data)) {
@@ -111,7 +117,78 @@ class SandboxFileSystem extends action_js_1.SandboxAction {
111
117
  }
112
118
  throw new Error("Unsupported file type");
113
119
  }
120
+ watch(path, callback, options) {
121
+ path = this.formatPath(path);
122
+ let closed = false;
123
+ let controller = new AbortController();
124
+ const start = async () => {
125
+ const { response, data, error } = await (0, index_js_1.getWatchFilesystemByPath)({
126
+ client: this.client,
127
+ path: { path },
128
+ baseUrl: this.url,
129
+ parseAs: 'stream',
130
+ signal: controller.signal,
131
+ });
132
+ if (error)
133
+ throw error;
134
+ const stream = data ?? response.body;
135
+ if (!stream)
136
+ throw new Error('No stream returned');
137
+ const reader = stream.getReader();
138
+ let buffer = '';
139
+ const decoder = new TextDecoder();
140
+ try {
141
+ while (!closed) {
142
+ const { value, done } = await reader.read();
143
+ if (done)
144
+ break;
145
+ buffer += decoder.decode(value, { stream: true });
146
+ let lines = buffer.split('\n');
147
+ buffer = lines.pop();
148
+ for (const line of lines) {
149
+ const filePath = line.trim();
150
+ if (!filePath)
151
+ continue;
152
+ if (options?.withContent) {
153
+ try {
154
+ const content = await this.read(filePath);
155
+ await callback(filePath, content);
156
+ }
157
+ catch (e) {
158
+ await callback(filePath, undefined);
159
+ }
160
+ }
161
+ else {
162
+ await callback(filePath);
163
+ }
164
+ }
165
+ }
166
+ }
167
+ finally {
168
+ reader.releaseLock();
169
+ }
170
+ };
171
+ start().catch((err) => {
172
+ // Suppress AbortError when closing
173
+ if (!(err && err.name === 'AbortError')) {
174
+ if (options?.onError) {
175
+ options.onError(err);
176
+ }
177
+ }
178
+ closed = true;
179
+ controller?.abort();
180
+ });
181
+ return {
182
+ close: () => {
183
+ closed = true;
184
+ controller?.abort();
185
+ },
186
+ };
187
+ }
114
188
  formatPath(path) {
189
+ if (path === "/") {
190
+ return path;
191
+ }
115
192
  if (path.startsWith("/")) {
116
193
  path = path.slice(1);
117
194
  }
@@ -3,7 +3,18 @@ import { SandboxAction } from "./action.js";
3
3
  import { DeleteProcessByIdentifierKillResponse, DeleteProcessByIdentifierResponse, GetProcessByIdentifierResponse, GetProcessResponse, PostProcessResponse, ProcessRequest } from "./client/index.js";
4
4
  export declare class SandboxProcess extends SandboxAction {
5
5
  constructor(sandbox: Sandbox);
6
+ streamLogs(identifier: string, options: {
7
+ onLog?: (log: string) => void;
8
+ onStdout?: (stdout: string) => void;
9
+ onStderr?: (stderr: string) => void;
10
+ }): {
11
+ close: () => void;
12
+ };
6
13
  exec(process: ProcessRequest): Promise<PostProcessResponse>;
14
+ wait(identifier: string, { maxWait, interval }?: {
15
+ maxWait?: number;
16
+ interval?: number;
17
+ }): Promise<GetProcessByIdentifierResponse>;
7
18
  get(identifier: string): Promise<GetProcessByIdentifierResponse>;
8
19
  list(): Promise<GetProcessResponse>;
9
20
  stop(identifier: string): Promise<DeleteProcessByIdentifierResponse>;
@@ -1,24 +1,97 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SandboxProcess = void 0;
4
+ const settings_js_1 = require("../common/settings.js");
4
5
  const action_js_1 = require("./action.js");
5
6
  const index_js_1 = require("./client/index.js");
6
7
  class SandboxProcess extends action_js_1.SandboxAction {
7
8
  constructor(sandbox) {
8
9
  super(sandbox);
9
10
  }
11
+ streamLogs(identifier, options) {
12
+ const controller = new AbortController();
13
+ (async () => {
14
+ try {
15
+ const headers = this.sandbox.forceUrl ? this.sandbox.headers : settings_js_1.settings.headers;
16
+ const stream = await fetch(`${this.url}/process/${identifier}/logs/stream`, {
17
+ method: 'GET',
18
+ signal: controller.signal,
19
+ headers,
20
+ });
21
+ if (stream.status !== 200) {
22
+ throw new Error(`Failed to stream logs: ${await stream.text()}`);
23
+ }
24
+ if (!stream.body)
25
+ throw new Error('No stream body');
26
+ const reader = stream.body.getReader();
27
+ const decoder = new TextDecoder();
28
+ let buffer = '';
29
+ while (true) {
30
+ const { done, value } = await reader.read();
31
+ if (done)
32
+ break;
33
+ buffer += decoder.decode(value, { stream: true });
34
+ let lines = buffer.split(/\r?\n/);
35
+ buffer = lines.pop();
36
+ for (const line of lines) {
37
+ if (line.startsWith('stdout:')) {
38
+ options.onStdout?.(line.slice(7));
39
+ options.onLog?.(line.slice(7));
40
+ }
41
+ else if (line.startsWith('stderr:')) {
42
+ options.onStderr?.(line.slice(7));
43
+ options.onLog?.(line.slice(7));
44
+ }
45
+ else {
46
+ options.onLog?.(line);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ catch (err) {
52
+ if (err && err.name !== 'AbortError') {
53
+ console.error("Stream error:", err);
54
+ throw err;
55
+ }
56
+ }
57
+ })();
58
+ return {
59
+ close: () => controller.abort(),
60
+ };
61
+ }
10
62
  async exec(process) {
11
63
  const { response, data, error } = await (0, index_js_1.postProcess)({
12
64
  body: process,
13
65
  baseUrl: this.url,
66
+ client: this.client,
14
67
  });
15
68
  this.handleResponseError(response, data, error);
16
69
  return data;
17
70
  }
71
+ async wait(identifier, { maxWait = 60000, interval = 1000 } = {}) {
72
+ const startTime = Date.now();
73
+ let status = "running";
74
+ let data = await this.get(identifier);
75
+ while (status === "running") {
76
+ await new Promise((resolve) => setTimeout(resolve, interval));
77
+ try {
78
+ data = await this.get(identifier);
79
+ status = data.status ?? "running";
80
+ }
81
+ catch {
82
+ break;
83
+ }
84
+ if (Date.now() - startTime > maxWait) {
85
+ throw new Error("Process did not finish in time");
86
+ }
87
+ }
88
+ return data;
89
+ }
18
90
  async get(identifier) {
19
91
  const { response, data, error } = await (0, index_js_1.getProcessByIdentifier)({
20
92
  path: { identifier },
21
93
  baseUrl: this.url,
94
+ client: this.client,
22
95
  });
23
96
  this.handleResponseError(response, data, error);
24
97
  return data;
@@ -26,6 +99,7 @@ class SandboxProcess extends action_js_1.SandboxAction {
26
99
  async list() {
27
100
  const { response, data, error } = await (0, index_js_1.getProcess)({
28
101
  baseUrl: this.url,
102
+ client: this.client,
29
103
  });
30
104
  this.handleResponseError(response, data, error);
31
105
  return data;
@@ -34,6 +108,7 @@ class SandboxProcess extends action_js_1.SandboxAction {
34
108
  const { response, data, error } = await (0, index_js_1.deleteProcessByIdentifier)({
35
109
  path: { identifier },
36
110
  baseUrl: this.url,
111
+ client: this.client,
37
112
  });
38
113
  this.handleResponseError(response, data, error);
39
114
  return data;
@@ -42,6 +117,7 @@ class SandboxProcess extends action_js_1.SandboxAction {
42
117
  const { response, data, error } = await (0, index_js_1.deleteProcessByIdentifierKill)({
43
118
  path: { identifier },
44
119
  baseUrl: this.url,
120
+ client: this.client,
45
121
  });
46
122
  this.handleResponseError(response, data, error);
47
123
  return data;
@@ -50,6 +126,7 @@ class SandboxProcess extends action_js_1.SandboxAction {
50
126
  const { response, data, error } = await (0, index_js_1.getProcessByIdentifierLogs)({
51
127
  path: { identifier },
52
128
  baseUrl: this.url,
129
+ client: this.client,
53
130
  });
54
131
  this.handleResponseError(response, data, error);
55
132
  if (data && type in data) {
@@ -3,13 +3,16 @@ import { SandboxFileSystem } from "./filesystem.js";
3
3
  import { SandboxNetwork } from "./network.js";
4
4
  import { SandboxPreviews } from "./preview.js";
5
5
  import { SandboxProcess } from "./process.js";
6
+ import { SandboxSessions } from "./session.js";
7
+ import { SandboxConfiguration, SessionWithToken } from "./types.js";
6
8
  export declare class SandboxInstance {
7
9
  private sandbox;
8
10
  fs: SandboxFileSystem;
9
11
  network: SandboxNetwork;
10
12
  process: SandboxProcess;
11
13
  previews: SandboxPreviews;
12
- constructor(sandbox: SandboxModel);
14
+ sessions: SandboxSessions;
15
+ constructor(sandbox: SandboxConfiguration);
13
16
  get metadata(): import("../client/types.gen.js").Metadata | undefined;
14
17
  get status(): string | undefined;
15
18
  get events(): import("../client/types.gen.js").CoreEvents | undefined;
@@ -22,4 +25,5 @@ export declare class SandboxInstance {
22
25
  static get(sandboxName: string): Promise<SandboxInstance>;
23
26
  static list(): Promise<SandboxInstance[]>;
24
27
  static delete(sandboxName: string): Promise<SandboxModel>;
28
+ static fromSession(session: SessionWithToken): Promise<SandboxInstance>;
25
29
  }
@@ -7,18 +7,21 @@ const filesystem_js_1 = require("./filesystem.js");
7
7
  const network_js_1 = require("./network.js");
8
8
  const preview_js_1 = require("./preview.js");
9
9
  const process_js_1 = require("./process.js");
10
+ const session_js_1 = require("./session.js");
10
11
  class SandboxInstance {
11
12
  sandbox;
12
13
  fs;
13
14
  network;
14
15
  process;
15
16
  previews;
17
+ sessions;
16
18
  constructor(sandbox) {
17
19
  this.sandbox = sandbox;
18
20
  this.fs = new filesystem_js_1.SandboxFileSystem(sandbox);
19
21
  this.network = new network_js_1.SandboxNetwork(sandbox);
20
22
  this.process = new process_js_1.SandboxProcess(sandbox);
21
23
  this.previews = new preview_js_1.SandboxPreviews(sandbox);
24
+ this.sessions = new session_js_1.SandboxSessions(sandbox);
22
25
  }
23
26
  get metadata() {
24
27
  return this.sandbox.metadata;
@@ -91,5 +94,8 @@ class SandboxInstance {
91
94
  });
92
95
  return data;
93
96
  }
97
+ static async fromSession(session) {
98
+ return new SandboxInstance({ forceUrl: session.url, params: { bl_preview_token: session.token }, headers: { "X-Blaxel-Preview-Token": session.token } });
99
+ }
94
100
  }
95
101
  exports.SandboxInstance = SandboxInstance;
@@ -0,0 +1,21 @@
1
+ import { Sandbox } from "../client/index.js";
2
+ import { SessionCreateOptions, SessionWithToken } from "./types.js";
3
+ export declare class SandboxSessions {
4
+ private sandbox;
5
+ constructor(sandbox: Sandbox);
6
+ get sandboxName(): string;
7
+ create(options?: SessionCreateOptions): Promise<SessionWithToken>;
8
+ list(): Promise<{
9
+ name: string;
10
+ url: string;
11
+ token: string;
12
+ expiresAt: string | Date;
13
+ }[]>;
14
+ get(name: string): Promise<{
15
+ url: string;
16
+ token: string;
17
+ expiresAt: string | Date;
18
+ }>;
19
+ delete(name: string): Promise<import("../client/types.gen.js").Preview>;
20
+ getToken(previewName: string): Promise<import("../client/types.gen.js").PreviewToken | null>;
21
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SandboxSessions = void 0;
4
+ const index_js_1 = require("../client/index.js");
5
+ const preview_js_1 = require("./preview.js");
6
+ class SandboxSessions {
7
+ sandbox;
8
+ constructor(sandbox) {
9
+ this.sandbox = sandbox;
10
+ }
11
+ get sandboxName() {
12
+ return this.sandbox.metadata?.name ?? "";
13
+ }
14
+ async create(options = {}) {
15
+ const expiresAt = options.expiresAt ?? new Date(Date.now() + 24 * 60 * 60 * 1000); // 1 day from now
16
+ const body = {
17
+ metadata: {
18
+ name: "session-" + Date.now(),
19
+ },
20
+ spec: {
21
+ port: 443,
22
+ public: false,
23
+ },
24
+ };
25
+ const { data } = await (0, index_js_1.createSandboxPreview)({
26
+ path: {
27
+ sandboxName: this.sandboxName,
28
+ },
29
+ body,
30
+ throwOnError: true,
31
+ });
32
+ const preview = new preview_js_1.SandboxPreview(data);
33
+ // Create a token for the preview with the given expiresAt
34
+ const tokenObj = await preview.tokens.create(expiresAt);
35
+ return {
36
+ name: body.metadata.name,
37
+ url: preview.spec?.url ?? "",
38
+ token: tokenObj.value,
39
+ expiresAt: typeof tokenObj.expiresAt === 'string' ? new Date(tokenObj.expiresAt) : tokenObj.expiresAt,
40
+ };
41
+ }
42
+ async list() {
43
+ const { data } = await (0, index_js_1.listSandboxPreviews)({
44
+ path: {
45
+ sandboxName: this.sandboxName,
46
+ },
47
+ throwOnError: true,
48
+ });
49
+ return await Promise.all(data.filter((preview) => preview.metadata?.name?.includes("session-")).map(async (preview) => {
50
+ const token = await this.getToken(preview.metadata?.name ?? "");
51
+ return {
52
+ name: preview.metadata?.name ?? "",
53
+ url: preview.spec?.url ?? "",
54
+ token: token?.spec?.token ?? "",
55
+ expiresAt: token?.spec?.expiresAt ?? new Date(),
56
+ };
57
+ }));
58
+ }
59
+ async get(name) {
60
+ const { data } = await (0, index_js_1.getSandboxPreview)({
61
+ path: {
62
+ sandboxName: this.sandboxName,
63
+ previewName: name,
64
+ },
65
+ throwOnError: true,
66
+ });
67
+ const token = await this.getToken(name);
68
+ return {
69
+ url: data.spec?.url ?? "",
70
+ token: token?.spec?.token ?? "",
71
+ expiresAt: token?.spec?.expiresAt ?? new Date(),
72
+ };
73
+ }
74
+ async delete(name) {
75
+ const { data } = await (0, index_js_1.deleteSandboxPreview)({
76
+ path: {
77
+ sandboxName: this.sandboxName,
78
+ previewName: name,
79
+ },
80
+ throwOnError: true,
81
+ });
82
+ return data;
83
+ }
84
+ async getToken(previewName) {
85
+ const { data } = await (0, index_js_1.listSandboxPreviewTokens)({
86
+ path: {
87
+ sandboxName: this.sandboxName,
88
+ previewName,
89
+ },
90
+ throwOnError: true,
91
+ });
92
+ if (data.length === 0)
93
+ return null;
94
+ return data[0];
95
+ }
96
+ }
97
+ exports.SandboxSessions = SandboxSessions;
@@ -0,0 +1,15 @@
1
+ import { Sandbox } from "../client/types.gen";
2
+ export interface SessionCreateOptions {
3
+ expiresAt?: Date;
4
+ }
5
+ export interface SessionWithToken {
6
+ name: string;
7
+ url: string;
8
+ token: string;
9
+ expiresAt: Date;
10
+ }
11
+ export type SandboxConfiguration = {
12
+ forceUrl?: string;
13
+ headers?: Record<string, string>;
14
+ params?: Record<string, string>;
15
+ } & Sandbox;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -55,4 +55,5 @@ export declare const telemetryRegistry: TelemetryRegistry;
55
55
  * Create a span with the registered provider
56
56
  */
57
57
  export declare function startSpan(name: string, options?: BlaxelSpanOptions): BlaxelSpan;
58
+ export declare function withSpan<T>(name: string, fn: () => T, options?: BlaxelSpanOptions): T;
58
59
  export {};
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.telemetryRegistry = void 0;
5
5
  exports.startSpan = startSpan;
6
+ exports.withSpan = withSpan;
6
7
  /**
7
8
  * No-operation implementation of Span
8
9
  */
@@ -57,3 +58,16 @@ exports.telemetryRegistry = TelemetryRegistry.getInstance();
57
58
  function startSpan(name, options) {
58
59
  return exports.telemetryRegistry.getProvider().startSpan(name, options);
59
60
  }
61
+ function withSpan(name, fn, options) {
62
+ const span = startSpan(name, options);
63
+ try {
64
+ const result = fn();
65
+ span.end();
66
+ return result;
67
+ }
68
+ catch (error) {
69
+ span.recordException(error);
70
+ span.end();
71
+ throw error;
72
+ }
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blaxel/core",
3
- "version": "0.2.0-preview3",
3
+ "version": "0.2.0-preview5",
4
4
  "description": "Blaxel Core SDK for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Blaxel, INC (https://blaxel.ai)",
@@ -56,21 +56,25 @@
56
56
  "@hey-api/client-fetch": "^0.10.0",
57
57
  "@modelcontextprotocol/sdk": "^1.11.0",
58
58
  "crypto": "^1.0.1",
59
+ "dotenv": "^16.5.0",
59
60
  "jwt-decode": "^4.0.0",
60
61
  "toml": "^3.0.0",
61
62
  "uuid": "^11.1.0",
62
63
  "ws": "^8.18.2",
63
64
  "yaml": "^2.7.1",
65
+ "yargs": "^17.7.2",
64
66
  "zod": "^3.24.3"
65
67
  },
66
68
  "devDependencies": {
67
69
  "@eslint/js": "^9.26.0",
68
70
  "@types/ws": "^8.18.1",
71
+ "@types/yargs": "^17.0.33",
69
72
  "typescript": "^5.0.0",
70
73
  "typescript-eslint": "^8.31.1"
71
74
  },
72
75
  "scripts": {
73
76
  "lint": "eslint src/",
77
+ "dev": "tsc --watch",
74
78
  "build": "tsc"
75
79
  }
76
80
  }