sparkecoder 0.1.67 → 0.1.69
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/agent/index.d.ts +3 -3
- package/dist/agent/index.js +173 -19
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +307 -64
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-DHyVVhJY.d.ts → index-DqaHLgSC.d.ts} +20 -19
- package/dist/index.d.ts +5 -5
- package/dist/index.js +307 -64
- package/dist/index.js.map +1 -1
- package/dist/{schema-XcP0dedO.d.ts → schema-Bq4tID-f.d.ts} +3 -3
- package/dist/{search-CCffrVJE.d.ts → search-BRnGaIl-.d.ts} +7 -7
- package/dist/server/index.js +307 -64
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +2 -2
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__c71f29f9._.js +3 -3
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_2b3a5919._.js +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_38156da8._.js +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/web/.next/static/chunks/{4e673433173ad456.js → 2cafc7cb79454d33.js} +3 -3
- package/web/.next/standalone/web/.next/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
- package/web/.next/{static/chunks/31208ade542a0fcb.js → standalone/web/.next/static/chunks/fc39a194539da104.js} +3 -3
- package/web/.next/{static/chunks/4e673433173ad456.js → standalone/web/.next/static/static/chunks/2cafc7cb79454d33.js} +3 -3
- package/web/.next/standalone/web/.next/static/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
- package/web/.next/standalone/web/.next/static/static/chunks/{31208ade542a0fcb.js → fc39a194539da104.js} +3 -3
- package/web/.next/standalone/web/src/components/chat-interface.tsx +14 -0
- package/web/.next/standalone/web/src/lib/api.ts +89 -16
- package/web/.next/{standalone/web/.next/static/static/chunks/4e673433173ad456.js → static/chunks/2cafc7cb79454d33.js} +3 -3
- package/web/.next/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
- package/web/.next/{standalone/web/.next/static/chunks/31208ade542a0fcb.js → static/chunks/fc39a194539da104.js} +3 -3
- /package/web/.next/standalone/web/.next/static/{static/tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{static/tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{static/tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{tZkod5afiOX7T9AkN1yPO → static/XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{tZkod5afiOX7T9AkN1yPO → static/XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{tZkod5afiOX7T9AkN1yPO → static/XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
- /package/web/.next/static/{tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
- /package/web/.next/static/{tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
|
@@ -311,19 +311,32 @@ function parseSSEStream(
|
|
|
311
311
|
return new Promise(async (resolve, reject) => {
|
|
312
312
|
const reader = response.body?.getReader();
|
|
313
313
|
if (!reader) {
|
|
314
|
+
console.error('[SSE] No response body — cannot read stream');
|
|
314
315
|
reject(new Error('No response body'));
|
|
315
316
|
return;
|
|
316
317
|
}
|
|
317
318
|
|
|
318
319
|
const decoder = new TextDecoder();
|
|
319
320
|
let buffer = '';
|
|
321
|
+
let totalEvents = 0;
|
|
322
|
+
let browserFrames = 0;
|
|
323
|
+
let browserStatusEvents = 0;
|
|
324
|
+
let parseErrors = 0;
|
|
325
|
+
let totalBytes = 0;
|
|
326
|
+
let lastStatsLog = Date.now();
|
|
320
327
|
const shouldDebugSSE = typeof window !== 'undefined' && (window as any).__sparkeSseDebug === true;
|
|
321
328
|
|
|
329
|
+
console.log('[SSE] Stream reader started, status:', response.status);
|
|
330
|
+
|
|
322
331
|
try {
|
|
323
332
|
while (true) {
|
|
324
333
|
const { done, value } = await reader.read();
|
|
325
|
-
if (done)
|
|
334
|
+
if (done) {
|
|
335
|
+
console.log(`[SSE] Stream ended. Total events: ${totalEvents}, browser frames: ${browserFrames}, browser status: ${browserStatusEvents}, parse errors: ${parseErrors}, bytes: ${totalBytes}`);
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
326
338
|
|
|
339
|
+
totalBytes += value?.byteLength ?? 0;
|
|
327
340
|
buffer += decoder.decode(value, { stream: true });
|
|
328
341
|
const lines = buffer.split('\n');
|
|
329
342
|
buffer = lines.pop() || '';
|
|
@@ -331,13 +344,38 @@ function parseSSEStream(
|
|
|
331
344
|
for (const line of lines) {
|
|
332
345
|
if (line.startsWith('data: ')) {
|
|
333
346
|
const data = line.slice(6);
|
|
334
|
-
if (data === '[DONE]')
|
|
347
|
+
if (data === '[DONE]') {
|
|
348
|
+
console.log('[SSE] Received [DONE] marker');
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
335
351
|
|
|
336
352
|
try {
|
|
337
353
|
const event = JSON.parse(data);
|
|
354
|
+
totalEvents++;
|
|
338
355
|
|
|
356
|
+
// Track browser-specific events
|
|
357
|
+
if (event.type === 'browser-frame') {
|
|
358
|
+
browserFrames++;
|
|
359
|
+
if (browserFrames === 1) {
|
|
360
|
+
console.log(`[SSE] First browser-frame received! dataSize=${event.data?.length ?? 0}`);
|
|
361
|
+
} else if (browserFrames % 50 === 0) {
|
|
362
|
+
console.log(`[SSE] Browser frame #${browserFrames}`);
|
|
363
|
+
}
|
|
364
|
+
} else if (event.type === 'browser-status') {
|
|
365
|
+
browserStatusEvents++;
|
|
366
|
+
console.log(`[SSE] Browser status event: connected=${event.connected} screencasting=${event.screencasting}`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Periodic stats
|
|
370
|
+
const now = Date.now();
|
|
371
|
+
if (now - lastStatsLog > 10000) {
|
|
372
|
+
console.log(`[SSE] Stats: events=${totalEvents} browserFrames=${browserFrames} bytes=${totalBytes} parseErrors=${parseErrors}`);
|
|
373
|
+
lastStatsLog = now;
|
|
374
|
+
}
|
|
375
|
+
|
|
339
376
|
// Capture stream ID for reconnection
|
|
340
377
|
if (event.type === 'data-stream-id' && onStreamId) {
|
|
378
|
+
console.log(`[SSE] Stream ID received: ${event.streamId}`);
|
|
341
379
|
onStreamId(event.streamId);
|
|
342
380
|
}
|
|
343
381
|
|
|
@@ -354,10 +392,12 @@ function parseSSEStream(
|
|
|
354
392
|
|
|
355
393
|
onEvent(event as SSEEvent);
|
|
356
394
|
} catch (err) {
|
|
395
|
+
parseErrors++;
|
|
357
396
|
console.warn('[SSE] Failed to parse event JSON', {
|
|
358
397
|
error: err instanceof Error ? err.message : String(err),
|
|
359
398
|
dataLength: data.length,
|
|
360
399
|
preview: data.slice(0, 200),
|
|
400
|
+
parseErrors,
|
|
361
401
|
});
|
|
362
402
|
if (shouldDebugSSE && typeof window !== 'undefined') {
|
|
363
403
|
window.dispatchEvent(new CustomEvent('sparke:sse-parse-error', {
|
|
@@ -374,6 +414,7 @@ function parseSSEStream(
|
|
|
374
414
|
}
|
|
375
415
|
resolve();
|
|
376
416
|
} catch (err) {
|
|
417
|
+
console.error(`[SSE] Stream read error after ${totalEvents} events, ${totalBytes} bytes:`, err);
|
|
377
418
|
reject(err);
|
|
378
419
|
}
|
|
379
420
|
});
|
|
@@ -398,6 +439,7 @@ export function runAgent(
|
|
|
398
439
|
}
|
|
399
440
|
): () => void {
|
|
400
441
|
const controller = new AbortController();
|
|
442
|
+
console.log(`[STREAM] runAgent: starting stream for session ${sessionId}`);
|
|
401
443
|
|
|
402
444
|
const body: { prompt: string; attachments?: RunAgentAttachment[] } = { prompt };
|
|
403
445
|
if (options?.attachments && options.attachments.length > 0) {
|
|
@@ -411,19 +453,29 @@ export function runAgent(
|
|
|
411
453
|
signal: controller.signal,
|
|
412
454
|
})
|
|
413
455
|
.then(async (response) => {
|
|
456
|
+
console.log(`[STREAM] runAgent: response status=${response.status}, content-type=${response.headers.get('content-type')}`);
|
|
414
457
|
const streamId = response.headers.get('x-stream-id');
|
|
415
|
-
if (streamId
|
|
416
|
-
|
|
458
|
+
if (streamId) {
|
|
459
|
+
console.log(`[STREAM] runAgent: received stream ID ${streamId}`);
|
|
460
|
+
if (options?.onStreamId) {
|
|
461
|
+
options.onStreamId(streamId);
|
|
462
|
+
}
|
|
417
463
|
}
|
|
418
464
|
await parseSSEStream(response, onEvent, options?.onStreamId);
|
|
465
|
+
console.log(`[STREAM] runAgent: stream completed for session ${sessionId}`);
|
|
419
466
|
})
|
|
420
467
|
.catch((err) => {
|
|
421
468
|
if (err.name !== 'AbortError') {
|
|
422
|
-
console.error(
|
|
469
|
+
console.error(`[STREAM] runAgent error for session ${sessionId}:`, err);
|
|
470
|
+
} else {
|
|
471
|
+
console.log(`[STREAM] runAgent: aborted for session ${sessionId}`);
|
|
423
472
|
}
|
|
424
473
|
});
|
|
425
474
|
|
|
426
|
-
return () =>
|
|
475
|
+
return () => {
|
|
476
|
+
console.log(`[STREAM] runAgent: abort called for session ${sessionId}`);
|
|
477
|
+
controller.abort();
|
|
478
|
+
};
|
|
427
479
|
}
|
|
428
480
|
|
|
429
481
|
// Watch/subscribe to an existing stream (for multiple tabs/clients)
|
|
@@ -443,30 +495,41 @@ export function watchStream(
|
|
|
443
495
|
if (options?.resumeAt !== undefined) params.set('resumeAt', String(options.resumeAt));
|
|
444
496
|
|
|
445
497
|
const url = `${getApiBase()}/agents/${sessionId}/watch${params.toString() ? '?' + params.toString() : ''}`;
|
|
498
|
+
console.log(`[STREAM] watchStream: connecting to ${url}`);
|
|
446
499
|
|
|
447
500
|
fetch(url, { signal: controller.signal })
|
|
448
501
|
.then(async (response) => {
|
|
502
|
+
console.log(`[STREAM] watchStream: response status=${response.status}, content-type=${response.headers.get('content-type')}`);
|
|
449
503
|
if (!response.ok) {
|
|
450
504
|
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
451
|
-
console.error(
|
|
505
|
+
console.error(`[STREAM] watchStream error: status=${response.status}`, error);
|
|
452
506
|
onEvent({ type: 'error', errorText: error.error || 'Failed to watch stream' });
|
|
453
507
|
return;
|
|
454
508
|
}
|
|
455
509
|
|
|
456
510
|
const streamId = response.headers.get('x-stream-id');
|
|
457
|
-
if (streamId
|
|
458
|
-
|
|
511
|
+
if (streamId) {
|
|
512
|
+
console.log(`[STREAM] watchStream: received stream ID ${streamId}`);
|
|
513
|
+
if (options?.onStreamId) {
|
|
514
|
+
options.onStreamId(streamId);
|
|
515
|
+
}
|
|
459
516
|
}
|
|
460
517
|
|
|
461
518
|
await parseSSEStream(response, onEvent, options?.onStreamId);
|
|
519
|
+
console.log(`[STREAM] watchStream: completed for session ${sessionId}`);
|
|
462
520
|
})
|
|
463
521
|
.catch((err) => {
|
|
464
522
|
if (err.name !== 'AbortError') {
|
|
465
|
-
console.error(
|
|
523
|
+
console.error(`[STREAM] watchStream error for session ${sessionId}:`, err);
|
|
524
|
+
} else {
|
|
525
|
+
console.log(`[STREAM] watchStream: aborted for session ${sessionId}`);
|
|
466
526
|
}
|
|
467
527
|
});
|
|
468
528
|
|
|
469
|
-
return () =>
|
|
529
|
+
return () => {
|
|
530
|
+
console.log(`[STREAM] watchStream: abort called for session ${sessionId}`);
|
|
531
|
+
controller.abort();
|
|
532
|
+
};
|
|
470
533
|
}
|
|
471
534
|
|
|
472
535
|
export type SSEEvent =
|
|
@@ -520,6 +583,7 @@ export function streamTerminal(
|
|
|
520
583
|
onExit?: () => void
|
|
521
584
|
): () => void {
|
|
522
585
|
const controller = new AbortController();
|
|
586
|
+
console.log(`[TERMINAL] Connecting to terminal stream: ${terminalId}`);
|
|
523
587
|
|
|
524
588
|
const connect = async () => {
|
|
525
589
|
try {
|
|
@@ -528,17 +592,22 @@ export function streamTerminal(
|
|
|
528
592
|
});
|
|
529
593
|
|
|
530
594
|
if (!response.ok || !response.body) {
|
|
531
|
-
console.error(
|
|
595
|
+
console.error(`[TERMINAL] Failed to connect to terminal stream ${terminalId}: status=${response.status}`);
|
|
532
596
|
return;
|
|
533
597
|
}
|
|
598
|
+
console.log(`[TERMINAL] Connected to terminal stream ${terminalId}`);
|
|
534
599
|
|
|
535
600
|
const reader = response.body.getReader();
|
|
536
601
|
const decoder = new TextDecoder();
|
|
537
602
|
let buffer = '';
|
|
603
|
+
let chunkCount = 0;
|
|
538
604
|
|
|
539
605
|
while (true) {
|
|
540
606
|
const { done, value } = await reader.read();
|
|
541
|
-
if (done)
|
|
607
|
+
if (done) {
|
|
608
|
+
console.log(`[TERMINAL] Stream ended for ${terminalId} after ${chunkCount} output chunks`);
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
542
611
|
|
|
543
612
|
buffer += decoder.decode(value, { stream: true });
|
|
544
613
|
const lines = buffer.split('\n\n');
|
|
@@ -547,7 +616,6 @@ export function streamTerminal(
|
|
|
547
616
|
for (const chunk of lines) {
|
|
548
617
|
if (!chunk.trim()) continue;
|
|
549
618
|
|
|
550
|
-
// Parse SSE format: "event: type\ndata: {...}"
|
|
551
619
|
const eventMatch = chunk.match(/event:\s*(\w+)/);
|
|
552
620
|
const dataMatch = chunk.match(/data:\s*(.+)/);
|
|
553
621
|
|
|
@@ -557,8 +625,10 @@ export function streamTerminal(
|
|
|
557
625
|
const data = JSON.parse(dataMatch[1]);
|
|
558
626
|
|
|
559
627
|
if (eventType === 'stdout' && data.data) {
|
|
628
|
+
chunkCount++;
|
|
560
629
|
onOutput(data.data);
|
|
561
630
|
} else if (eventType === 'exit') {
|
|
631
|
+
console.log(`[TERMINAL] Exit event for ${terminalId}`);
|
|
562
632
|
onExit?.();
|
|
563
633
|
}
|
|
564
634
|
} catch {
|
|
@@ -569,14 +639,17 @@ export function streamTerminal(
|
|
|
569
639
|
}
|
|
570
640
|
} catch (error) {
|
|
571
641
|
if (error instanceof Error && error.name !== 'AbortError') {
|
|
572
|
-
console.error(
|
|
642
|
+
console.error(`[TERMINAL] Stream error for ${terminalId}:`, error);
|
|
573
643
|
}
|
|
574
644
|
}
|
|
575
645
|
};
|
|
576
646
|
|
|
577
647
|
connect();
|
|
578
648
|
|
|
579
|
-
return () =>
|
|
649
|
+
return () => {
|
|
650
|
+
console.log(`[TERMINAL] Aborting terminal stream ${terminalId}`);
|
|
651
|
+
controller.abort();
|
|
652
|
+
};
|
|
580
653
|
}
|
|
581
654
|
|
|
582
655
|
// ============================================
|