@cloudflare/sandbox 0.0.9 → 0.1.1
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/CHANGELOG.md +18 -0
- package/Dockerfile +1 -14
- package/container_src/handler/exec.ts +337 -0
- package/container_src/handler/file.ts +844 -0
- package/container_src/handler/git.ts +182 -0
- package/container_src/handler/ports.ts +314 -0
- package/container_src/handler/process.ts +640 -0
- package/container_src/index.ts +82 -2973
- package/container_src/types.ts +103 -0
- package/dist/chunk-6THNBO4S.js +46 -0
- package/dist/chunk-6THNBO4S.js.map +1 -0
- package/dist/chunk-6UAWTJ5S.js +85 -0
- package/dist/chunk-6UAWTJ5S.js.map +1 -0
- package/dist/chunk-G4XT4SP7.js +638 -0
- package/dist/chunk-G4XT4SP7.js.map +1 -0
- package/dist/chunk-ISFOIYQC.js +585 -0
- package/dist/chunk-ISFOIYQC.js.map +1 -0
- package/dist/chunk-NNGBXDMY.js +89 -0
- package/dist/chunk-NNGBXDMY.js.map +1 -0
- package/dist/client-Da-mLX4p.d.ts +210 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.js +3 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +13 -3
- package/dist/request-handler.d.ts +2 -1
- package/dist/request-handler.js +4 -2
- package/dist/sandbox.d.ts +2 -1
- package/dist/sandbox.js +4 -2
- package/dist/security.d.ts +30 -0
- package/dist/security.js +13 -0
- package/dist/security.js.map +1 -0
- package/dist/sse-parser.d.ts +28 -0
- package/dist/sse-parser.js +11 -0
- package/dist/sse-parser.js.map +1 -0
- package/dist/types.d.ts +284 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/package.json +2 -7
- package/src/client.ts +235 -1286
- package/src/index.ts +6 -0
- package/src/request-handler.ts +69 -20
- package/src/sandbox.ts +463 -70
- package/src/security.ts +113 -0
- package/src/sse-parser.ts +147 -0
- package/src/types.ts +386 -0
- package/tsconfig.json +1 -1
- package/README.md +0 -65
- package/dist/chunk-4J5LQCCN.js +0 -1446
- package/dist/chunk-4J5LQCCN.js.map +0 -1
- package/dist/chunk-5SZ3RVJZ.js +0 -250
- package/dist/chunk-5SZ3RVJZ.js.map +0 -1
- package/dist/client-BuVjqV00.d.ts +0 -247
- package/tests/client.example.ts +0 -308
- package/tests/connection-test.ts +0 -81
- package/tests/simple-test.ts +0 -81
- package/tests/test1.ts +0 -281
- package/tests/test2.ts +0 -929
package/src/client.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { Sandbox } from "./index";
|
|
2
|
+
import type {
|
|
3
|
+
GetProcessLogsResponse,
|
|
4
|
+
GetProcessResponse,
|
|
5
|
+
ListProcessesResponse,
|
|
6
|
+
StartProcessRequest,
|
|
7
|
+
StartProcessResponse
|
|
8
|
+
} from "./types";
|
|
2
9
|
|
|
3
10
|
interface ExecuteRequest {
|
|
4
11
|
command: string;
|
|
5
|
-
args?: string[];
|
|
6
12
|
sessionId?: string;
|
|
7
|
-
background?: boolean;
|
|
8
13
|
}
|
|
9
14
|
|
|
10
15
|
export interface ExecuteResponse {
|
|
@@ -13,7 +18,6 @@ export interface ExecuteResponse {
|
|
|
13
18
|
stderr: string;
|
|
14
19
|
exitCode: number;
|
|
15
20
|
command: string;
|
|
16
|
-
args: string[];
|
|
17
21
|
timestamp: string;
|
|
18
22
|
}
|
|
19
23
|
|
|
@@ -176,32 +180,11 @@ interface PingResponse {
|
|
|
176
180
|
timestamp: string;
|
|
177
181
|
}
|
|
178
182
|
|
|
179
|
-
interface StreamEvent {
|
|
180
|
-
type: "command_start" | "output" | "command_complete" | "error";
|
|
181
|
-
command?: string;
|
|
182
|
-
args?: string[];
|
|
183
|
-
stream?: "stdout" | "stderr";
|
|
184
|
-
data?: string;
|
|
185
|
-
message?: string;
|
|
186
|
-
path?: string;
|
|
187
|
-
oldPath?: string;
|
|
188
|
-
newPath?: string;
|
|
189
|
-
sourcePath?: string;
|
|
190
|
-
destinationPath?: string;
|
|
191
|
-
content?: string;
|
|
192
|
-
success?: boolean;
|
|
193
|
-
exitCode?: number;
|
|
194
|
-
stdout?: string;
|
|
195
|
-
stderr?: string;
|
|
196
|
-
error?: string;
|
|
197
|
-
timestamp?: string;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
183
|
interface HttpClientOptions {
|
|
201
184
|
stub?: Sandbox;
|
|
202
185
|
baseUrl?: string;
|
|
203
186
|
port?: number;
|
|
204
|
-
onCommandStart?: (command: string
|
|
187
|
+
onCommandStart?: (command: string) => void;
|
|
205
188
|
onOutput?: (
|
|
206
189
|
stream: "stdout" | "stderr",
|
|
207
190
|
data: string,
|
|
@@ -212,11 +195,9 @@ interface HttpClientOptions {
|
|
|
212
195
|
exitCode: number,
|
|
213
196
|
stdout: string,
|
|
214
197
|
stderr: string,
|
|
215
|
-
command: string
|
|
216
|
-
args: string[]
|
|
198
|
+
command: string
|
|
217
199
|
) => void;
|
|
218
|
-
onError?: (error: string, command?: string
|
|
219
|
-
onStreamEvent?: (event: StreamEvent) => void;
|
|
200
|
+
onError?: (error: string, command?: string) => void;
|
|
220
201
|
}
|
|
221
202
|
|
|
222
203
|
export class HttpClient {
|
|
@@ -271,117 +252,17 @@ export class HttpClient {
|
|
|
271
252
|
throw error;
|
|
272
253
|
}
|
|
273
254
|
}
|
|
274
|
-
// Public methods to set event handlers
|
|
275
|
-
setOnOutput(
|
|
276
|
-
handler: (
|
|
277
|
-
stream: "stdout" | "stderr",
|
|
278
|
-
data: string,
|
|
279
|
-
command: string
|
|
280
|
-
) => void
|
|
281
|
-
): void {
|
|
282
|
-
this.options.onOutput = handler;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
setOnCommandComplete(
|
|
286
|
-
handler: (
|
|
287
|
-
success: boolean,
|
|
288
|
-
exitCode: number,
|
|
289
|
-
stdout: string,
|
|
290
|
-
stderr: string,
|
|
291
|
-
command: string,
|
|
292
|
-
args: string[]
|
|
293
|
-
) => void
|
|
294
|
-
): void {
|
|
295
|
-
this.options.onCommandComplete = handler;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
setOnStreamEvent(handler: (event: StreamEvent) => void): void {
|
|
299
|
-
this.options.onStreamEvent = handler;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Public getter methods
|
|
303
|
-
getOnOutput():
|
|
304
|
-
| ((stream: "stdout" | "stderr", data: string, command: string) => void)
|
|
305
|
-
| undefined {
|
|
306
|
-
return this.options.onOutput;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
getOnCommandComplete():
|
|
310
|
-
| ((
|
|
311
|
-
success: boolean,
|
|
312
|
-
exitCode: number,
|
|
313
|
-
stdout: string,
|
|
314
|
-
stderr: string,
|
|
315
|
-
command: string,
|
|
316
|
-
args: string[]
|
|
317
|
-
) => void)
|
|
318
|
-
| undefined {
|
|
319
|
-
return this.options.onCommandComplete;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
getOnStreamEvent(): ((event: StreamEvent) => void) | undefined {
|
|
323
|
-
return this.options.onStreamEvent;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
async createSession(): Promise<string> {
|
|
327
|
-
try {
|
|
328
|
-
const response = await this.doFetch(`/api/session/create`, {
|
|
329
|
-
headers: {
|
|
330
|
-
"Content-Type": "application/json",
|
|
331
|
-
},
|
|
332
|
-
method: "POST",
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
if (!response.ok) {
|
|
336
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const data: SessionResponse = await response.json();
|
|
340
|
-
this.sessionId = data.sessionId;
|
|
341
|
-
console.log(`[HTTP Client] Created session: ${this.sessionId}`);
|
|
342
|
-
return this.sessionId;
|
|
343
|
-
} catch (error) {
|
|
344
|
-
console.error("[HTTP Client] Error creating session:", error);
|
|
345
|
-
throw error;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
async listSessions(): Promise<SessionListResponse> {
|
|
350
|
-
try {
|
|
351
|
-
const response = await this.doFetch(`/api/session/list`, {
|
|
352
|
-
headers: {
|
|
353
|
-
"Content-Type": "application/json",
|
|
354
|
-
},
|
|
355
|
-
method: "GET",
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
if (!response.ok) {
|
|
359
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
const data: SessionListResponse = await response.json();
|
|
363
|
-
console.log(`[HTTP Client] Listed ${data.count} sessions`);
|
|
364
|
-
return data;
|
|
365
|
-
} catch (error) {
|
|
366
|
-
console.error("[HTTP Client] Error listing sessions:", error);
|
|
367
|
-
throw error;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
255
|
|
|
371
256
|
async execute(
|
|
372
257
|
command: string,
|
|
373
|
-
|
|
374
|
-
sessionId?: string,
|
|
375
|
-
background: boolean = false,
|
|
258
|
+
sessionId?: string
|
|
376
259
|
): Promise<ExecuteResponse> {
|
|
377
260
|
try {
|
|
378
261
|
const targetSessionId = sessionId || this.sessionId;
|
|
379
262
|
|
|
380
263
|
const response = await this.doFetch(`/api/execute`, {
|
|
381
264
|
body: JSON.stringify({
|
|
382
|
-
args,
|
|
383
265
|
command,
|
|
384
|
-
background,
|
|
385
266
|
sessionId: targetSessionId,
|
|
386
267
|
} as ExecuteRequest),
|
|
387
268
|
headers: {
|
|
@@ -410,8 +291,7 @@ export class HttpClient {
|
|
|
410
291
|
data.exitCode,
|
|
411
292
|
data.stdout,
|
|
412
293
|
data.stderr,
|
|
413
|
-
data.command
|
|
414
|
-
data.args
|
|
294
|
+
data.command
|
|
415
295
|
);
|
|
416
296
|
|
|
417
297
|
return data;
|
|
@@ -419,31 +299,28 @@ export class HttpClient {
|
|
|
419
299
|
console.error("[HTTP Client] Error executing command:", error);
|
|
420
300
|
this.options.onError?.(
|
|
421
301
|
error instanceof Error ? error.message : "Unknown error",
|
|
422
|
-
command
|
|
423
|
-
args
|
|
302
|
+
command
|
|
424
303
|
);
|
|
425
304
|
throw error;
|
|
426
305
|
}
|
|
427
306
|
}
|
|
428
307
|
|
|
429
|
-
|
|
308
|
+
|
|
309
|
+
async executeCommandStream(
|
|
430
310
|
command: string,
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
background: boolean = false
|
|
434
|
-
): Promise<void> {
|
|
311
|
+
sessionId?: string
|
|
312
|
+
): Promise<ReadableStream<Uint8Array>> {
|
|
435
313
|
try {
|
|
436
314
|
const targetSessionId = sessionId || this.sessionId;
|
|
437
315
|
|
|
438
316
|
const response = await this.doFetch(`/api/execute/stream`, {
|
|
439
317
|
body: JSON.stringify({
|
|
440
|
-
args,
|
|
441
318
|
command,
|
|
442
|
-
background,
|
|
443
319
|
sessionId: targetSessionId,
|
|
444
320
|
}),
|
|
445
321
|
headers: {
|
|
446
322
|
"Content-Type": "application/json",
|
|
323
|
+
"Accept": "text/event-stream",
|
|
447
324
|
},
|
|
448
325
|
method: "POST",
|
|
449
326
|
});
|
|
@@ -461,94 +338,13 @@ export class HttpClient {
|
|
|
461
338
|
throw new Error("No response body for streaming request");
|
|
462
339
|
}
|
|
463
340
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
try {
|
|
468
|
-
while (true) {
|
|
469
|
-
const { done, value } = await reader.read();
|
|
470
|
-
|
|
471
|
-
if (done) {
|
|
472
|
-
break;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
476
|
-
const lines = chunk.split("\n");
|
|
477
|
-
|
|
478
|
-
for (const line of lines) {
|
|
479
|
-
if (line.startsWith("data: ")) {
|
|
480
|
-
try {
|
|
481
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
482
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
483
|
-
|
|
484
|
-
console.log(`[HTTP Client] Stream event: ${event.type}`);
|
|
485
|
-
this.options.onStreamEvent?.(event);
|
|
486
|
-
|
|
487
|
-
switch (event.type) {
|
|
488
|
-
case "command_start":
|
|
489
|
-
console.log(
|
|
490
|
-
`[HTTP Client] Command started: ${event.command
|
|
491
|
-
} ${event.args?.join(" ")}`
|
|
492
|
-
);
|
|
493
|
-
this.options.onCommandStart?.(
|
|
494
|
-
event.command!,
|
|
495
|
-
event.args || []
|
|
496
|
-
);
|
|
497
|
-
break;
|
|
498
|
-
|
|
499
|
-
case "output":
|
|
500
|
-
console.log(`[${event.stream}] ${event.data}`);
|
|
501
|
-
this.options.onOutput?.(
|
|
502
|
-
event.stream!,
|
|
503
|
-
event.data!,
|
|
504
|
-
event.command!
|
|
505
|
-
);
|
|
506
|
-
break;
|
|
507
|
-
|
|
508
|
-
case "command_complete":
|
|
509
|
-
console.log(
|
|
510
|
-
`[HTTP Client] Command completed: ${event.command}, Success: ${event.success}, Exit code: ${event.exitCode}`
|
|
511
|
-
);
|
|
512
|
-
this.options.onCommandComplete?.(
|
|
513
|
-
event.success!,
|
|
514
|
-
event.exitCode!,
|
|
515
|
-
event.stdout!,
|
|
516
|
-
event.stderr!,
|
|
517
|
-
event.command!,
|
|
518
|
-
event.args || []
|
|
519
|
-
);
|
|
520
|
-
break;
|
|
521
|
-
|
|
522
|
-
case "error":
|
|
523
|
-
console.error(
|
|
524
|
-
`[HTTP Client] Command error: ${event.error}`
|
|
525
|
-
);
|
|
526
|
-
this.options.onError?.(
|
|
527
|
-
event.error!,
|
|
528
|
-
event.command,
|
|
529
|
-
event.args
|
|
530
|
-
);
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
} catch (parseError) {
|
|
534
|
-
console.warn(
|
|
535
|
-
"[HTTP Client] Failed to parse stream event:",
|
|
536
|
-
parseError
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
} finally {
|
|
543
|
-
reader.releaseLock();
|
|
544
|
-
}
|
|
545
|
-
} catch (error) {
|
|
546
|
-
console.error("[HTTP Client] Error in streaming execution:", error);
|
|
547
|
-
this.options.onError?.(
|
|
548
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
549
|
-
command,
|
|
550
|
-
args
|
|
341
|
+
console.log(
|
|
342
|
+
`[HTTP Client] Started command stream: ${command}`
|
|
551
343
|
);
|
|
344
|
+
|
|
345
|
+
return response.body;
|
|
346
|
+
} catch (error) {
|
|
347
|
+
console.error("[HTTP Client] Error in command stream:", error);
|
|
552
348
|
throw error;
|
|
553
349
|
}
|
|
554
350
|
}
|
|
@@ -596,134 +392,6 @@ export class HttpClient {
|
|
|
596
392
|
}
|
|
597
393
|
}
|
|
598
394
|
|
|
599
|
-
async gitCheckoutStream(
|
|
600
|
-
repoUrl: string,
|
|
601
|
-
branch: string = "main",
|
|
602
|
-
targetDir?: string,
|
|
603
|
-
sessionId?: string
|
|
604
|
-
): Promise<void> {
|
|
605
|
-
try {
|
|
606
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
607
|
-
|
|
608
|
-
const response = await this.doFetch(`/api/git/checkout/stream`, {
|
|
609
|
-
body: JSON.stringify({
|
|
610
|
-
branch,
|
|
611
|
-
repoUrl,
|
|
612
|
-
sessionId: targetSessionId,
|
|
613
|
-
targetDir,
|
|
614
|
-
}),
|
|
615
|
-
headers: {
|
|
616
|
-
"Content-Type": "application/json",
|
|
617
|
-
},
|
|
618
|
-
method: "POST",
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
if (!response.ok) {
|
|
622
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
623
|
-
error?: string;
|
|
624
|
-
};
|
|
625
|
-
throw new Error(
|
|
626
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
627
|
-
);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
if (!response.body) {
|
|
631
|
-
throw new Error("No response body for streaming request");
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
const reader = response.body.getReader();
|
|
635
|
-
const decoder = new TextDecoder();
|
|
636
|
-
|
|
637
|
-
try {
|
|
638
|
-
while (true) {
|
|
639
|
-
const { done, value } = await reader.read();
|
|
640
|
-
|
|
641
|
-
if (done) {
|
|
642
|
-
break;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
646
|
-
const lines = chunk.split("\n");
|
|
647
|
-
|
|
648
|
-
for (const line of lines) {
|
|
649
|
-
if (line.startsWith("data: ")) {
|
|
650
|
-
try {
|
|
651
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
652
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
653
|
-
|
|
654
|
-
console.log(
|
|
655
|
-
`[HTTP Client] Git checkout stream event: ${event.type}`
|
|
656
|
-
);
|
|
657
|
-
this.options.onStreamEvent?.(event);
|
|
658
|
-
|
|
659
|
-
switch (event.type) {
|
|
660
|
-
case "command_start":
|
|
661
|
-
console.log(
|
|
662
|
-
`[HTTP Client] Git checkout started: ${event.command
|
|
663
|
-
} ${event.args?.join(" ")}`
|
|
664
|
-
);
|
|
665
|
-
this.options.onCommandStart?.(
|
|
666
|
-
event.command!,
|
|
667
|
-
event.args || []
|
|
668
|
-
);
|
|
669
|
-
break;
|
|
670
|
-
|
|
671
|
-
case "output":
|
|
672
|
-
console.log(`[${event.stream}] ${event.data}`);
|
|
673
|
-
this.options.onOutput?.(
|
|
674
|
-
event.stream!,
|
|
675
|
-
event.data!,
|
|
676
|
-
event.command!
|
|
677
|
-
);
|
|
678
|
-
break;
|
|
679
|
-
|
|
680
|
-
case "command_complete":
|
|
681
|
-
console.log(
|
|
682
|
-
`[HTTP Client] Git checkout completed: ${event.command}, Success: ${event.success}, Exit code: ${event.exitCode}`
|
|
683
|
-
);
|
|
684
|
-
this.options.onCommandComplete?.(
|
|
685
|
-
event.success!,
|
|
686
|
-
event.exitCode!,
|
|
687
|
-
event.stdout!,
|
|
688
|
-
event.stderr!,
|
|
689
|
-
event.command!,
|
|
690
|
-
event.args || []
|
|
691
|
-
);
|
|
692
|
-
break;
|
|
693
|
-
|
|
694
|
-
case "error":
|
|
695
|
-
console.error(
|
|
696
|
-
`[HTTP Client] Git checkout error: ${event.error}`
|
|
697
|
-
);
|
|
698
|
-
this.options.onError?.(
|
|
699
|
-
event.error!,
|
|
700
|
-
event.command,
|
|
701
|
-
event.args
|
|
702
|
-
);
|
|
703
|
-
break;
|
|
704
|
-
}
|
|
705
|
-
} catch (parseError) {
|
|
706
|
-
console.warn(
|
|
707
|
-
"[HTTP Client] Failed to parse git checkout stream event:",
|
|
708
|
-
parseError
|
|
709
|
-
);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
} finally {
|
|
715
|
-
reader.releaseLock();
|
|
716
|
-
}
|
|
717
|
-
} catch (error) {
|
|
718
|
-
console.error("[HTTP Client] Error in streaming git checkout:", error);
|
|
719
|
-
this.options.onError?.(
|
|
720
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
721
|
-
"git clone",
|
|
722
|
-
[branch, repoUrl, targetDir || ""]
|
|
723
|
-
);
|
|
724
|
-
throw error;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
395
|
|
|
728
396
|
async mkdir(
|
|
729
397
|
path: string,
|
|
@@ -766,128 +434,6 @@ export class HttpClient {
|
|
|
766
434
|
}
|
|
767
435
|
}
|
|
768
436
|
|
|
769
|
-
async mkdirStream(
|
|
770
|
-
path: string,
|
|
771
|
-
recursive: boolean = false,
|
|
772
|
-
sessionId?: string
|
|
773
|
-
): Promise<void> {
|
|
774
|
-
try {
|
|
775
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
776
|
-
|
|
777
|
-
const response = await this.doFetch(`/api/mkdir/stream`, {
|
|
778
|
-
body: JSON.stringify({
|
|
779
|
-
path,
|
|
780
|
-
recursive,
|
|
781
|
-
sessionId: targetSessionId,
|
|
782
|
-
} as MkdirRequest),
|
|
783
|
-
headers: {
|
|
784
|
-
"Content-Type": "application/json",
|
|
785
|
-
},
|
|
786
|
-
method: "POST",
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
if (!response.ok) {
|
|
790
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
791
|
-
error?: string;
|
|
792
|
-
};
|
|
793
|
-
throw new Error(
|
|
794
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
795
|
-
);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
if (!response.body) {
|
|
799
|
-
throw new Error("No response body for streaming request");
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
const reader = response.body.getReader();
|
|
803
|
-
const decoder = new TextDecoder();
|
|
804
|
-
|
|
805
|
-
try {
|
|
806
|
-
while (true) {
|
|
807
|
-
const { done, value } = await reader.read();
|
|
808
|
-
|
|
809
|
-
if (done) {
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
814
|
-
const lines = chunk.split("\n");
|
|
815
|
-
|
|
816
|
-
for (const line of lines) {
|
|
817
|
-
if (line.startsWith("data: ")) {
|
|
818
|
-
try {
|
|
819
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
820
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
821
|
-
|
|
822
|
-
console.log(`[HTTP Client] Mkdir stream event: ${event.type}`);
|
|
823
|
-
this.options.onStreamEvent?.(event);
|
|
824
|
-
|
|
825
|
-
switch (event.type) {
|
|
826
|
-
case "command_start":
|
|
827
|
-
console.log(
|
|
828
|
-
`[HTTP Client] Mkdir started: ${event.command
|
|
829
|
-
} ${event.args?.join(" ")}`
|
|
830
|
-
);
|
|
831
|
-
this.options.onCommandStart?.(
|
|
832
|
-
event.command!,
|
|
833
|
-
event.args || []
|
|
834
|
-
);
|
|
835
|
-
break;
|
|
836
|
-
|
|
837
|
-
case "output":
|
|
838
|
-
console.log(`[${event.stream}] ${event.data}`);
|
|
839
|
-
this.options.onOutput?.(
|
|
840
|
-
event.stream!,
|
|
841
|
-
event.data!,
|
|
842
|
-
event.command!
|
|
843
|
-
);
|
|
844
|
-
break;
|
|
845
|
-
|
|
846
|
-
case "command_complete":
|
|
847
|
-
console.log(
|
|
848
|
-
`[HTTP Client] Mkdir completed: ${event.command}, Success: ${event.success}, Exit code: ${event.exitCode}`
|
|
849
|
-
);
|
|
850
|
-
this.options.onCommandComplete?.(
|
|
851
|
-
event.success!,
|
|
852
|
-
event.exitCode!,
|
|
853
|
-
event.stdout!,
|
|
854
|
-
event.stderr!,
|
|
855
|
-
event.command!,
|
|
856
|
-
event.args || []
|
|
857
|
-
);
|
|
858
|
-
break;
|
|
859
|
-
|
|
860
|
-
case "error":
|
|
861
|
-
console.error(`[HTTP Client] Mkdir error: ${event.error}`);
|
|
862
|
-
this.options.onError?.(
|
|
863
|
-
event.error!,
|
|
864
|
-
event.command,
|
|
865
|
-
event.args
|
|
866
|
-
);
|
|
867
|
-
break;
|
|
868
|
-
}
|
|
869
|
-
} catch (parseError) {
|
|
870
|
-
console.warn(
|
|
871
|
-
"[HTTP Client] Failed to parse mkdir stream event:",
|
|
872
|
-
parseError
|
|
873
|
-
);
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
} finally {
|
|
879
|
-
reader.releaseLock();
|
|
880
|
-
}
|
|
881
|
-
} catch (error) {
|
|
882
|
-
console.error("[HTTP Client] Error in streaming mkdir:", error);
|
|
883
|
-
this.options.onError?.(
|
|
884
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
885
|
-
"mkdir",
|
|
886
|
-
recursive ? ["-p", path] : [path]
|
|
887
|
-
);
|
|
888
|
-
throw error;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
437
|
|
|
892
438
|
async writeFile(
|
|
893
439
|
path: string,
|
|
@@ -932,130 +478,6 @@ export class HttpClient {
|
|
|
932
478
|
}
|
|
933
479
|
}
|
|
934
480
|
|
|
935
|
-
async writeFileStream(
|
|
936
|
-
path: string,
|
|
937
|
-
content: string,
|
|
938
|
-
encoding: string = "utf-8",
|
|
939
|
-
sessionId?: string
|
|
940
|
-
): Promise<void> {
|
|
941
|
-
try {
|
|
942
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
943
|
-
|
|
944
|
-
const response = await this.doFetch(`/api/write/stream`, {
|
|
945
|
-
body: JSON.stringify({
|
|
946
|
-
content,
|
|
947
|
-
encoding,
|
|
948
|
-
path,
|
|
949
|
-
sessionId: targetSessionId,
|
|
950
|
-
} as WriteFileRequest),
|
|
951
|
-
headers: {
|
|
952
|
-
"Content-Type": "application/json",
|
|
953
|
-
},
|
|
954
|
-
method: "POST",
|
|
955
|
-
});
|
|
956
|
-
|
|
957
|
-
if (!response.ok) {
|
|
958
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
959
|
-
error?: string;
|
|
960
|
-
};
|
|
961
|
-
throw new Error(
|
|
962
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
963
|
-
);
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
if (!response.body) {
|
|
967
|
-
throw new Error("No response body for streaming request");
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
const reader = response.body.getReader();
|
|
971
|
-
const decoder = new TextDecoder();
|
|
972
|
-
|
|
973
|
-
try {
|
|
974
|
-
while (true) {
|
|
975
|
-
const { done, value } = await reader.read();
|
|
976
|
-
|
|
977
|
-
if (done) {
|
|
978
|
-
break;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
982
|
-
const lines = chunk.split("\n");
|
|
983
|
-
|
|
984
|
-
for (const line of lines) {
|
|
985
|
-
if (line.startsWith("data: ")) {
|
|
986
|
-
try {
|
|
987
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
988
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
989
|
-
|
|
990
|
-
console.log(
|
|
991
|
-
`[HTTP Client] Write file stream event: ${event.type}`
|
|
992
|
-
);
|
|
993
|
-
this.options.onStreamEvent?.(event);
|
|
994
|
-
|
|
995
|
-
switch (event.type) {
|
|
996
|
-
case "command_start":
|
|
997
|
-
console.log(
|
|
998
|
-
`[HTTP Client] Write file started: ${event.path}`
|
|
999
|
-
);
|
|
1000
|
-
this.options.onCommandStart?.("write", [
|
|
1001
|
-
path,
|
|
1002
|
-
content,
|
|
1003
|
-
encoding,
|
|
1004
|
-
]);
|
|
1005
|
-
break;
|
|
1006
|
-
|
|
1007
|
-
case "output":
|
|
1008
|
-
console.log(`[output] ${event.message}`);
|
|
1009
|
-
this.options.onOutput?.("stdout", event.message!, "write");
|
|
1010
|
-
break;
|
|
1011
|
-
|
|
1012
|
-
case "command_complete":
|
|
1013
|
-
console.log(
|
|
1014
|
-
`[HTTP Client] Write file completed: ${event.path}, Success: ${event.success}`
|
|
1015
|
-
);
|
|
1016
|
-
this.options.onCommandComplete?.(
|
|
1017
|
-
event.success!,
|
|
1018
|
-
0,
|
|
1019
|
-
"",
|
|
1020
|
-
"",
|
|
1021
|
-
"write",
|
|
1022
|
-
[path, content, encoding]
|
|
1023
|
-
);
|
|
1024
|
-
break;
|
|
1025
|
-
|
|
1026
|
-
case "error":
|
|
1027
|
-
console.error(
|
|
1028
|
-
`[HTTP Client] Write file error: ${event.error}`
|
|
1029
|
-
);
|
|
1030
|
-
this.options.onError?.(event.error!, "write", [
|
|
1031
|
-
path,
|
|
1032
|
-
content,
|
|
1033
|
-
encoding,
|
|
1034
|
-
]);
|
|
1035
|
-
break;
|
|
1036
|
-
}
|
|
1037
|
-
} catch (parseError) {
|
|
1038
|
-
console.warn(
|
|
1039
|
-
"[HTTP Client] Failed to parse write file stream event:",
|
|
1040
|
-
parseError
|
|
1041
|
-
);
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
} finally {
|
|
1047
|
-
reader.releaseLock();
|
|
1048
|
-
}
|
|
1049
|
-
} catch (error) {
|
|
1050
|
-
console.error("[HTTP Client] Error in streaming write file:", error);
|
|
1051
|
-
this.options.onError?.(
|
|
1052
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
1053
|
-
"write",
|
|
1054
|
-
[path, content, encoding]
|
|
1055
|
-
);
|
|
1056
|
-
throw error;
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
481
|
|
|
1060
482
|
async readFile(
|
|
1061
483
|
path: string,
|
|
@@ -1098,120 +520,6 @@ export class HttpClient {
|
|
|
1098
520
|
}
|
|
1099
521
|
}
|
|
1100
522
|
|
|
1101
|
-
async readFileStream(
|
|
1102
|
-
path: string,
|
|
1103
|
-
encoding: string = "utf-8",
|
|
1104
|
-
sessionId?: string
|
|
1105
|
-
): Promise<void> {
|
|
1106
|
-
try {
|
|
1107
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
1108
|
-
|
|
1109
|
-
const response = await this.doFetch(`/api/read/stream`, {
|
|
1110
|
-
body: JSON.stringify({
|
|
1111
|
-
encoding,
|
|
1112
|
-
path,
|
|
1113
|
-
sessionId: targetSessionId,
|
|
1114
|
-
} as ReadFileRequest),
|
|
1115
|
-
headers: {
|
|
1116
|
-
"Content-Type": "application/json",
|
|
1117
|
-
},
|
|
1118
|
-
method: "POST",
|
|
1119
|
-
});
|
|
1120
|
-
|
|
1121
|
-
if (!response.ok) {
|
|
1122
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
1123
|
-
error?: string;
|
|
1124
|
-
};
|
|
1125
|
-
throw new Error(
|
|
1126
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
1127
|
-
);
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
if (!response.body) {
|
|
1131
|
-
throw new Error("No response body for streaming request");
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
const reader = response.body.getReader();
|
|
1135
|
-
const decoder = new TextDecoder();
|
|
1136
|
-
|
|
1137
|
-
try {
|
|
1138
|
-
while (true) {
|
|
1139
|
-
const { done, value } = await reader.read();
|
|
1140
|
-
|
|
1141
|
-
if (done) {
|
|
1142
|
-
break;
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
1146
|
-
const lines = chunk.split("\n");
|
|
1147
|
-
|
|
1148
|
-
for (const line of lines) {
|
|
1149
|
-
if (line.startsWith("data: ")) {
|
|
1150
|
-
try {
|
|
1151
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
1152
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
1153
|
-
|
|
1154
|
-
console.log(
|
|
1155
|
-
`[HTTP Client] Read file stream event: ${event.type}`
|
|
1156
|
-
);
|
|
1157
|
-
this.options.onStreamEvent?.(event);
|
|
1158
|
-
|
|
1159
|
-
switch (event.type) {
|
|
1160
|
-
case "command_start":
|
|
1161
|
-
console.log(
|
|
1162
|
-
`[HTTP Client] Read file started: ${event.path}`
|
|
1163
|
-
);
|
|
1164
|
-
this.options.onCommandStart?.("read", [path, encoding]);
|
|
1165
|
-
break;
|
|
1166
|
-
|
|
1167
|
-
case "command_complete":
|
|
1168
|
-
console.log(
|
|
1169
|
-
`[HTTP Client] Read file completed: ${event.path
|
|
1170
|
-
}, Success: ${event.success}, Content length: ${event.content?.length || 0
|
|
1171
|
-
}`
|
|
1172
|
-
);
|
|
1173
|
-
this.options.onCommandComplete?.(
|
|
1174
|
-
event.success!,
|
|
1175
|
-
0,
|
|
1176
|
-
event.content || "",
|
|
1177
|
-
"",
|
|
1178
|
-
"read",
|
|
1179
|
-
[path, encoding]
|
|
1180
|
-
);
|
|
1181
|
-
break;
|
|
1182
|
-
|
|
1183
|
-
case "error":
|
|
1184
|
-
console.error(
|
|
1185
|
-
`[HTTP Client] Read file error: ${event.error}`
|
|
1186
|
-
);
|
|
1187
|
-
this.options.onError?.(event.error!, "read", [
|
|
1188
|
-
path,
|
|
1189
|
-
encoding,
|
|
1190
|
-
]);
|
|
1191
|
-
break;
|
|
1192
|
-
}
|
|
1193
|
-
} catch (parseError) {
|
|
1194
|
-
console.warn(
|
|
1195
|
-
"[HTTP Client] Failed to parse read file stream event:",
|
|
1196
|
-
parseError
|
|
1197
|
-
);
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
} finally {
|
|
1203
|
-
reader.releaseLock();
|
|
1204
|
-
}
|
|
1205
|
-
} catch (error) {
|
|
1206
|
-
console.error("[HTTP Client] Error in streaming read file:", error);
|
|
1207
|
-
this.options.onError?.(
|
|
1208
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
1209
|
-
"read",
|
|
1210
|
-
[path, encoding]
|
|
1211
|
-
);
|
|
1212
|
-
throw error;
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
523
|
|
|
1216
524
|
async deleteFile(
|
|
1217
525
|
path: string,
|
|
@@ -1252,110 +560,6 @@ export class HttpClient {
|
|
|
1252
560
|
}
|
|
1253
561
|
}
|
|
1254
562
|
|
|
1255
|
-
async deleteFileStream(path: string, sessionId?: string): Promise<void> {
|
|
1256
|
-
try {
|
|
1257
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
1258
|
-
|
|
1259
|
-
const response = await this.doFetch(`/api/delete/stream`, {
|
|
1260
|
-
body: JSON.stringify({
|
|
1261
|
-
path,
|
|
1262
|
-
sessionId: targetSessionId,
|
|
1263
|
-
} as DeleteFileRequest),
|
|
1264
|
-
headers: {
|
|
1265
|
-
"Content-Type": "application/json",
|
|
1266
|
-
},
|
|
1267
|
-
method: "POST",
|
|
1268
|
-
});
|
|
1269
|
-
|
|
1270
|
-
if (!response.ok) {
|
|
1271
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
1272
|
-
error?: string;
|
|
1273
|
-
};
|
|
1274
|
-
throw new Error(
|
|
1275
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
1276
|
-
);
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
if (!response.body) {
|
|
1280
|
-
throw new Error("No response body for streaming request");
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
const reader = response.body.getReader();
|
|
1284
|
-
const decoder = new TextDecoder();
|
|
1285
|
-
|
|
1286
|
-
try {
|
|
1287
|
-
while (true) {
|
|
1288
|
-
const { done, value } = await reader.read();
|
|
1289
|
-
|
|
1290
|
-
if (done) {
|
|
1291
|
-
break;
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
1295
|
-
const lines = chunk.split("\n");
|
|
1296
|
-
|
|
1297
|
-
for (const line of lines) {
|
|
1298
|
-
if (line.startsWith("data: ")) {
|
|
1299
|
-
try {
|
|
1300
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
1301
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
1302
|
-
|
|
1303
|
-
console.log(
|
|
1304
|
-
`[HTTP Client] Delete file stream event: ${event.type}`
|
|
1305
|
-
);
|
|
1306
|
-
this.options.onStreamEvent?.(event);
|
|
1307
|
-
|
|
1308
|
-
switch (event.type) {
|
|
1309
|
-
case "command_start":
|
|
1310
|
-
console.log(
|
|
1311
|
-
`[HTTP Client] Delete file started: ${event.path}`
|
|
1312
|
-
);
|
|
1313
|
-
this.options.onCommandStart?.("delete", [path]);
|
|
1314
|
-
break;
|
|
1315
|
-
|
|
1316
|
-
case "command_complete":
|
|
1317
|
-
console.log(
|
|
1318
|
-
`[HTTP Client] Delete file completed: ${event.path}, Success: ${event.success}`
|
|
1319
|
-
);
|
|
1320
|
-
this.options.onCommandComplete?.(
|
|
1321
|
-
event.success!,
|
|
1322
|
-
0,
|
|
1323
|
-
"",
|
|
1324
|
-
"",
|
|
1325
|
-
"delete",
|
|
1326
|
-
[path]
|
|
1327
|
-
);
|
|
1328
|
-
break;
|
|
1329
|
-
|
|
1330
|
-
case "error":
|
|
1331
|
-
console.error(
|
|
1332
|
-
`[HTTP Client] Delete file error: ${event.error}`
|
|
1333
|
-
);
|
|
1334
|
-
this.options.onError?.(event.error!, "delete", [path]);
|
|
1335
|
-
break;
|
|
1336
|
-
}
|
|
1337
|
-
} catch (parseError) {
|
|
1338
|
-
console.warn(
|
|
1339
|
-
"[HTTP Client] Failed to parse delete file stream event:",
|
|
1340
|
-
parseError
|
|
1341
|
-
);
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
} finally {
|
|
1347
|
-
reader.releaseLock();
|
|
1348
|
-
}
|
|
1349
|
-
} catch (error) {
|
|
1350
|
-
console.error("[HTTP Client] Error in streaming delete file:", error);
|
|
1351
|
-
this.options.onError?.(
|
|
1352
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
1353
|
-
"delete",
|
|
1354
|
-
[path]
|
|
1355
|
-
);
|
|
1356
|
-
throw error;
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
563
|
|
|
1360
564
|
async renameFile(
|
|
1361
565
|
oldPath: string,
|
|
@@ -1398,118 +602,6 @@ export class HttpClient {
|
|
|
1398
602
|
}
|
|
1399
603
|
}
|
|
1400
604
|
|
|
1401
|
-
async renameFileStream(
|
|
1402
|
-
oldPath: string,
|
|
1403
|
-
newPath: string,
|
|
1404
|
-
sessionId?: string
|
|
1405
|
-
): Promise<void> {
|
|
1406
|
-
try {
|
|
1407
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
1408
|
-
|
|
1409
|
-
const response = await this.doFetch(`/api/rename/stream`, {
|
|
1410
|
-
body: JSON.stringify({
|
|
1411
|
-
newPath,
|
|
1412
|
-
oldPath,
|
|
1413
|
-
sessionId: targetSessionId,
|
|
1414
|
-
} as RenameFileRequest),
|
|
1415
|
-
headers: {
|
|
1416
|
-
"Content-Type": "application/json",
|
|
1417
|
-
},
|
|
1418
|
-
method: "POST",
|
|
1419
|
-
});
|
|
1420
|
-
|
|
1421
|
-
if (!response.ok) {
|
|
1422
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
1423
|
-
error?: string;
|
|
1424
|
-
};
|
|
1425
|
-
throw new Error(
|
|
1426
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
1427
|
-
);
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
if (!response.body) {
|
|
1431
|
-
throw new Error("No response body for streaming request");
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
const reader = response.body.getReader();
|
|
1435
|
-
const decoder = new TextDecoder();
|
|
1436
|
-
|
|
1437
|
-
try {
|
|
1438
|
-
while (true) {
|
|
1439
|
-
const { done, value } = await reader.read();
|
|
1440
|
-
|
|
1441
|
-
if (done) {
|
|
1442
|
-
break;
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
1446
|
-
const lines = chunk.split("\n");
|
|
1447
|
-
|
|
1448
|
-
for (const line of lines) {
|
|
1449
|
-
if (line.startsWith("data: ")) {
|
|
1450
|
-
try {
|
|
1451
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
1452
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
1453
|
-
|
|
1454
|
-
console.log(
|
|
1455
|
-
`[HTTP Client] Rename file stream event: ${event.type}`
|
|
1456
|
-
);
|
|
1457
|
-
this.options.onStreamEvent?.(event);
|
|
1458
|
-
|
|
1459
|
-
switch (event.type) {
|
|
1460
|
-
case "command_start":
|
|
1461
|
-
console.log(
|
|
1462
|
-
`[HTTP Client] Rename file started: ${event.oldPath} -> ${event.newPath}`
|
|
1463
|
-
);
|
|
1464
|
-
this.options.onCommandStart?.("rename", [oldPath, newPath]);
|
|
1465
|
-
break;
|
|
1466
|
-
|
|
1467
|
-
case "command_complete":
|
|
1468
|
-
console.log(
|
|
1469
|
-
`[HTTP Client] Rename file completed: ${event.oldPath} -> ${event.newPath}, Success: ${event.success}`
|
|
1470
|
-
);
|
|
1471
|
-
this.options.onCommandComplete?.(
|
|
1472
|
-
event.success!,
|
|
1473
|
-
0,
|
|
1474
|
-
"",
|
|
1475
|
-
"",
|
|
1476
|
-
"rename",
|
|
1477
|
-
[oldPath, newPath]
|
|
1478
|
-
);
|
|
1479
|
-
break;
|
|
1480
|
-
|
|
1481
|
-
case "error":
|
|
1482
|
-
console.error(
|
|
1483
|
-
`[HTTP Client] Rename file error: ${event.error}`
|
|
1484
|
-
);
|
|
1485
|
-
this.options.onError?.(event.error!, "rename", [
|
|
1486
|
-
oldPath,
|
|
1487
|
-
newPath,
|
|
1488
|
-
]);
|
|
1489
|
-
break;
|
|
1490
|
-
}
|
|
1491
|
-
} catch (parseError) {
|
|
1492
|
-
console.warn(
|
|
1493
|
-
"[HTTP Client] Failed to parse rename file stream event:",
|
|
1494
|
-
parseError
|
|
1495
|
-
);
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
} finally {
|
|
1501
|
-
reader.releaseLock();
|
|
1502
|
-
}
|
|
1503
|
-
} catch (error) {
|
|
1504
|
-
console.error("[HTTP Client] Error in streaming rename file:", error);
|
|
1505
|
-
this.options.onError?.(
|
|
1506
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
1507
|
-
"rename",
|
|
1508
|
-
[oldPath, newPath]
|
|
1509
|
-
);
|
|
1510
|
-
throw error;
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
605
|
|
|
1514
606
|
async moveFile(
|
|
1515
607
|
sourcePath: string,
|
|
@@ -1552,121 +644,6 @@ export class HttpClient {
|
|
|
1552
644
|
}
|
|
1553
645
|
}
|
|
1554
646
|
|
|
1555
|
-
async moveFileStream(
|
|
1556
|
-
sourcePath: string,
|
|
1557
|
-
destinationPath: string,
|
|
1558
|
-
sessionId?: string
|
|
1559
|
-
): Promise<void> {
|
|
1560
|
-
try {
|
|
1561
|
-
const targetSessionId = sessionId || this.sessionId;
|
|
1562
|
-
|
|
1563
|
-
const response = await this.doFetch(`/api/move/stream`, {
|
|
1564
|
-
body: JSON.stringify({
|
|
1565
|
-
destinationPath,
|
|
1566
|
-
sessionId: targetSessionId,
|
|
1567
|
-
sourcePath,
|
|
1568
|
-
} as MoveFileRequest),
|
|
1569
|
-
headers: {
|
|
1570
|
-
"Content-Type": "application/json",
|
|
1571
|
-
},
|
|
1572
|
-
method: "POST",
|
|
1573
|
-
});
|
|
1574
|
-
|
|
1575
|
-
if (!response.ok) {
|
|
1576
|
-
const errorData = (await response.json().catch(() => ({}))) as {
|
|
1577
|
-
error?: string;
|
|
1578
|
-
};
|
|
1579
|
-
throw new Error(
|
|
1580
|
-
errorData.error || `HTTP error! status: ${response.status}`
|
|
1581
|
-
);
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1584
|
-
if (!response.body) {
|
|
1585
|
-
throw new Error("No response body for streaming request");
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
const reader = response.body.getReader();
|
|
1589
|
-
const decoder = new TextDecoder();
|
|
1590
|
-
|
|
1591
|
-
try {
|
|
1592
|
-
while (true) {
|
|
1593
|
-
const { done, value } = await reader.read();
|
|
1594
|
-
|
|
1595
|
-
if (done) {
|
|
1596
|
-
break;
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
1600
|
-
const lines = chunk.split("\n");
|
|
1601
|
-
|
|
1602
|
-
for (const line of lines) {
|
|
1603
|
-
if (line.startsWith("data: ")) {
|
|
1604
|
-
try {
|
|
1605
|
-
const eventData = line.slice(6); // Remove 'data: ' prefix
|
|
1606
|
-
const event: StreamEvent = JSON.parse(eventData);
|
|
1607
|
-
|
|
1608
|
-
console.log(
|
|
1609
|
-
`[HTTP Client] Move file stream event: ${event.type}`
|
|
1610
|
-
);
|
|
1611
|
-
this.options.onStreamEvent?.(event);
|
|
1612
|
-
|
|
1613
|
-
switch (event.type) {
|
|
1614
|
-
case "command_start":
|
|
1615
|
-
console.log(
|
|
1616
|
-
`[HTTP Client] Move file started: ${event.sourcePath} -> ${event.destinationPath}`
|
|
1617
|
-
);
|
|
1618
|
-
this.options.onCommandStart?.("move", [
|
|
1619
|
-
sourcePath,
|
|
1620
|
-
destinationPath,
|
|
1621
|
-
]);
|
|
1622
|
-
break;
|
|
1623
|
-
|
|
1624
|
-
case "command_complete":
|
|
1625
|
-
console.log(
|
|
1626
|
-
`[HTTP Client] Move file completed: ${event.sourcePath} -> ${event.destinationPath}, Success: ${event.success}`
|
|
1627
|
-
);
|
|
1628
|
-
this.options.onCommandComplete?.(
|
|
1629
|
-
event.success!,
|
|
1630
|
-
0,
|
|
1631
|
-
"",
|
|
1632
|
-
"",
|
|
1633
|
-
"move",
|
|
1634
|
-
[sourcePath, destinationPath]
|
|
1635
|
-
);
|
|
1636
|
-
break;
|
|
1637
|
-
|
|
1638
|
-
case "error":
|
|
1639
|
-
console.error(
|
|
1640
|
-
`[HTTP Client] Move file error: ${event.error}`
|
|
1641
|
-
);
|
|
1642
|
-
this.options.onError?.(event.error!, "move", [
|
|
1643
|
-
sourcePath,
|
|
1644
|
-
destinationPath,
|
|
1645
|
-
]);
|
|
1646
|
-
break;
|
|
1647
|
-
}
|
|
1648
|
-
} catch (parseError) {
|
|
1649
|
-
console.warn(
|
|
1650
|
-
"[HTTP Client] Failed to parse move file stream event:",
|
|
1651
|
-
parseError
|
|
1652
|
-
);
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
} finally {
|
|
1658
|
-
reader.releaseLock();
|
|
1659
|
-
}
|
|
1660
|
-
} catch (error) {
|
|
1661
|
-
console.error("[HTTP Client] Error in streaming move file:", error);
|
|
1662
|
-
this.options.onError?.(
|
|
1663
|
-
error instanceof Error ? error.message : "Unknown error",
|
|
1664
|
-
"move",
|
|
1665
|
-
[sourcePath, destinationPath]
|
|
1666
|
-
);
|
|
1667
|
-
throw error;
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
647
|
|
|
1671
648
|
async exposePort(port: number, name?: string): Promise<ExposePortResponse> {
|
|
1672
649
|
try {
|
|
@@ -1823,267 +800,239 @@ export class HttpClient {
|
|
|
1823
800
|
clearSession(): void {
|
|
1824
801
|
this.sessionId = null;
|
|
1825
802
|
}
|
|
1826
|
-
}
|
|
1827
803
|
|
|
1828
|
-
//
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
804
|
+
// Process management methods
|
|
805
|
+
async startProcess(
|
|
806
|
+
command: string,
|
|
807
|
+
options?: {
|
|
808
|
+
processId?: string;
|
|
809
|
+
sessionId?: string;
|
|
810
|
+
timeout?: number;
|
|
811
|
+
env?: Record<string, string>;
|
|
812
|
+
cwd?: string;
|
|
813
|
+
encoding?: string;
|
|
814
|
+
autoCleanup?: boolean;
|
|
815
|
+
}
|
|
816
|
+
): Promise<StartProcessResponse> {
|
|
817
|
+
try {
|
|
818
|
+
const targetSessionId = options?.sessionId || this.sessionId;
|
|
1832
819
|
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
820
|
+
const response = await this.doFetch("/api/process/start", {
|
|
821
|
+
body: JSON.stringify({
|
|
822
|
+
command,
|
|
823
|
+
options: {
|
|
824
|
+
...options,
|
|
825
|
+
sessionId: targetSessionId,
|
|
826
|
+
},
|
|
827
|
+
} as StartProcessRequest),
|
|
828
|
+
headers: {
|
|
829
|
+
"Content-Type": "application/json",
|
|
830
|
+
},
|
|
831
|
+
method: "POST",
|
|
832
|
+
});
|
|
1848
833
|
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
try {
|
|
1859
|
-
await client.executeStream(command, args);
|
|
1860
|
-
} finally {
|
|
1861
|
-
client.clearSession();
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
834
|
+
if (!response.ok) {
|
|
835
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
836
|
+
error?: string;
|
|
837
|
+
};
|
|
838
|
+
throw new Error(
|
|
839
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
840
|
+
);
|
|
841
|
+
}
|
|
1864
842
|
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
targetDir?: string,
|
|
1870
|
-
options?: HttpClientOptions
|
|
1871
|
-
): Promise<GitCheckoutResponse> {
|
|
1872
|
-
const client = createClient(options);
|
|
1873
|
-
await client.createSession();
|
|
1874
|
-
|
|
1875
|
-
try {
|
|
1876
|
-
return await client.gitCheckout(repoUrl, branch, targetDir);
|
|
1877
|
-
} finally {
|
|
1878
|
-
client.clearSession();
|
|
1879
|
-
}
|
|
1880
|
-
}
|
|
843
|
+
const data: StartProcessResponse = await response.json();
|
|
844
|
+
console.log(
|
|
845
|
+
`[HTTP Client] Process started: ${command}, ID: ${data.process.id}`
|
|
846
|
+
);
|
|
1881
847
|
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
): Promise<MkdirResponse> {
|
|
1888
|
-
const client = createClient(options);
|
|
1889
|
-
await client.createSession();
|
|
1890
|
-
|
|
1891
|
-
try {
|
|
1892
|
-
return await client.mkdir(path, recursive);
|
|
1893
|
-
} finally {
|
|
1894
|
-
client.clearSession();
|
|
848
|
+
return data;
|
|
849
|
+
} catch (error) {
|
|
850
|
+
console.error("[HTTP Client] Error starting process:", error);
|
|
851
|
+
throw error;
|
|
852
|
+
}
|
|
1895
853
|
}
|
|
1896
|
-
}
|
|
1897
854
|
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
await client.createSession();
|
|
1907
|
-
|
|
1908
|
-
try {
|
|
1909
|
-
await client.gitCheckoutStream(repoUrl, branch, targetDir);
|
|
1910
|
-
} finally {
|
|
1911
|
-
client.clearSession();
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
855
|
+
async listProcesses(): Promise<ListProcessesResponse> {
|
|
856
|
+
try {
|
|
857
|
+
const response = await this.doFetch("/api/process/list", {
|
|
858
|
+
headers: {
|
|
859
|
+
"Content-Type": "application/json",
|
|
860
|
+
},
|
|
861
|
+
method: "GET",
|
|
862
|
+
});
|
|
1914
863
|
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
try {
|
|
1925
|
-
await client.mkdirStream(path, recursive);
|
|
1926
|
-
} finally {
|
|
1927
|
-
client.clearSession();
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
864
|
+
if (!response.ok) {
|
|
865
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
866
|
+
error?: string;
|
|
867
|
+
};
|
|
868
|
+
throw new Error(
|
|
869
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
870
|
+
);
|
|
871
|
+
}
|
|
1930
872
|
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
encoding: string = "utf-8",
|
|
1936
|
-
options?: HttpClientOptions
|
|
1937
|
-
): Promise<WriteFileResponse> {
|
|
1938
|
-
const client = createClient(options);
|
|
1939
|
-
await client.createSession();
|
|
1940
|
-
|
|
1941
|
-
try {
|
|
1942
|
-
return await client.writeFile(path, content, encoding);
|
|
1943
|
-
} finally {
|
|
1944
|
-
client.clearSession();
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
873
|
+
const data: ListProcessesResponse = await response.json();
|
|
874
|
+
console.log(
|
|
875
|
+
`[HTTP Client] Listed ${data.processes.length} processes`
|
|
876
|
+
);
|
|
1947
877
|
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
options?: HttpClientOptions
|
|
1954
|
-
): Promise<void> {
|
|
1955
|
-
const client = createClient(options);
|
|
1956
|
-
await client.createSession();
|
|
1957
|
-
|
|
1958
|
-
try {
|
|
1959
|
-
await client.writeFileStream(path, content, encoding);
|
|
1960
|
-
} finally {
|
|
1961
|
-
client.clearSession();
|
|
878
|
+
return data;
|
|
879
|
+
} catch (error) {
|
|
880
|
+
console.error("[HTTP Client] Error listing processes:", error);
|
|
881
|
+
throw error;
|
|
882
|
+
}
|
|
1962
883
|
}
|
|
1963
|
-
}
|
|
1964
884
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
try {
|
|
1975
|
-
return await client.readFile(path, encoding);
|
|
1976
|
-
} finally {
|
|
1977
|
-
client.clearSession();
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
885
|
+
async getProcess(processId: string): Promise<GetProcessResponse> {
|
|
886
|
+
try {
|
|
887
|
+
const response = await this.doFetch(`/api/process/${processId}`, {
|
|
888
|
+
headers: {
|
|
889
|
+
"Content-Type": "application/json",
|
|
890
|
+
},
|
|
891
|
+
method: "GET",
|
|
892
|
+
});
|
|
1980
893
|
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
try {
|
|
1991
|
-
await client.readFileStream(path, encoding);
|
|
1992
|
-
} finally {
|
|
1993
|
-
client.clearSession();
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
894
|
+
if (!response.ok) {
|
|
895
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
896
|
+
error?: string;
|
|
897
|
+
};
|
|
898
|
+
throw new Error(
|
|
899
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
900
|
+
);
|
|
901
|
+
}
|
|
1996
902
|
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
): Promise<DeleteFileResponse> {
|
|
2002
|
-
const client = createClient(options);
|
|
2003
|
-
await client.createSession();
|
|
2004
|
-
|
|
2005
|
-
try {
|
|
2006
|
-
return await client.deleteFile(path);
|
|
2007
|
-
} finally {
|
|
2008
|
-
client.clearSession();
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
903
|
+
const data: GetProcessResponse = await response.json();
|
|
904
|
+
console.log(
|
|
905
|
+
`[HTTP Client] Got process ${processId}: ${data.process?.status || 'not found'}`
|
|
906
|
+
);
|
|
2011
907
|
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
const client = createClient(options);
|
|
2018
|
-
await client.createSession();
|
|
2019
|
-
|
|
2020
|
-
try {
|
|
2021
|
-
await client.deleteFileStream(path);
|
|
2022
|
-
} finally {
|
|
2023
|
-
client.clearSession();
|
|
908
|
+
return data;
|
|
909
|
+
} catch (error) {
|
|
910
|
+
console.error("[HTTP Client] Error getting process:", error);
|
|
911
|
+
throw error;
|
|
912
|
+
}
|
|
2024
913
|
}
|
|
2025
|
-
}
|
|
2026
914
|
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
915
|
+
async killProcess(processId: string): Promise<{ success: boolean; message: string }> {
|
|
916
|
+
try {
|
|
917
|
+
const response = await this.doFetch(`/api/process/${processId}`, {
|
|
918
|
+
headers: {
|
|
919
|
+
"Content-Type": "application/json",
|
|
920
|
+
},
|
|
921
|
+
method: "DELETE",
|
|
922
|
+
});
|
|
923
|
+
|
|
924
|
+
if (!response.ok) {
|
|
925
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
926
|
+
error?: string;
|
|
927
|
+
};
|
|
928
|
+
throw new Error(
|
|
929
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
const data = await response.json() as { success: boolean; message: string };
|
|
934
|
+
console.log(
|
|
935
|
+
`[HTTP Client] Killed process ${processId}`
|
|
936
|
+
);
|
|
937
|
+
|
|
938
|
+
return data;
|
|
939
|
+
} catch (error) {
|
|
940
|
+
console.error("[HTTP Client] Error killing process:", error);
|
|
941
|
+
throw error;
|
|
942
|
+
}
|
|
2040
943
|
}
|
|
2041
|
-
}
|
|
2042
944
|
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
945
|
+
async killAllProcesses(): Promise<{ success: boolean; killedCount: number; message: string }> {
|
|
946
|
+
try {
|
|
947
|
+
const response = await this.doFetch("/api/process/kill-all", {
|
|
948
|
+
headers: {
|
|
949
|
+
"Content-Type": "application/json",
|
|
950
|
+
},
|
|
951
|
+
method: "DELETE",
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
if (!response.ok) {
|
|
955
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
956
|
+
error?: string;
|
|
957
|
+
};
|
|
958
|
+
throw new Error(
|
|
959
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const data = await response.json() as { success: boolean; killedCount: number; message: string };
|
|
964
|
+
console.log(
|
|
965
|
+
`[HTTP Client] Killed ${data.killedCount} processes`
|
|
966
|
+
);
|
|
967
|
+
|
|
968
|
+
return data;
|
|
969
|
+
} catch (error) {
|
|
970
|
+
console.error("[HTTP Client] Error killing all processes:", error);
|
|
971
|
+
throw error;
|
|
972
|
+
}
|
|
2056
973
|
}
|
|
2057
|
-
}
|
|
2058
974
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
975
|
+
async getProcessLogs(processId: string): Promise<GetProcessLogsResponse> {
|
|
976
|
+
try {
|
|
977
|
+
const response = await this.doFetch(`/api/process/${processId}/logs`, {
|
|
978
|
+
headers: {
|
|
979
|
+
"Content-Type": "application/json",
|
|
980
|
+
},
|
|
981
|
+
method: "GET",
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
if (!response.ok) {
|
|
985
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
986
|
+
error?: string;
|
|
987
|
+
};
|
|
988
|
+
throw new Error(
|
|
989
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
const data: GetProcessLogsResponse = await response.json();
|
|
994
|
+
console.log(
|
|
995
|
+
`[HTTP Client] Got logs for process ${processId}`
|
|
996
|
+
);
|
|
997
|
+
|
|
998
|
+
return data;
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
console.error("[HTTP Client] Error getting process logs:", error);
|
|
1001
|
+
throw error;
|
|
1002
|
+
}
|
|
2072
1003
|
}
|
|
2073
|
-
}
|
|
2074
1004
|
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
1005
|
+
async streamProcessLogs(processId: string): Promise<ReadableStream<Uint8Array>> {
|
|
1006
|
+
try {
|
|
1007
|
+
const response = await this.doFetch(`/api/process/${processId}/stream`, {
|
|
1008
|
+
headers: {
|
|
1009
|
+
"Accept": "text/event-stream",
|
|
1010
|
+
"Cache-Control": "no-cache",
|
|
1011
|
+
},
|
|
1012
|
+
method: "GET",
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
if (!response.ok) {
|
|
1016
|
+
const errorData = (await response.json().catch(() => ({}))) as {
|
|
1017
|
+
error?: string;
|
|
1018
|
+
};
|
|
1019
|
+
throw new Error(
|
|
1020
|
+
errorData.error || `HTTP error! status: ${response.status}`
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
if (!response.body) {
|
|
1025
|
+
throw new Error("No response body for streaming request");
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
console.log(
|
|
1029
|
+
`[HTTP Client] Started streaming logs for process ${processId}`
|
|
1030
|
+
);
|
|
1031
|
+
|
|
1032
|
+
return response.body;
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
console.error("[HTTP Client] Error streaming process logs:", error);
|
|
1035
|
+
throw error;
|
|
1036
|
+
}
|
|
2088
1037
|
}
|
|
2089
1038
|
}
|