@blaxel/core 0.2.57-preview.30 → 0.2.57-preview.33
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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/common/settings.js +2 -2
- package/dist/cjs/sandbox/client/sdk.gen.js +1 -1
- package/dist/cjs/sandbox/process/process.js +138 -28
- package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +1 -1
- package/dist/cjs/types/sandbox/client/types.gen.d.ts +2 -0
- package/dist/cjs/types/sandbox/process/process.d.ts +1 -0
- package/dist/cjs/types/sandbox/types.d.ts +2 -0
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/settings.js +2 -2
- package/dist/cjs-browser/sandbox/client/sdk.gen.js +1 -1
- package/dist/cjs-browser/sandbox/process/process.js +138 -28
- package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +1 -1
- package/dist/cjs-browser/types/sandbox/client/types.gen.d.ts +2 -0
- package/dist/cjs-browser/types/sandbox/process/process.d.ts +1 -0
- package/dist/cjs-browser/types/sandbox/types.d.ts +2 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/settings.js +2 -2
- package/dist/esm/sandbox/client/sdk.gen.js +1 -1
- package/dist/esm/sandbox/process/process.js +138 -28
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/settings.js +2 -2
- package/dist/esm-browser/sandbox/client/sdk.gen.js +1 -1
- package/dist/esm-browser/sandbox/process/process.js +138 -28
- package/package.json +1 -1
|
@@ -3,8 +3,8 @@ import { authentication } from "../authentication/index.js";
|
|
|
3
3
|
import { env } from "../common/env.js";
|
|
4
4
|
import { fs, os, path } from "../common/node.js";
|
|
5
5
|
// Build info - these placeholders are replaced at build time by build:replace-imports
|
|
6
|
-
const BUILD_VERSION = "0.2.57-preview.
|
|
7
|
-
const BUILD_COMMIT = "
|
|
6
|
+
const BUILD_VERSION = "0.2.57-preview.33";
|
|
7
|
+
const BUILD_COMMIT = "c169eb11d41a069351c8203a2aad841f8cdef220";
|
|
8
8
|
const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
|
|
9
9
|
// Cache for config.yaml tracking value
|
|
10
10
|
let configTrackingValue = null;
|
|
@@ -495,7 +495,7 @@ export const getProcess = (options) => {
|
|
|
495
495
|
};
|
|
496
496
|
/**
|
|
497
497
|
* Execute a command
|
|
498
|
-
* Execute a command and return process information
|
|
498
|
+
* Execute a command and return process information. If Accept header is text/event-stream, streams logs in SSE format and returns the process response as a final event.
|
|
499
499
|
*/
|
|
500
500
|
export const postProcess = (options) => {
|
|
501
501
|
return (options.client ?? _heyApiClient).post({
|
|
@@ -74,41 +74,36 @@ export class SandboxProcess extends SandboxAction {
|
|
|
74
74
|
}
|
|
75
75
|
async exec(process) {
|
|
76
76
|
let onLog;
|
|
77
|
+
let onStdout;
|
|
78
|
+
let onStderr;
|
|
77
79
|
if ('onLog' in process && process.onLog) {
|
|
78
80
|
onLog = process.onLog;
|
|
79
81
|
delete process.onLog;
|
|
80
82
|
}
|
|
83
|
+
if ('onStdout' in process && process.onStdout) {
|
|
84
|
+
onStdout = process.onStdout;
|
|
85
|
+
delete process.onStdout;
|
|
86
|
+
}
|
|
87
|
+
if ('onStderr' in process && process.onStderr) {
|
|
88
|
+
onStderr = process.onStderr;
|
|
89
|
+
delete process.onStderr;
|
|
90
|
+
}
|
|
81
91
|
// Store original wait_for_completion setting
|
|
82
92
|
const shouldWaitForCompletion = process.waitForCompletion;
|
|
83
|
-
//
|
|
84
|
-
if (shouldWaitForCompletion && onLog) {
|
|
85
|
-
process
|
|
86
|
-
}
|
|
87
|
-
const { response, data, error } = await postProcess({
|
|
88
|
-
body: process,
|
|
89
|
-
baseUrl: this.url,
|
|
90
|
-
client: this.client,
|
|
91
|
-
});
|
|
92
|
-
this.handleResponseError(response, data, error);
|
|
93
|
-
let result = data;
|
|
94
|
-
// Handle wait_for_completion with parallel log streaming
|
|
95
|
-
if (shouldWaitForCompletion && onLog) {
|
|
96
|
-
const streamControl = this.streamLogs(result.pid, { onLog });
|
|
97
|
-
try {
|
|
98
|
-
// Wait for process completion
|
|
99
|
-
result = await this.wait(result.pid, { interval: 500, maxWait: 1000 * 60 * 60 });
|
|
100
|
-
}
|
|
101
|
-
finally {
|
|
102
|
-
// Clean up log streaming
|
|
103
|
-
if (streamControl) {
|
|
104
|
-
streamControl.close();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
93
|
+
// When waiting for completion with streaming callbacks, use streaming endpoint
|
|
94
|
+
if (shouldWaitForCompletion && (onLog || onStdout || onStderr)) {
|
|
95
|
+
return await this.execWithStreaming(process, { onLog, onStdout, onStderr });
|
|
107
96
|
}
|
|
108
97
|
else {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
98
|
+
const { response, data, error } = await postProcess({
|
|
99
|
+
body: process,
|
|
100
|
+
baseUrl: this.url,
|
|
101
|
+
client: this.client,
|
|
102
|
+
});
|
|
103
|
+
this.handleResponseError(response, data, error);
|
|
104
|
+
const result = data;
|
|
105
|
+
if (onLog || onStdout || onStderr) {
|
|
106
|
+
const streamControl = this.streamLogs(result.pid, { onLog, onStdout, onStderr });
|
|
112
107
|
return {
|
|
113
108
|
...result,
|
|
114
109
|
close() {
|
|
@@ -118,8 +113,123 @@ export class SandboxProcess extends SandboxAction {
|
|
|
118
113
|
},
|
|
119
114
|
};
|
|
120
115
|
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async execWithStreaming(processRequest, options) {
|
|
120
|
+
const headers = this.sandbox.forceUrl ? this.sandbox.headers : settings.headers;
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
const response = await fetch(`${this.url}/process`, {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
signal: controller.signal,
|
|
125
|
+
headers: {
|
|
126
|
+
...headers,
|
|
127
|
+
'Content-Type': 'application/json',
|
|
128
|
+
'Accept': 'text/event-stream',
|
|
129
|
+
},
|
|
130
|
+
body: JSON.stringify(processRequest),
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
const errorText = await response.text();
|
|
134
|
+
throw new Error(`Failed to execute process: ${errorText}`);
|
|
121
135
|
}
|
|
122
|
-
|
|
136
|
+
const contentType = response.headers.get('Content-Type') || '';
|
|
137
|
+
const isStreaming = contentType.includes('application/x-ndjson');
|
|
138
|
+
// Fallback: server doesn't support streaming, use legacy approach
|
|
139
|
+
if (!isStreaming) {
|
|
140
|
+
const data = await response.json();
|
|
141
|
+
// If process already completed (server waited), just return with logs
|
|
142
|
+
if (data.status === 'completed' || data.status === 'failed') {
|
|
143
|
+
// Emit any captured logs through callbacks
|
|
144
|
+
if (data.stdout) {
|
|
145
|
+
for (const line of data.stdout.split('\n').filter(l => l)) {
|
|
146
|
+
options.onStdout?.(line);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (data.stderr) {
|
|
150
|
+
for (const line of data.stderr.split('\n').filter(l => l)) {
|
|
151
|
+
options.onStderr?.(line);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (data.logs) {
|
|
155
|
+
for (const line of data.logs.split('\n').filter(l => l)) {
|
|
156
|
+
options.onLog?.(line);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
...data,
|
|
161
|
+
close: () => { },
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
...data,
|
|
166
|
+
close: () => { },
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Streaming response handling
|
|
170
|
+
if (!response.body) {
|
|
171
|
+
throw new Error('No response body for streaming');
|
|
172
|
+
}
|
|
173
|
+
const reader = response.body.getReader();
|
|
174
|
+
const decoder = new TextDecoder();
|
|
175
|
+
let buffer = '';
|
|
176
|
+
let result = null;
|
|
177
|
+
while (true) {
|
|
178
|
+
const readResult = await reader.read();
|
|
179
|
+
if (readResult.done)
|
|
180
|
+
break;
|
|
181
|
+
if (readResult.value && readResult.value instanceof Uint8Array) {
|
|
182
|
+
buffer += decoder.decode(readResult.value, { stream: true });
|
|
183
|
+
}
|
|
184
|
+
const lines = buffer.split(/\r?\n/);
|
|
185
|
+
buffer = lines.pop();
|
|
186
|
+
for (const line of lines) {
|
|
187
|
+
const parsed = JSON.parse(line);
|
|
188
|
+
switch (parsed.type) {
|
|
189
|
+
case 'stdout':
|
|
190
|
+
if (parsed.data) {
|
|
191
|
+
options.onStdout?.(parsed.data);
|
|
192
|
+
options.onLog?.(parsed.data);
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
195
|
+
case 'stderr':
|
|
196
|
+
if (parsed.data) {
|
|
197
|
+
options.onStderr?.(parsed.data);
|
|
198
|
+
options.onLog?.(parsed.data);
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
case 'result':
|
|
202
|
+
try {
|
|
203
|
+
result = JSON.parse(parsed.data);
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
throw new Error(`Failed to parse result JSON: ${parsed.data}`);
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
default:
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Process any remaining buffer
|
|
215
|
+
if (buffer.trim()) {
|
|
216
|
+
if (buffer.startsWith('result:')) {
|
|
217
|
+
const jsonStr = buffer.slice(7);
|
|
218
|
+
try {
|
|
219
|
+
result = JSON.parse(jsonStr);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
throw new Error(`Failed to parse result JSON: ${jsonStr}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!result) {
|
|
227
|
+
throw new Error('No result received from streaming response');
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
...result,
|
|
231
|
+
close: () => controller.abort(),
|
|
232
|
+
};
|
|
123
233
|
}
|
|
124
234
|
async wait(identifier, { maxWait = 60000, interval = 1000 } = {}) {
|
|
125
235
|
const startTime = Date.now();
|