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.
Files changed (108) hide show
  1. package/dist/agent/index.d.ts +3 -3
  2. package/dist/agent/index.js +38 -6
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +107 -16
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +2 -2
  7. package/dist/{index-Dm6wGcYv.d.ts → index-DqaHLgSC.d.ts} +19 -19
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.js +107 -16
  10. package/dist/index.js.map +1 -1
  11. package/dist/{schema-XcP0dedO.d.ts → schema-Bq4tID-f.d.ts} +3 -3
  12. package/dist/{search-CCffrVJE.d.ts → search-BRnGaIl-.d.ts} +7 -7
  13. package/dist/server/index.js +107 -16
  14. package/dist/server/index.js.map +1 -1
  15. package/dist/tools/index.d.ts +2 -2
  16. package/package.json +1 -1
  17. package/web/.next/BUILD_ID +1 -1
  18. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  19. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  20. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  21. package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
  22. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  23. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  24. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  25. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  37. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  39. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  41. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  48. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  57. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  66. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  70. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  73. package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
  74. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  75. package/web/.next/standalone/web/.next/server/app/index.rsc +3 -3
  76. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
  77. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
  78. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +3 -3
  79. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  80. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  81. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  82. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__c71f29f9._.js +3 -3
  83. package/web/.next/standalone/web/.next/server/chunks/ssr/web_2b3a5919._.js +1 -1
  84. package/web/.next/standalone/web/.next/server/chunks/ssr/web_38156da8._.js +1 -1
  85. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  86. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  87. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  88. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  89. package/web/.next/{static/chunks/4e673433173ad456.js → standalone/web/.next/static/chunks/2cafc7cb79454d33.js} +3 -3
  90. package/web/.next/standalone/web/.next/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
  91. package/web/.next/standalone/web/.next/static/chunks/{31208ade542a0fcb.js → fc39a194539da104.js} +3 -3
  92. package/web/.next/standalone/web/.next/static/{chunks/4e673433173ad456.js → static/chunks/2cafc7cb79454d33.js} +3 -3
  93. package/web/.next/standalone/web/.next/static/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
  94. package/web/.next/{static/chunks/31208ade542a0fcb.js → standalone/web/.next/static/static/chunks/fc39a194539da104.js} +3 -3
  95. package/web/.next/standalone/web/src/components/chat-interface.tsx +14 -0
  96. package/web/.next/standalone/web/src/lib/api.ts +89 -16
  97. package/web/.next/{standalone/web/.next/static/static/chunks/4e673433173ad456.js → static/chunks/2cafc7cb79454d33.js} +3 -3
  98. package/web/.next/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
  99. package/web/.next/{standalone/web/.next/static/static/chunks/31208ade542a0fcb.js → static/chunks/fc39a194539da104.js} +3 -3
  100. /package/web/.next/standalone/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
  101. /package/web/.next/standalone/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
  102. /package/web/.next/standalone/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
  103. /package/web/.next/standalone/web/.next/static/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
  104. /package/web/.next/standalone/web/.next/static/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
  105. /package/web/.next/standalone/web/.next/static/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
  106. /package/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
  107. /package/web/.next/static/{6Dlxqhgk8Mki7q7L-gDbl → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
  108. /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) return 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) return;
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] Status:`, s);
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] Status:`, s);
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
  },