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
@@ -85,7 +85,7 @@ declare const sessions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
85
85
  tableName: "sessions";
86
86
  dataType: "string";
87
87
  columnType: "SQLiteText";
88
- data: "error" | "completed" | "active" | "waiting";
88
+ data: "active" | "waiting" | "completed" | "error";
89
89
  driverParam: string;
90
90
  notNull: true;
91
91
  hasDefault: true;
@@ -391,7 +391,7 @@ declare const toolExecutions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
391
391
  tableName: "tool_executions";
392
392
  dataType: "string";
393
393
  columnType: "SQLiteText";
394
- data: "error" | "completed" | "pending" | "approved" | "rejected";
394
+ data: "completed" | "error" | "pending" | "approved" | "rejected";
395
395
  driverParam: string;
396
396
  notNull: true;
397
397
  hasDefault: true;
@@ -967,7 +967,7 @@ declare const activeStreams: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
967
967
  tableName: "active_streams";
968
968
  dataType: "string";
969
969
  columnType: "SQLiteText";
970
- data: "error" | "active" | "finished";
970
+ data: "active" | "error" | "finished";
971
971
  driverParam: string;
972
972
  notNull: true;
973
973
  hasDefault: true;
@@ -15,12 +15,12 @@ interface BashToolOptions {
15
15
  }
16
16
  declare function createBashTool(options: BashToolOptions): ai.Tool<{
17
17
  background: boolean;
18
- input?: string | undefined;
19
18
  id?: string | undefined;
19
+ input?: string | undefined;
20
20
  command?: string | undefined;
21
21
  kill?: boolean | undefined;
22
22
  tail?: number | undefined;
23
- key?: "y" | "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "n" | undefined;
23
+ key?: "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "y" | "n" | undefined;
24
24
  }, {
25
25
  success: boolean;
26
26
  id: string;
@@ -41,7 +41,7 @@ declare function createBashTool(options: BashToolOptions): ai.Tool<{
41
41
  success: boolean;
42
42
  id: string;
43
43
  output: string;
44
- status: "unknown" | "running" | "stopped";
44
+ status: "running" | "stopped" | "unknown";
45
45
  message: string;
46
46
  error?: undefined;
47
47
  exitCode?: undefined;
@@ -49,7 +49,7 @@ declare function createBashTool(options: BashToolOptions): ai.Tool<{
49
49
  success: boolean;
50
50
  id: string;
51
51
  output: string;
52
- status: "unknown" | "running" | "stopped";
52
+ status: "running" | "stopped" | "unknown";
53
53
  message?: undefined;
54
54
  error?: undefined;
55
55
  exitCode?: undefined;
@@ -66,7 +66,7 @@ declare function createBashTool(options: BashToolOptions): ai.Tool<{
66
66
  id: string;
67
67
  output: string;
68
68
  exitCode: number;
69
- status: "error" | "completed" | "running" | "stopped";
69
+ status: "completed" | "error" | "running" | "stopped";
70
70
  message?: undefined;
71
71
  error?: undefined;
72
72
  } | {
@@ -116,8 +116,8 @@ interface WriteFileToolOptions {
116
116
  onProgress?: (progress: WriteFileProgress) => void;
117
117
  }
118
118
  declare function createWriteFileTool(options: WriteFileToolOptions): ai.Tool<{
119
- path: string;
120
119
  mode: "full" | "str_replace";
120
+ path: string;
121
121
  content?: string | undefined;
122
122
  old_string?: string | undefined;
123
123
  new_string?: string | undefined;
@@ -218,8 +218,8 @@ interface SearchToolOptions {
218
218
  * Progress is streamed back to the UI so users can see exploration happening.
219
219
  */
220
220
  declare function createSearchTool(options: SearchToolOptions): ai.Tool<{
221
- context: string;
222
221
  query: string;
222
+ context: string;
223
223
  }, {
224
224
  success: boolean;
225
225
  error: string;
@@ -1785,10 +1785,15 @@ import WebSocket from "ws";
1785
1785
  import { EventEmitter } from "events";
1786
1786
  function getOrCreateProxy(sessionId, port) {
1787
1787
  const existing = activeProxies.get(sessionId);
1788
- if (existing) return existing;
1788
+ if (existing) {
1789
+ console.log(`[BROWSER-WS] Reusing existing proxy for session ${sessionId} (connected=${existing.connected})`);
1790
+ return existing;
1791
+ }
1792
+ console.log(`[BROWSER-WS] Creating new proxy for session ${sessionId} on port ${port} (active proxies: ${activeProxies.size})`);
1789
1793
  const proxy = new BrowserStreamProxy(port);
1790
1794
  activeProxies.set(sessionId, proxy);
1791
1795
  proxy.on("close", () => {
1796
+ console.log(`[BROWSER-WS] Proxy closed for session ${sessionId}, removing from registry`);
1792
1797
  activeProxies.delete(sessionId);
1793
1798
  });
1794
1799
  proxy.connect();
@@ -1800,8 +1805,11 @@ function getProxy(sessionId) {
1800
1805
  function destroyProxy(sessionId) {
1801
1806
  const proxy = activeProxies.get(sessionId);
1802
1807
  if (proxy) {
1808
+ console.log(`[BROWSER-WS] destroyProxy() called for session ${sessionId}`);
1803
1809
  proxy.destroy();
1804
1810
  activeProxies.delete(sessionId);
1811
+ } else {
1812
+ console.log(`[BROWSER-WS] destroyProxy() called but no proxy exists for session ${sessionId}`);
1805
1813
  }
1806
1814
  }
1807
1815
  var RECONNECT_DELAY_MS, MAX_RECONNECT_ATTEMPTS, FRAME_THROTTLE_MS, BrowserStreamProxy, activeProxies;
@@ -1832,18 +1840,22 @@ var init_stream_proxy = __esm({
1832
1840
  }
1833
1841
  connect() {
1834
1842
  if (this.destroyed) return;
1843
+ console.log(`[BROWSER-WS] connect() called for port ${this.port}`);
1835
1844
  this.doConnect();
1836
1845
  }
1837
1846
  doConnect() {
1838
1847
  if (this.destroyed) return;
1839
1848
  const url = `ws://localhost:${this.port}`;
1849
+ console.log(`[BROWSER-WS] Attempting WebSocket connection to ${url} (attempt ${this.reconnectAttempts + 1}/${MAX_RECONNECT_ATTEMPTS})`);
1840
1850
  try {
1841
1851
  this.ws = new WebSocket(url);
1842
- } catch {
1852
+ } catch (err) {
1853
+ console.warn(`[BROWSER-WS] WebSocket constructor threw for ${url}:`, err);
1843
1854
  this.scheduleReconnect();
1844
1855
  return;
1845
1856
  }
1846
1857
  this.ws.on("open", () => {
1858
+ console.log(`[BROWSER-WS] Connected to ${url} (after ${this.reconnectAttempts} retries)`);
1847
1859
  this.reconnectAttempts = 0;
1848
1860
  this._connected = true;
1849
1861
  this.emit("status", {
@@ -1855,12 +1867,14 @@ var init_stream_proxy = __esm({
1855
1867
  try {
1856
1868
  const msg = JSON.parse(typeof raw === "string" ? raw : raw.toString("utf8"));
1857
1869
  this.handleMessage(msg);
1858
- } catch {
1870
+ } catch (err) {
1871
+ console.warn(`[BROWSER-WS] Malformed message from ${url}:`, err);
1859
1872
  }
1860
1873
  });
1861
- this.ws.on("close", () => {
1874
+ this.ws.on("close", (code, reason) => {
1862
1875
  const wasConnected = this._connected;
1863
1876
  this._connected = false;
1877
+ console.log(`[BROWSER-WS] Connection closed: code=${code} reason="${reason?.toString() || ""}" wasConnected=${wasConnected} destroyed=${this.destroyed}`);
1864
1878
  if (wasConnected) {
1865
1879
  this.emit("status", { connected: false, screencasting: false });
1866
1880
  }
@@ -1868,14 +1882,26 @@ var init_stream_proxy = __esm({
1868
1882
  this.scheduleReconnect();
1869
1883
  }
1870
1884
  });
1871
- this.ws.on("error", () => {
1885
+ this.ws.on("error", (err) => {
1886
+ console.warn(`[BROWSER-WS] WebSocket error on port ${this.port}:`, err.message);
1872
1887
  });
1873
1888
  }
1889
+ frameCount = 0;
1890
+ throttledCount = 0;
1891
+ lastFrameLogTime = 0;
1874
1892
  handleMessage(msg) {
1875
1893
  if (msg.type === "frame") {
1876
1894
  const now = Date.now();
1877
- if (now - this.lastFrameTime < FRAME_THROTTLE_MS) return;
1895
+ if (now - this.lastFrameTime < FRAME_THROTTLE_MS) {
1896
+ this.throttledCount++;
1897
+ return;
1898
+ }
1878
1899
  this.lastFrameTime = now;
1900
+ this.frameCount++;
1901
+ if (now - this.lastFrameLogTime > 5e3) {
1902
+ console.log(`[BROWSER-WS] Frame stats: emitted=${this.frameCount} throttled=${this.throttledCount} listeners=${this.listenerCount("frame")} dataSize=${msg.data?.length ?? 0}`);
1903
+ this.lastFrameLogTime = now;
1904
+ }
1879
1905
  const frame = {
1880
1906
  data: msg.data,
1881
1907
  metadata: msg.metadata ?? {
@@ -1891,21 +1917,26 @@ var init_stream_proxy = __esm({
1891
1917
  this._latestFrame = frame;
1892
1918
  this.emit("frame", frame);
1893
1919
  } else if (msg.type === "status") {
1920
+ console.log(`[BROWSER-WS] Status message received:`, JSON.stringify(msg));
1894
1921
  this.emit("status", {
1895
1922
  connected: msg.connected ?? true,
1896
1923
  screencasting: msg.screencasting ?? true,
1897
1924
  viewportWidth: msg.viewportWidth,
1898
1925
  viewportHeight: msg.viewportHeight
1899
1926
  });
1927
+ } else {
1928
+ console.log(`[BROWSER-WS] Unknown message type: ${msg.type}`);
1900
1929
  }
1901
1930
  }
1902
1931
  scheduleReconnect() {
1903
1932
  if (this.destroyed || this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
1933
+ console.log(`[BROWSER-WS] Giving up reconnection: destroyed=${this.destroyed} attempts=${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS}`);
1904
1934
  this.emit("close");
1905
1935
  return;
1906
1936
  }
1907
1937
  this.reconnectAttempts++;
1908
1938
  const delay = this.reconnectAttempts <= 5 ? RECONNECT_DELAY_MS : RECONNECT_DELAY_MS * (this.reconnectAttempts - 4);
1939
+ console.log(`[BROWSER-WS] Scheduling reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
1909
1940
  this.reconnectTimer = setTimeout(() => this.doConnect(), delay);
1910
1941
  }
1911
1942
  /**
@@ -1917,6 +1948,7 @@ var init_stream_proxy = __esm({
1917
1948
  }
1918
1949
  }
1919
1950
  destroy() {
1951
+ console.log(`[BROWSER-WS] Destroying proxy for port ${this.port} (emitted ${this.frameCount} frames, throttled ${this.throttledCount})`);
1920
1952
  this.destroyed = true;
1921
1953
  if (this.reconnectTimer) {
1922
1954
  clearTimeout(this.reconnectTimer);
@@ -8063,11 +8095,19 @@ var cleanupInterval = setInterval(() => {
8063
8095
  }
8064
8096
  }, 6e4);
8065
8097
  cleanupInterval.unref();
8098
+ var publishCount = 0;
8099
+ var lastPublishLog = 0;
8066
8100
  var publisher = {
8067
8101
  connect: async () => {
8068
8102
  },
8069
8103
  publish: async (channel, message) => {
8070
8104
  const subscribers = channels.get(channel);
8105
+ publishCount++;
8106
+ const now = Date.now();
8107
+ if (now - lastPublishLog > 1e4) {
8108
+ console.log(`[ResumableStream] Publish stats: total=${publishCount}, channels=${channels.size}, store=${store.size}`);
8109
+ lastPublishLog = now;
8110
+ }
8071
8111
  if (subscribers) {
8072
8112
  for (const callback of subscribers) {
8073
8113
  setImmediate(() => callback(message));
@@ -8106,9 +8146,12 @@ var subscriber = {
8106
8146
  channels.set(channel, /* @__PURE__ */ new Set());
8107
8147
  }
8108
8148
  channels.get(channel).add(callback);
8149
+ console.log(`[ResumableStream] Subscribe to channel "${channel}" (total subscribers: ${channels.get(channel).size})`);
8109
8150
  },
8110
8151
  unsubscribe: async (channel) => {
8152
+ const count = channels.get(channel)?.size ?? 0;
8111
8153
  channels.delete(channel);
8154
+ console.log(`[ResumableStream] Unsubscribe from channel "${channel}" (removed ${count} subscribers)`);
8112
8155
  }
8113
8156
  };
8114
8157
  var streamContext = createResumableStreamContext({
@@ -8294,19 +8337,28 @@ function createAgentStreamProducer(sessionId, prompt, streamId, attachments) {
8294
8337
  const toolCallStarts = /* @__PURE__ */ new Set();
8295
8338
  const abortController = new AbortController();
8296
8339
  streamAbortControllers.set(streamId, abortController);
8340
+ let sseEventCount = 0;
8341
+ let sseBrowserFrameCount = 0;
8342
+ let sseWriteErrors = 0;
8297
8343
  const writeSSE = async (data) => {
8298
8344
  if (writerClosed) return;
8299
8345
  try {
8346
+ sseEventCount++;
8300
8347
  await writer.write(`data: ${data}
8301
8348
 
8302
8349
  `);
8303
8350
  } catch (err) {
8351
+ sseWriteErrors++;
8352
+ if (sseWriteErrors === 1) {
8353
+ console.log(`[SSE:${streamId}] Writer closed (client disconnected). Total events sent: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}`);
8354
+ }
8304
8355
  writerClosed = true;
8305
8356
  }
8306
8357
  };
8307
8358
  const safeClose = async () => {
8308
8359
  if (writerClosed) return;
8309
8360
  try {
8361
+ console.log(`[SSE:${streamId}] Stream closing. Total events: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}, write errors: ${sseWriteErrors}`);
8310
8362
  writerClosed = true;
8311
8363
  await writer.close();
8312
8364
  } catch {
@@ -8429,35 +8481,47 @@ ${prompt}` });
8429
8481
  const browserPort = progress.data?.browserStreamPort;
8430
8482
  const browserClosed = progress.data?.browserClosed;
8431
8483
  if (progress.toolName === "bash" && browserClosed) {
8432
- console.log(`[BROWSER-STREAM] agent-browser close detected, destroying proxy`);
8484
+ console.log(`[BROWSER-STREAM:${streamId}] agent-browser close detected, destroying proxy for session ${sessionId}`);
8433
8485
  destroyProxy(sessionId);
8434
8486
  } else if (progress.toolName === "bash" && browserPort) {
8435
- console.log(`[BROWSER-STREAM] agent-browser command detected, ensuring proxy on port ${browserPort}`);
8487
+ console.log(`[BROWSER-STREAM:${streamId}] agent-browser command detected, ensuring proxy on port ${browserPort} for session ${sessionId}`);
8436
8488
  const proxy = getOrCreateProxy(sessionId, browserPort);
8489
+ console.log(`[BROWSER-STREAM:${streamId}] Proxy state: connected=${proxy.connected}, frameListeners=${proxy.listenerCount("frame")}, statusListeners=${proxy.listenerCount("status")}`);
8437
8490
  if (!sessionRecorders.has(sessionId)) {
8438
8491
  const recorder = new FrameRecorder(sessionId);
8439
8492
  recorder.start();
8440
8493
  sessionRecorders.set(sessionId, recorder);
8441
8494
  }
8442
8495
  if (proxy.listenerCount("frame") === 0) {
8496
+ console.log(`[BROWSER-STREAM:${streamId}] Attaching frame+status listeners to proxy`);
8443
8497
  proxy.on("frame", (frame) => {
8498
+ sseBrowserFrameCount++;
8499
+ if (sseBrowserFrameCount === 1) {
8500
+ console.log(`[BROWSER-STREAM:${streamId}] First browser frame received! dataSize=${frame.data?.length ?? 0} writerClosed=${writerClosed}`);
8501
+ } else if (sseBrowserFrameCount % 50 === 0) {
8502
+ console.log(`[BROWSER-STREAM:${streamId}] Browser frame #${sseBrowserFrameCount} (writerClosed=${writerClosed})`);
8503
+ }
8444
8504
  const rec = sessionRecorders.get(sessionId);
8445
8505
  rec?.addFrame(frame);
8446
8506
  writeSSE(JSON.stringify({
8447
8507
  type: "browser-frame",
8448
8508
  data: frame.data,
8449
8509
  metadata: frame.metadata
8450
- })).catch(() => {
8510
+ })).catch((err) => {
8511
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-frame via SSE:`, err);
8451
8512
  });
8452
8513
  });
8453
8514
  proxy.on("status", (s) => {
8454
- console.log(`[BROWSER-STREAM] Status:`, s);
8515
+ console.log(`[BROWSER-STREAM:${streamId}] Browser status event: connected=${s.connected} screencasting=${s.screencasting} viewport=${s.viewportWidth}x${s.viewportHeight}`);
8455
8516
  writeSSE(JSON.stringify({
8456
8517
  type: "browser-status",
8457
8518
  ...s
8458
- })).catch(() => {
8519
+ })).catch((err) => {
8520
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-status via SSE:`, err);
8459
8521
  });
8460
8522
  });
8523
+ } else {
8524
+ console.log(`[BROWSER-STREAM:${streamId}] Frame listeners already attached (count=${proxy.listenerCount("frame")}), skipping`);
8461
8525
  }
8462
8526
  }
8463
8527
  },
@@ -8647,14 +8711,17 @@ ${prompt}` });
8647
8711
  }
8648
8712
  await messageQueries.create(id, { role: "user", content: userMessageContent });
8649
8713
  const streamId = `stream_${id}_${nanoid6(10)}`;
8714
+ console.log(`[STREAM] Creating stream ${streamId} for session ${id}`);
8650
8715
  await activeStreamQueries.create(id, streamId);
8651
8716
  const stream = await streamContext.resumableStream(
8652
8717
  streamId,
8653
8718
  createAgentStreamProducer(id, prompt, streamId, streamAttachments)
8654
8719
  );
8655
8720
  if (!stream) {
8721
+ console.error(`[STREAM] Failed to create resumable stream ${streamId}`);
8656
8722
  return c.json({ error: "Failed to create stream" }, 500);
8657
8723
  }
8724
+ console.log(`[STREAM] Stream ${streamId} created successfully`);
8658
8725
  const encodedStream = stream.pipeThrough(new TextEncoderStream());
8659
8726
  return new Response(encodedStream, {
8660
8727
  headers: {
@@ -8683,17 +8750,20 @@ agents.get("/:id/watch", async (c) => {
8683
8750
  }
8684
8751
  streamId = activeStream.streamId;
8685
8752
  }
8753
+ console.log(`[STREAM] Watch request for session ${sessionId}, streamId=${streamId}, resumeAt=${resumeAt || "none"}`);
8686
8754
  const stream = await streamContext.resumeExistingStream(
8687
8755
  streamId,
8688
8756
  resumeAt ? parseInt(resumeAt, 10) : void 0
8689
8757
  );
8690
8758
  if (!stream) {
8759
+ console.log(`[STREAM] Watch failed \u2014 stream ${streamId} is no longer active`);
8691
8760
  return c.json({
8692
8761
  error: "Stream is no longer active",
8693
8762
  streamId,
8694
8763
  hint: "The stream may have finished. Check /agents/:id/approvals or start a new run."
8695
8764
  }, 422);
8696
8765
  }
8766
+ console.log(`[STREAM] Client watching stream ${streamId}`);
8697
8767
  const encodedStream = stream.pipeThrough(new TextEncoderStream());
8698
8768
  return new Response(encodedStream, {
8699
8769
  headers: {
@@ -8855,19 +8925,28 @@ agents.post(
8855
8925
  const toolCallStarts = /* @__PURE__ */ new Set();
8856
8926
  const abortController = new AbortController();
8857
8927
  streamAbortControllers.set(streamId, abortController);
8928
+ let sseEventCount = 0;
8929
+ let sseBrowserFrameCount = 0;
8930
+ let sseWriteErrors = 0;
8858
8931
  const writeSSE = async (data) => {
8859
8932
  if (writerClosed) return;
8860
8933
  try {
8934
+ sseEventCount++;
8861
8935
  await writer.write(`data: ${data}
8862
8936
 
8863
8937
  `);
8864
8938
  } catch (err) {
8939
+ sseWriteErrors++;
8940
+ if (sseWriteErrors === 1) {
8941
+ console.log(`[SSE:${streamId}] Writer closed (client disconnected). Total events sent: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}`);
8942
+ }
8865
8943
  writerClosed = true;
8866
8944
  }
8867
8945
  };
8868
8946
  const safeClose = async () => {
8869
8947
  if (writerClosed) return;
8870
8948
  try {
8949
+ console.log(`[SSE:${streamId}] Stream closing. Total events: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}, write errors: ${sseWriteErrors}`);
8871
8950
  writerClosed = true;
8872
8951
  await writer.close();
8873
8952
  } catch {
@@ -8927,35 +9006,47 @@ agents.post(
8927
9006
  const browserPort = progress.data?.browserStreamPort;
8928
9007
  const browserClosed = progress.data?.browserClosed;
8929
9008
  if (progress.toolName === "bash" && browserClosed) {
8930
- console.log(`[BROWSER-STREAM] agent-browser close detected`);
9009
+ console.log(`[BROWSER-STREAM:${streamId}] agent-browser close detected, destroying proxy for session ${session.id}`);
8931
9010
  destroyProxy(session.id);
8932
9011
  } else if (progress.toolName === "bash" && browserPort) {
8933
- console.log(`[BROWSER-STREAM] agent-browser command detected, port ${browserPort}`);
9012
+ console.log(`[BROWSER-STREAM:${streamId}] agent-browser command detected, port ${browserPort} for session ${session.id}`);
8934
9013
  const proxy = getOrCreateProxy(session.id, browserPort);
9014
+ console.log(`[BROWSER-STREAM:${streamId}] Proxy state: connected=${proxy.connected}, frameListeners=${proxy.listenerCount("frame")}, statusListeners=${proxy.listenerCount("status")}`);
8935
9015
  if (!sessionRecorders.has(session.id)) {
8936
9016
  const recorder = new FrameRecorder(session.id);
8937
9017
  recorder.start();
8938
9018
  sessionRecorders.set(session.id, recorder);
8939
9019
  }
8940
9020
  if (proxy.listenerCount("frame") === 0) {
9021
+ console.log(`[BROWSER-STREAM:${streamId}] Attaching frame+status listeners to proxy`);
8941
9022
  proxy.on("frame", (frame) => {
9023
+ sseBrowserFrameCount++;
9024
+ if (sseBrowserFrameCount === 1) {
9025
+ console.log(`[BROWSER-STREAM:${streamId}] First browser frame received! dataSize=${frame.data?.length ?? 0} writerClosed=${writerClosed}`);
9026
+ } else if (sseBrowserFrameCount % 50 === 0) {
9027
+ console.log(`[BROWSER-STREAM:${streamId}] Browser frame #${sseBrowserFrameCount} (writerClosed=${writerClosed})`);
9028
+ }
8942
9029
  const rec = sessionRecorders.get(session.id);
8943
9030
  rec?.addFrame(frame);
8944
9031
  writeSSE(JSON.stringify({
8945
9032
  type: "browser-frame",
8946
9033
  data: frame.data,
8947
9034
  metadata: frame.metadata
8948
- })).catch(() => {
9035
+ })).catch((err) => {
9036
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-frame via SSE:`, err);
8949
9037
  });
8950
9038
  });
8951
9039
  proxy.on("status", (s) => {
8952
- console.log(`[BROWSER-STREAM] Status:`, s);
9040
+ console.log(`[BROWSER-STREAM:${streamId}] Browser status event: connected=${s.connected} screencasting=${s.screencasting} viewport=${s.viewportWidth}x${s.viewportHeight}`);
8953
9041
  writeSSE(JSON.stringify({
8954
9042
  type: "browser-status",
8955
9043
  ...s
8956
- })).catch(() => {
9044
+ })).catch((err) => {
9045
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-status via SSE:`, err);
8957
9046
  });
8958
9047
  });
9048
+ } else {
9049
+ console.log(`[BROWSER-STREAM:${streamId}] Frame listeners already attached (count=${proxy.listenerCount("frame")}), skipping`);
8959
9050
  }
8960
9051
  }
8961
9052
  },