sparkecoder 0.1.68 → 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 +38 -6
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +107 -16
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-Dm6wGcYv.d.ts → index-DqaHLgSC.d.ts} +19 -19
- package/dist/index.d.ts +5 -5
- package/dist/index.js +107 -16
- 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 +107 -16
- 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/{static/chunks/4e673433173ad456.js → standalone/web/.next/static/chunks/2cafc7cb79454d33.js} +3 -3
- package/web/.next/standalone/web/.next/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
- package/web/.next/standalone/web/.next/static/chunks/{31208ade542a0fcb.js → fc39a194539da104.js} +3 -3
- package/web/.next/standalone/web/.next/static/{chunks/4e673433173ad456.js → static/chunks/2cafc7cb79454d33.js} +3 -3
- package/web/.next/standalone/web/.next/static/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
- package/web/.next/{static/chunks/31208ade542a0fcb.js → standalone/web/.next/static/static/chunks/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/static/chunks/31208ade542a0fcb.js → static/chunks/fc39a194539da104.js} +3 -3
- /package/web/.next/standalone/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
- /package/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
- /package/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
package/dist/cli.js
CHANGED
|
@@ -2556,10 +2556,15 @@ import WebSocket from "ws";
|
|
|
2556
2556
|
import { EventEmitter } from "events";
|
|
2557
2557
|
function getOrCreateProxy(sessionId, port) {
|
|
2558
2558
|
const existing = activeProxies.get(sessionId);
|
|
2559
|
-
if (existing)
|
|
2559
|
+
if (existing) {
|
|
2560
|
+
console.log(`[BROWSER-WS] Reusing existing proxy for session ${sessionId} (connected=${existing.connected})`);
|
|
2561
|
+
return existing;
|
|
2562
|
+
}
|
|
2563
|
+
console.log(`[BROWSER-WS] Creating new proxy for session ${sessionId} on port ${port} (active proxies: ${activeProxies.size})`);
|
|
2560
2564
|
const proxy = new BrowserStreamProxy(port);
|
|
2561
2565
|
activeProxies.set(sessionId, proxy);
|
|
2562
2566
|
proxy.on("close", () => {
|
|
2567
|
+
console.log(`[BROWSER-WS] Proxy closed for session ${sessionId}, removing from registry`);
|
|
2563
2568
|
activeProxies.delete(sessionId);
|
|
2564
2569
|
});
|
|
2565
2570
|
proxy.connect();
|
|
@@ -2571,8 +2576,11 @@ function getProxy(sessionId) {
|
|
|
2571
2576
|
function destroyProxy(sessionId) {
|
|
2572
2577
|
const proxy = activeProxies.get(sessionId);
|
|
2573
2578
|
if (proxy) {
|
|
2579
|
+
console.log(`[BROWSER-WS] destroyProxy() called for session ${sessionId}`);
|
|
2574
2580
|
proxy.destroy();
|
|
2575
2581
|
activeProxies.delete(sessionId);
|
|
2582
|
+
} else {
|
|
2583
|
+
console.log(`[BROWSER-WS] destroyProxy() called but no proxy exists for session ${sessionId}`);
|
|
2576
2584
|
}
|
|
2577
2585
|
}
|
|
2578
2586
|
var RECONNECT_DELAY_MS, MAX_RECONNECT_ATTEMPTS, FRAME_THROTTLE_MS, BrowserStreamProxy, activeProxies;
|
|
@@ -2603,18 +2611,22 @@ var init_stream_proxy = __esm({
|
|
|
2603
2611
|
}
|
|
2604
2612
|
connect() {
|
|
2605
2613
|
if (this.destroyed) return;
|
|
2614
|
+
console.log(`[BROWSER-WS] connect() called for port ${this.port}`);
|
|
2606
2615
|
this.doConnect();
|
|
2607
2616
|
}
|
|
2608
2617
|
doConnect() {
|
|
2609
2618
|
if (this.destroyed) return;
|
|
2610
2619
|
const url = `ws://localhost:${this.port}`;
|
|
2620
|
+
console.log(`[BROWSER-WS] Attempting WebSocket connection to ${url} (attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS})`);
|
|
2611
2621
|
try {
|
|
2612
2622
|
this.ws = new WebSocket(url);
|
|
2613
|
-
} catch {
|
|
2623
|
+
} catch (err) {
|
|
2624
|
+
console.warn(`[BROWSER-WS] WebSocket constructor threw for ${url}:`, err);
|
|
2614
2625
|
this.scheduleReconnect();
|
|
2615
2626
|
return;
|
|
2616
2627
|
}
|
|
2617
2628
|
this.ws.on("open", () => {
|
|
2629
|
+
console.log(`[BROWSER-WS] Connected to ${url} (after ${this.reconnectAttempts} retries)`);
|
|
2618
2630
|
this.reconnectAttempts = 0;
|
|
2619
2631
|
this._connected = true;
|
|
2620
2632
|
this.emit("status", {
|
|
@@ -2626,12 +2638,14 @@ var init_stream_proxy = __esm({
|
|
|
2626
2638
|
try {
|
|
2627
2639
|
const msg = JSON.parse(typeof raw === "string" ? raw : raw.toString("utf8"));
|
|
2628
2640
|
this.handleMessage(msg);
|
|
2629
|
-
} catch {
|
|
2641
|
+
} catch (err) {
|
|
2642
|
+
console.warn(`[BROWSER-WS] Malformed message from ${url}:`, err);
|
|
2630
2643
|
}
|
|
2631
2644
|
});
|
|
2632
|
-
this.ws.on("close", () => {
|
|
2645
|
+
this.ws.on("close", (code, reason) => {
|
|
2633
2646
|
const wasConnected = this._connected;
|
|
2634
2647
|
this._connected = false;
|
|
2648
|
+
console.log(`[BROWSER-WS] Connection closed: code=${code} reason="${reason?.toString() || ""}" wasConnected=${wasConnected} destroyed=${this.destroyed}`);
|
|
2635
2649
|
if (wasConnected) {
|
|
2636
2650
|
this.emit("status", { connected: false, screencasting: false });
|
|
2637
2651
|
}
|
|
@@ -2639,14 +2653,26 @@ var init_stream_proxy = __esm({
|
|
|
2639
2653
|
this.scheduleReconnect();
|
|
2640
2654
|
}
|
|
2641
2655
|
});
|
|
2642
|
-
this.ws.on("error", () => {
|
|
2656
|
+
this.ws.on("error", (err) => {
|
|
2657
|
+
console.warn(`[BROWSER-WS] WebSocket error on port ${this.port}:`, err.message);
|
|
2643
2658
|
});
|
|
2644
2659
|
}
|
|
2660
|
+
frameCount = 0;
|
|
2661
|
+
throttledCount = 0;
|
|
2662
|
+
lastFrameLogTime = 0;
|
|
2645
2663
|
handleMessage(msg) {
|
|
2646
2664
|
if (msg.type === "frame") {
|
|
2647
2665
|
const now = Date.now();
|
|
2648
|
-
if (now - this.lastFrameTime < FRAME_THROTTLE_MS)
|
|
2666
|
+
if (now - this.lastFrameTime < FRAME_THROTTLE_MS) {
|
|
2667
|
+
this.throttledCount++;
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2649
2670
|
this.lastFrameTime = now;
|
|
2671
|
+
this.frameCount++;
|
|
2672
|
+
if (now - this.lastFrameLogTime > 5e3) {
|
|
2673
|
+
console.log(`[BROWSER-WS] Frame stats: emitted=${this.frameCount} throttled=${this.throttledCount} listeners=${this.listenerCount("frame")} dataSize=${msg.data?.length ?? 0}`);
|
|
2674
|
+
this.lastFrameLogTime = now;
|
|
2675
|
+
}
|
|
2650
2676
|
const frame = {
|
|
2651
2677
|
data: msg.data,
|
|
2652
2678
|
metadata: msg.metadata ?? {
|
|
@@ -2662,21 +2688,26 @@ var init_stream_proxy = __esm({
|
|
|
2662
2688
|
this._latestFrame = frame;
|
|
2663
2689
|
this.emit("frame", frame);
|
|
2664
2690
|
} else if (msg.type === "status") {
|
|
2691
|
+
console.log(`[BROWSER-WS] Status message received:`, JSON.stringify(msg));
|
|
2665
2692
|
this.emit("status", {
|
|
2666
2693
|
connected: msg.connected ?? true,
|
|
2667
2694
|
screencasting: msg.screencasting ?? true,
|
|
2668
2695
|
viewportWidth: msg.viewportWidth,
|
|
2669
2696
|
viewportHeight: msg.viewportHeight
|
|
2670
2697
|
});
|
|
2698
|
+
} else {
|
|
2699
|
+
console.log(`[BROWSER-WS] Unknown message type: ${msg.type}`);
|
|
2671
2700
|
}
|
|
2672
2701
|
}
|
|
2673
2702
|
scheduleReconnect() {
|
|
2674
2703
|
if (this.destroyed || this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
2704
|
+
console.log(`[BROWSER-WS] Giving up reconnection: destroyed=${this.destroyed} attempts=${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS}`);
|
|
2675
2705
|
this.emit("close");
|
|
2676
2706
|
return;
|
|
2677
2707
|
}
|
|
2678
2708
|
this.reconnectAttempts++;
|
|
2679
2709
|
const delay = this.reconnectAttempts <= 5 ? RECONNECT_DELAY_MS : RECONNECT_DELAY_MS * (this.reconnectAttempts - 4);
|
|
2710
|
+
console.log(`[BROWSER-WS] Scheduling reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
|
|
2680
2711
|
this.reconnectTimer = setTimeout(() => this.doConnect(), delay);
|
|
2681
2712
|
}
|
|
2682
2713
|
/**
|
|
@@ -2688,6 +2719,7 @@ var init_stream_proxy = __esm({
|
|
|
2688
2719
|
}
|
|
2689
2720
|
}
|
|
2690
2721
|
destroy() {
|
|
2722
|
+
console.log(`[BROWSER-WS] Destroying proxy for port ${this.port} (emitted ${this.frameCount} frames, throttled ${this.throttledCount})`);
|
|
2691
2723
|
this.destroyed = true;
|
|
2692
2724
|
if (this.reconnectTimer) {
|
|
2693
2725
|
clearTimeout(this.reconnectTimer);
|
|
@@ -8841,11 +8873,19 @@ var cleanupInterval = setInterval(() => {
|
|
|
8841
8873
|
}
|
|
8842
8874
|
}, 6e4);
|
|
8843
8875
|
cleanupInterval.unref();
|
|
8876
|
+
var publishCount = 0;
|
|
8877
|
+
var lastPublishLog = 0;
|
|
8844
8878
|
var publisher = {
|
|
8845
8879
|
connect: async () => {
|
|
8846
8880
|
},
|
|
8847
8881
|
publish: async (channel, message) => {
|
|
8848
8882
|
const subscribers = channels.get(channel);
|
|
8883
|
+
publishCount++;
|
|
8884
|
+
const now = Date.now();
|
|
8885
|
+
if (now - lastPublishLog > 1e4) {
|
|
8886
|
+
console.log(`[ResumableStream] Publish stats: total=${publishCount}, channels=${channels.size}, store=${store.size}`);
|
|
8887
|
+
lastPublishLog = now;
|
|
8888
|
+
}
|
|
8849
8889
|
if (subscribers) {
|
|
8850
8890
|
for (const callback of subscribers) {
|
|
8851
8891
|
setImmediate(() => callback(message));
|
|
@@ -8884,9 +8924,12 @@ var subscriber = {
|
|
|
8884
8924
|
channels.set(channel, /* @__PURE__ */ new Set());
|
|
8885
8925
|
}
|
|
8886
8926
|
channels.get(channel).add(callback);
|
|
8927
|
+
console.log(`[ResumableStream] Subscribe to channel "${channel}" (total subscribers: ${channels.get(channel).size})`);
|
|
8887
8928
|
},
|
|
8888
8929
|
unsubscribe: async (channel) => {
|
|
8930
|
+
const count = channels.get(channel)?.size ?? 0;
|
|
8889
8931
|
channels.delete(channel);
|
|
8932
|
+
console.log(`[ResumableStream] Unsubscribe from channel "${channel}" (removed ${count} subscribers)`);
|
|
8890
8933
|
}
|
|
8891
8934
|
};
|
|
8892
8935
|
var streamContext = createResumableStreamContext({
|
|
@@ -9072,19 +9115,28 @@ function createAgentStreamProducer(sessionId, prompt, streamId, attachments) {
|
|
|
9072
9115
|
const toolCallStarts = /* @__PURE__ */ new Set();
|
|
9073
9116
|
const abortController = new AbortController();
|
|
9074
9117
|
streamAbortControllers.set(streamId, abortController);
|
|
9118
|
+
let sseEventCount = 0;
|
|
9119
|
+
let sseBrowserFrameCount = 0;
|
|
9120
|
+
let sseWriteErrors = 0;
|
|
9075
9121
|
const writeSSE = async (data) => {
|
|
9076
9122
|
if (writerClosed) return;
|
|
9077
9123
|
try {
|
|
9124
|
+
sseEventCount++;
|
|
9078
9125
|
await writer.write(`data: ${data}
|
|
9079
9126
|
|
|
9080
9127
|
`);
|
|
9081
9128
|
} catch (err) {
|
|
9129
|
+
sseWriteErrors++;
|
|
9130
|
+
if (sseWriteErrors === 1) {
|
|
9131
|
+
console.log(`[SSE:${streamId}] Writer closed (client disconnected). Total events sent: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}`);
|
|
9132
|
+
}
|
|
9082
9133
|
writerClosed = true;
|
|
9083
9134
|
}
|
|
9084
9135
|
};
|
|
9085
9136
|
const safeClose = async () => {
|
|
9086
9137
|
if (writerClosed) return;
|
|
9087
9138
|
try {
|
|
9139
|
+
console.log(`[SSE:${streamId}] Stream closing. Total events: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}, write errors: ${sseWriteErrors}`);
|
|
9088
9140
|
writerClosed = true;
|
|
9089
9141
|
await writer.close();
|
|
9090
9142
|
} catch {
|
|
@@ -9207,35 +9259,47 @@ ${prompt}` });
|
|
|
9207
9259
|
const browserPort = progress.data?.browserStreamPort;
|
|
9208
9260
|
const browserClosed = progress.data?.browserClosed;
|
|
9209
9261
|
if (progress.toolName === "bash" && browserClosed) {
|
|
9210
|
-
console.log(`[BROWSER-STREAM] agent-browser close detected, destroying proxy`);
|
|
9262
|
+
console.log(`[BROWSER-STREAM:${streamId}] agent-browser close detected, destroying proxy for session ${sessionId}`);
|
|
9211
9263
|
destroyProxy(sessionId);
|
|
9212
9264
|
} else if (progress.toolName === "bash" && browserPort) {
|
|
9213
|
-
console.log(`[BROWSER-STREAM] agent-browser command detected, ensuring proxy on port ${browserPort}`);
|
|
9265
|
+
console.log(`[BROWSER-STREAM:${streamId}] agent-browser command detected, ensuring proxy on port ${browserPort} for session ${sessionId}`);
|
|
9214
9266
|
const proxy = getOrCreateProxy(sessionId, browserPort);
|
|
9267
|
+
console.log(`[BROWSER-STREAM:${streamId}] Proxy state: connected=${proxy.connected}, frameListeners=${proxy.listenerCount("frame")}, statusListeners=${proxy.listenerCount("status")}`);
|
|
9215
9268
|
if (!sessionRecorders.has(sessionId)) {
|
|
9216
9269
|
const recorder = new FrameRecorder(sessionId);
|
|
9217
9270
|
recorder.start();
|
|
9218
9271
|
sessionRecorders.set(sessionId, recorder);
|
|
9219
9272
|
}
|
|
9220
9273
|
if (proxy.listenerCount("frame") === 0) {
|
|
9274
|
+
console.log(`[BROWSER-STREAM:${streamId}] Attaching frame+status listeners to proxy`);
|
|
9221
9275
|
proxy.on("frame", (frame) => {
|
|
9276
|
+
sseBrowserFrameCount++;
|
|
9277
|
+
if (sseBrowserFrameCount === 1) {
|
|
9278
|
+
console.log(`[BROWSER-STREAM:${streamId}] First browser frame received! dataSize=${frame.data?.length ?? 0} writerClosed=${writerClosed}`);
|
|
9279
|
+
} else if (sseBrowserFrameCount % 50 === 0) {
|
|
9280
|
+
console.log(`[BROWSER-STREAM:${streamId}] Browser frame #${sseBrowserFrameCount} (writerClosed=${writerClosed})`);
|
|
9281
|
+
}
|
|
9222
9282
|
const rec = sessionRecorders.get(sessionId);
|
|
9223
9283
|
rec?.addFrame(frame);
|
|
9224
9284
|
writeSSE(JSON.stringify({
|
|
9225
9285
|
type: "browser-frame",
|
|
9226
9286
|
data: frame.data,
|
|
9227
9287
|
metadata: frame.metadata
|
|
9228
|
-
})).catch(() => {
|
|
9288
|
+
})).catch((err) => {
|
|
9289
|
+
console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-frame via SSE:`, err);
|
|
9229
9290
|
});
|
|
9230
9291
|
});
|
|
9231
9292
|
proxy.on("status", (s) => {
|
|
9232
|
-
console.log(`[BROWSER-STREAM]
|
|
9293
|
+
console.log(`[BROWSER-STREAM:${streamId}] Browser status event: connected=${s.connected} screencasting=${s.screencasting} viewport=${s.viewportWidth}x${s.viewportHeight}`);
|
|
9233
9294
|
writeSSE(JSON.stringify({
|
|
9234
9295
|
type: "browser-status",
|
|
9235
9296
|
...s
|
|
9236
|
-
})).catch(() => {
|
|
9297
|
+
})).catch((err) => {
|
|
9298
|
+
console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-status via SSE:`, err);
|
|
9237
9299
|
});
|
|
9238
9300
|
});
|
|
9301
|
+
} else {
|
|
9302
|
+
console.log(`[BROWSER-STREAM:${streamId}] Frame listeners already attached (count=${proxy.listenerCount("frame")}), skipping`);
|
|
9239
9303
|
}
|
|
9240
9304
|
}
|
|
9241
9305
|
},
|
|
@@ -9425,14 +9489,17 @@ ${prompt}` });
|
|
|
9425
9489
|
}
|
|
9426
9490
|
await messageQueries.create(id, { role: "user", content: userMessageContent });
|
|
9427
9491
|
const streamId = `stream_${id}_${nanoid6(10)}`;
|
|
9492
|
+
console.log(`[STREAM] Creating stream ${streamId} for session ${id}`);
|
|
9428
9493
|
await activeStreamQueries.create(id, streamId);
|
|
9429
9494
|
const stream = await streamContext.resumableStream(
|
|
9430
9495
|
streamId,
|
|
9431
9496
|
createAgentStreamProducer(id, prompt, streamId, streamAttachments)
|
|
9432
9497
|
);
|
|
9433
9498
|
if (!stream) {
|
|
9499
|
+
console.error(`[STREAM] Failed to create resumable stream ${streamId}`);
|
|
9434
9500
|
return c.json({ error: "Failed to create stream" }, 500);
|
|
9435
9501
|
}
|
|
9502
|
+
console.log(`[STREAM] Stream ${streamId} created successfully`);
|
|
9436
9503
|
const encodedStream = stream.pipeThrough(new TextEncoderStream());
|
|
9437
9504
|
return new Response(encodedStream, {
|
|
9438
9505
|
headers: {
|
|
@@ -9461,17 +9528,20 @@ agents.get("/:id/watch", async (c) => {
|
|
|
9461
9528
|
}
|
|
9462
9529
|
streamId = activeStream.streamId;
|
|
9463
9530
|
}
|
|
9531
|
+
console.log(`[STREAM] Watch request for session ${sessionId}, streamId=${streamId}, resumeAt=${resumeAt || "none"}`);
|
|
9464
9532
|
const stream = await streamContext.resumeExistingStream(
|
|
9465
9533
|
streamId,
|
|
9466
9534
|
resumeAt ? parseInt(resumeAt, 10) : void 0
|
|
9467
9535
|
);
|
|
9468
9536
|
if (!stream) {
|
|
9537
|
+
console.log(`[STREAM] Watch failed \u2014 stream ${streamId} is no longer active`);
|
|
9469
9538
|
return c.json({
|
|
9470
9539
|
error: "Stream is no longer active",
|
|
9471
9540
|
streamId,
|
|
9472
9541
|
hint: "The stream may have finished. Check /agents/:id/approvals or start a new run."
|
|
9473
9542
|
}, 422);
|
|
9474
9543
|
}
|
|
9544
|
+
console.log(`[STREAM] Client watching stream ${streamId}`);
|
|
9475
9545
|
const encodedStream = stream.pipeThrough(new TextEncoderStream());
|
|
9476
9546
|
return new Response(encodedStream, {
|
|
9477
9547
|
headers: {
|
|
@@ -9633,19 +9703,28 @@ agents.post(
|
|
|
9633
9703
|
const toolCallStarts = /* @__PURE__ */ new Set();
|
|
9634
9704
|
const abortController = new AbortController();
|
|
9635
9705
|
streamAbortControllers.set(streamId, abortController);
|
|
9706
|
+
let sseEventCount = 0;
|
|
9707
|
+
let sseBrowserFrameCount = 0;
|
|
9708
|
+
let sseWriteErrors = 0;
|
|
9636
9709
|
const writeSSE = async (data) => {
|
|
9637
9710
|
if (writerClosed) return;
|
|
9638
9711
|
try {
|
|
9712
|
+
sseEventCount++;
|
|
9639
9713
|
await writer.write(`data: ${data}
|
|
9640
9714
|
|
|
9641
9715
|
`);
|
|
9642
9716
|
} catch (err) {
|
|
9717
|
+
sseWriteErrors++;
|
|
9718
|
+
if (sseWriteErrors === 1) {
|
|
9719
|
+
console.log(`[SSE:${streamId}] Writer closed (client disconnected). Total events sent: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}`);
|
|
9720
|
+
}
|
|
9643
9721
|
writerClosed = true;
|
|
9644
9722
|
}
|
|
9645
9723
|
};
|
|
9646
9724
|
const safeClose = async () => {
|
|
9647
9725
|
if (writerClosed) return;
|
|
9648
9726
|
try {
|
|
9727
|
+
console.log(`[SSE:${streamId}] Stream closing. Total events: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}, write errors: ${sseWriteErrors}`);
|
|
9649
9728
|
writerClosed = true;
|
|
9650
9729
|
await writer.close();
|
|
9651
9730
|
} catch {
|
|
@@ -9705,35 +9784,47 @@ agents.post(
|
|
|
9705
9784
|
const browserPort = progress.data?.browserStreamPort;
|
|
9706
9785
|
const browserClosed = progress.data?.browserClosed;
|
|
9707
9786
|
if (progress.toolName === "bash" && browserClosed) {
|
|
9708
|
-
console.log(`[BROWSER-STREAM] agent-browser close detected`);
|
|
9787
|
+
console.log(`[BROWSER-STREAM:${streamId}] agent-browser close detected, destroying proxy for session ${session.id}`);
|
|
9709
9788
|
destroyProxy(session.id);
|
|
9710
9789
|
} else if (progress.toolName === "bash" && browserPort) {
|
|
9711
|
-
console.log(`[BROWSER-STREAM] agent-browser command detected, port ${browserPort}`);
|
|
9790
|
+
console.log(`[BROWSER-STREAM:${streamId}] agent-browser command detected, port ${browserPort} for session ${session.id}`);
|
|
9712
9791
|
const proxy = getOrCreateProxy(session.id, browserPort);
|
|
9792
|
+
console.log(`[BROWSER-STREAM:${streamId}] Proxy state: connected=${proxy.connected}, frameListeners=${proxy.listenerCount("frame")}, statusListeners=${proxy.listenerCount("status")}`);
|
|
9713
9793
|
if (!sessionRecorders.has(session.id)) {
|
|
9714
9794
|
const recorder = new FrameRecorder(session.id);
|
|
9715
9795
|
recorder.start();
|
|
9716
9796
|
sessionRecorders.set(session.id, recorder);
|
|
9717
9797
|
}
|
|
9718
9798
|
if (proxy.listenerCount("frame") === 0) {
|
|
9799
|
+
console.log(`[BROWSER-STREAM:${streamId}] Attaching frame+status listeners to proxy`);
|
|
9719
9800
|
proxy.on("frame", (frame) => {
|
|
9801
|
+
sseBrowserFrameCount++;
|
|
9802
|
+
if (sseBrowserFrameCount === 1) {
|
|
9803
|
+
console.log(`[BROWSER-STREAM:${streamId}] First browser frame received! dataSize=${frame.data?.length ?? 0} writerClosed=${writerClosed}`);
|
|
9804
|
+
} else if (sseBrowserFrameCount % 50 === 0) {
|
|
9805
|
+
console.log(`[BROWSER-STREAM:${streamId}] Browser frame #${sseBrowserFrameCount} (writerClosed=${writerClosed})`);
|
|
9806
|
+
}
|
|
9720
9807
|
const rec = sessionRecorders.get(session.id);
|
|
9721
9808
|
rec?.addFrame(frame);
|
|
9722
9809
|
writeSSE(JSON.stringify({
|
|
9723
9810
|
type: "browser-frame",
|
|
9724
9811
|
data: frame.data,
|
|
9725
9812
|
metadata: frame.metadata
|
|
9726
|
-
})).catch(() => {
|
|
9813
|
+
})).catch((err) => {
|
|
9814
|
+
console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-frame via SSE:`, err);
|
|
9727
9815
|
});
|
|
9728
9816
|
});
|
|
9729
9817
|
proxy.on("status", (s) => {
|
|
9730
|
-
console.log(`[BROWSER-STREAM]
|
|
9818
|
+
console.log(`[BROWSER-STREAM:${streamId}] Browser status event: connected=${s.connected} screencasting=${s.screencasting} viewport=${s.viewportWidth}x${s.viewportHeight}`);
|
|
9731
9819
|
writeSSE(JSON.stringify({
|
|
9732
9820
|
type: "browser-status",
|
|
9733
9821
|
...s
|
|
9734
|
-
})).catch(() => {
|
|
9822
|
+
})).catch((err) => {
|
|
9823
|
+
console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-status via SSE:`, err);
|
|
9735
9824
|
});
|
|
9736
9825
|
});
|
|
9826
|
+
} else {
|
|
9827
|
+
console.log(`[BROWSER-STREAM:${streamId}] Frame listeners already attached (count=${proxy.listenerCount("frame")}), skipping`);
|
|
9737
9828
|
}
|
|
9738
9829
|
}
|
|
9739
9830
|
},
|