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.
Files changed (108) hide show
  1. package/dist/agent/index.d.ts +3 -3
  2. package/dist/agent/index.js +173 -19
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +307 -64
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +2 -2
  7. package/dist/{index-DHyVVhJY.d.ts → index-DqaHLgSC.d.ts} +20 -19
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.js +307 -64
  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 +307 -64
  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/standalone/web/.next/static/chunks/{4e673433173ad456.js → 2cafc7cb79454d33.js} +3 -3
  90. package/web/.next/standalone/web/.next/static/chunks/{515f0c0bd6087843.js → b6ec74cad9ffd3ee.js} +3 -3
  91. package/web/.next/{static/chunks/31208ade542a0fcb.js → standalone/web/.next/static/chunks/fc39a194539da104.js} +3 -3
  92. package/web/.next/{static/chunks/4e673433173ad456.js → standalone/web/.next/static/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/standalone/web/.next/static/static/chunks/{31208ade542a0fcb.js → 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/chunks/31208ade542a0fcb.js → static/chunks/fc39a194539da104.js} +3 -3
  100. /package/web/.next/standalone/web/.next/static/{static/tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
  101. /package/web/.next/standalone/web/.next/static/{static/tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
  102. /package/web/.next/standalone/web/.next/static/{static/tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
  103. /package/web/.next/standalone/web/.next/static/{tZkod5afiOX7T9AkN1yPO → static/XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
  104. /package/web/.next/standalone/web/.next/static/{tZkod5afiOX7T9AkN1yPO → static/XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
  105. /package/web/.next/standalone/web/.next/static/{tZkod5afiOX7T9AkN1yPO → static/XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
  106. /package/web/.next/static/{tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_buildManifest.js +0 -0
  107. /package/web/.next/static/{tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_clientMiddlewareManifest.json +0 -0
  108. /package/web/.next/static/{tZkod5afiOX7T9AkN1yPO → XB638PEDChQhwk6wSMrSh}/_ssgManifest.js +0 -0
@@ -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);
@@ -6478,6 +6510,21 @@ ${this.summary}`
6478
6510
 
6479
6511
  // src/agent/index.ts
6480
6512
  init_webhook();
6513
+ var MAX_SSE_FIELD_LENGTH = 8 * 1024;
6514
+ var SSE_PREVIEW_LENGTH = 2 * 1024;
6515
+ function truncateWriteFileInput(input) {
6516
+ const out = { ...input };
6517
+ for (const key of ["content", "old_string", "new_string"]) {
6518
+ const val = out[key];
6519
+ if (typeof val === "string" && val.length > MAX_SSE_FIELD_LENGTH) {
6520
+ out[key] = `${val.slice(0, SSE_PREVIEW_LENGTH)}
6521
+ ... (truncated)`;
6522
+ out[`${key}Truncated`] = true;
6523
+ out[`${key}Length`] = val.length;
6524
+ }
6525
+ }
6526
+ return out;
6527
+ }
6481
6528
  var approvalResolvers = /* @__PURE__ */ new Map();
6482
6529
  var Agent = class _Agent {
6483
6530
  session;
@@ -6721,8 +6768,11 @@ ${prompt}` });
6721
6768
  };
6722
6769
  let taskRecorder = null;
6723
6770
  const sessionId = this.session.id;
6771
+ const emit = options.writeSSE;
6724
6772
  const bashProgressHandler = (progress) => {
6725
6773
  options.onToolProgress?.({ toolName: "bash", data: progress });
6774
+ if (emit) emit(JSON.stringify({ type: "tool-progress", toolName: "bash", data: progress })).catch(() => {
6775
+ });
6726
6776
  const port = progress.browserStreamPort;
6727
6777
  if (port && progress.status === "started") {
6728
6778
  Promise.resolve().then(() => (init_stream_proxy(), stream_proxy_exports)).then(({ getOrCreateProxy: getOrCreateProxy2 }) => {
@@ -6731,7 +6781,17 @@ ${prompt}` });
6731
6781
  Promise.resolve().then(() => (init_recorder(), recorder_exports)).then(({ FrameRecorder: FrameRecorder2 }) => {
6732
6782
  taskRecorder = new FrameRecorder2(sessionId);
6733
6783
  taskRecorder.start();
6734
- proxy.on("frame", (frame) => taskRecorder?.addFrame(frame));
6784
+ });
6785
+ }
6786
+ if (proxy.listenerCount("frame") === 0) {
6787
+ proxy.on("frame", (frame) => {
6788
+ taskRecorder?.addFrame(frame);
6789
+ if (emit) emit(JSON.stringify({ type: "browser-frame", data: frame.data, metadata: frame.metadata })).catch(() => {
6790
+ });
6791
+ });
6792
+ proxy.on("status", (s) => {
6793
+ if (emit) emit(JSON.stringify({ type: "browser-status", ...s })).catch(() => {
6794
+ });
6735
6795
  });
6736
6796
  }
6737
6797
  });
@@ -6742,8 +6802,16 @@ ${prompt}` });
6742
6802
  workingDirectory: this.session.workingDirectory,
6743
6803
  skillsDirectories: config.resolvedSkillsDirectories,
6744
6804
  onBashProgress: bashProgressHandler,
6745
- onWriteFileProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "write_file", data: progress }) : void 0,
6746
- onSearchProgress: options.onToolProgress ? (progress) => options.onToolProgress({ toolName: "explore_agent", data: progress }) : void 0,
6805
+ onWriteFileProgress: (progress) => {
6806
+ options.onToolProgress?.({ toolName: "write_file", data: progress });
6807
+ if (emit) emit(JSON.stringify({ type: "tool-progress", toolName: "write_file", data: progress })).catch(() => {
6808
+ });
6809
+ },
6810
+ onSearchProgress: (progress) => {
6811
+ options.onToolProgress?.({ toolName: "explore_agent", data: progress });
6812
+ if (emit) emit(JSON.stringify({ type: "tool-progress", toolName: "explore_agent", data: progress })).catch(() => {
6813
+ });
6814
+ },
6747
6815
  taskTools: {
6748
6816
  outputSchema: options.taskConfig.outputSchema,
6749
6817
  onComplete
@@ -6761,6 +6829,9 @@ ${prompt}` });
6761
6829
 
6762
6830
  ${taskAddendum}`;
6763
6831
  fireWebhook("task.started", { prompt: options.prompt });
6832
+ if (emit) {
6833
+ await emit(JSON.stringify({ type: "data-user-message", data: { id: `user_${Date.now()}`, content: options.prompt } }));
6834
+ }
6764
6835
  await this.context.addUserMessage(options.prompt);
6765
6836
  let iteration = 0;
6766
6837
  while (iteration < maxIterations) {
@@ -6772,7 +6843,15 @@ ${taskAddendum}`;
6772
6843
  }
6773
6844
  const messages = await this.context.getMessages();
6774
6845
  const useAnthropic = isAnthropicModel(this.session.model);
6775
- const result = await generateText3({
6846
+ if (emit) {
6847
+ await emit(JSON.stringify({ type: "start", messageId: `msg_${Date.now()}` }));
6848
+ }
6849
+ let textStarted = false;
6850
+ let textId = `text_${Date.now()}`;
6851
+ let reasoningId = `reasoning_${Date.now()}`;
6852
+ let reasoningStarted = false;
6853
+ const toolCallStarts = /* @__PURE__ */ new Set();
6854
+ const iterStream = streamText2({
6776
6855
  model: resolveModel(this.session.model),
6777
6856
  system: systemPrompt,
6778
6857
  messages,
@@ -6781,21 +6860,94 @@ ${taskAddendum}`;
6781
6860
  abortSignal: options.abortSignal,
6782
6861
  providerOptions: useAnthropic ? {
6783
6862
  anthropic: {
6863
+ toolStreaming: true,
6784
6864
  thinking: { type: "enabled", budgetTokens: 1e4 }
6785
6865
  }
6786
6866
  } : void 0,
6787
- onStepFinish: (step) => {
6867
+ onStepFinish: async (step) => {
6788
6868
  options.onStepFinish?.(step);
6789
6869
  fireWebhook("task.step_finished", { iteration, text: step.text });
6870
+ if (emit) {
6871
+ if (textStarted) {
6872
+ await emit(JSON.stringify({ type: "text-end", id: textId }));
6873
+ textStarted = false;
6874
+ textId = `text_${Date.now()}`;
6875
+ }
6876
+ await emit(JSON.stringify({ type: "finish-step" }));
6877
+ }
6790
6878
  }
6791
6879
  });
6792
- const responseMessages = result.response.messages;
6880
+ for await (const part of iterStream.fullStream) {
6881
+ if (part.type === "text-delta") {
6882
+ if (emit) {
6883
+ if (!textStarted) {
6884
+ await emit(JSON.stringify({ type: "text-start", id: textId }));
6885
+ textStarted = true;
6886
+ }
6887
+ await emit(JSON.stringify({ type: "text-delta", id: textId, delta: part.text }));
6888
+ }
6889
+ } else if (part.type === "reasoning-start") {
6890
+ if (emit) {
6891
+ await emit(JSON.stringify({ type: "reasoning-start", id: reasoningId }));
6892
+ reasoningStarted = true;
6893
+ }
6894
+ } else if (part.type === "reasoning-delta") {
6895
+ if (emit) {
6896
+ await emit(JSON.stringify({ type: "reasoning-delta", id: reasoningId, delta: part.text }));
6897
+ }
6898
+ } else if (part.type === "reasoning-end") {
6899
+ if (emit && reasoningStarted) {
6900
+ await emit(JSON.stringify({ type: "reasoning-end", id: reasoningId }));
6901
+ reasoningStarted = false;
6902
+ reasoningId = `reasoning_${Date.now()}`;
6903
+ }
6904
+ } else if (part.type === "tool-call-streaming-start") {
6905
+ if (emit) {
6906
+ const p = part;
6907
+ await emit(JSON.stringify({ type: "tool-input-start", toolCallId: p.toolCallId, toolName: p.toolName }));
6908
+ toolCallStarts.add(p.toolCallId);
6909
+ }
6910
+ } else if (part.type === "tool-call-delta") {
6911
+ if (emit) {
6912
+ const p = part;
6913
+ await emit(JSON.stringify({ type: "tool-input-delta", toolCallId: p.toolCallId, argsTextDelta: p.argsTextDelta }));
6914
+ }
6915
+ } else if (part.type === "tool-call") {
6916
+ if (emit) {
6917
+ if (!toolCallStarts.has(part.toolCallId)) {
6918
+ await emit(JSON.stringify({ type: "tool-input-start", toolCallId: part.toolCallId, toolName: part.toolName }));
6919
+ toolCallStarts.add(part.toolCallId);
6920
+ }
6921
+ const safeInput = part.toolName === "write_file" && part.input && typeof part.input === "object" ? truncateWriteFileInput(part.input) : part.input;
6922
+ await emit(JSON.stringify({ type: "tool-input-available", toolCallId: part.toolCallId, toolName: part.toolName, input: safeInput }));
6923
+ }
6924
+ } else if (part.type === "tool-result") {
6925
+ if (emit) {
6926
+ await emit(JSON.stringify({ type: "tool-output-available", toolCallId: part.toolCallId, output: part.output }));
6927
+ }
6928
+ } else if (part.type === "error") {
6929
+ console.error("Task stream error:", part.error);
6930
+ if (emit) {
6931
+ await emit(JSON.stringify({ type: "error", errorText: String(part.error) }));
6932
+ }
6933
+ }
6934
+ }
6935
+ if (emit && textStarted) {
6936
+ await emit(JSON.stringify({ type: "text-end", id: textId }));
6937
+ }
6938
+ if (emit && reasoningStarted) {
6939
+ await emit(JSON.stringify({ type: "reasoning-end", id: reasoningId }));
6940
+ }
6941
+ const iterResponse = await iterStream.response;
6942
+ const responseMessages = iterResponse.messages;
6793
6943
  await this.context.addResponseMessages(responseMessages);
6794
- if (result.text) {
6795
- options.onText?.(result.text);
6796
- fireWebhook("task.message", { iteration, text: result.text });
6944
+ const resultText = await iterStream.text;
6945
+ const resultSteps = await iterStream.steps;
6946
+ if (resultText) {
6947
+ options.onText?.(resultText);
6948
+ fireWebhook("task.message", { iteration, text: resultText });
6797
6949
  }
6798
- for (const step of result.steps) {
6950
+ for (const step of resultSteps) {
6799
6951
  if (step.toolCalls) {
6800
6952
  for (const tc of step.toolCalls) {
6801
6953
  options.onToolCall?.({ toolCallId: tc.toolCallId, toolName: tc.toolName, input: tc.args });
@@ -6848,9 +7000,11 @@ ${taskAddendum}`;
6848
7000
  iterations: iteration
6849
7001
  };
6850
7002
  }
6851
- await this.context.addUserMessage(
6852
- "Continue working on the task. Before calling `complete_task`, VERIFY your work is correct \u2014 re-read edited files, run the linter, run tests if applicable, and check the browser/server if you made UI or API changes. Make sure you searched the right directories and found everything relevant. When fully verified, call `complete_task` with the result. If you cannot complete it, call `task_failed` with a reason."
6853
- );
7003
+ const continuationPrompt = "Continue working on the task. Before calling `complete_task`, VERIFY your work is correct \u2014 re-read edited files, run the linter, run tests if applicable, and check the browser/server if you made UI or API changes. Make sure you searched the right directories and found everything relevant. When fully verified, call `complete_task` with the result. If you cannot complete it, call `task_failed` with a reason.";
7004
+ if (emit) {
7005
+ await emit(JSON.stringify({ type: "data-user-message", data: { id: `user_${Date.now()}`, content: continuationPrompt } }));
7006
+ }
7007
+ await this.context.addUserMessage(continuationPrompt);
6854
7008
  }
6855
7009
  const timeoutError = `Task did not complete within ${maxIterations} iterations`;
6856
7010
  const timeoutRecordingUrls = await this.finishTaskRecording(taskRecorder);
@@ -7941,11 +8095,19 @@ var cleanupInterval = setInterval(() => {
7941
8095
  }
7942
8096
  }, 6e4);
7943
8097
  cleanupInterval.unref();
8098
+ var publishCount = 0;
8099
+ var lastPublishLog = 0;
7944
8100
  var publisher = {
7945
8101
  connect: async () => {
7946
8102
  },
7947
8103
  publish: async (channel, message) => {
7948
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
+ }
7949
8111
  if (subscribers) {
7950
8112
  for (const callback of subscribers) {
7951
8113
  setImmediate(() => callback(message));
@@ -7984,9 +8146,12 @@ var subscriber = {
7984
8146
  channels.set(channel, /* @__PURE__ */ new Set());
7985
8147
  }
7986
8148
  channels.get(channel).add(callback);
8149
+ console.log(`[ResumableStream] Subscribe to channel "${channel}" (total subscribers: ${channels.get(channel).size})`);
7987
8150
  },
7988
8151
  unsubscribe: async (channel) => {
8152
+ const count = channels.get(channel)?.size ?? 0;
7989
8153
  channels.delete(channel);
8154
+ console.log(`[ResumableStream] Unsubscribe from channel "${channel}" (removed ${count} subscribers)`);
7990
8155
  }
7991
8156
  };
7992
8157
  var streamContext = createResumableStreamContext({
@@ -8172,19 +8337,28 @@ function createAgentStreamProducer(sessionId, prompt, streamId, attachments) {
8172
8337
  const toolCallStarts = /* @__PURE__ */ new Set();
8173
8338
  const abortController = new AbortController();
8174
8339
  streamAbortControllers.set(streamId, abortController);
8340
+ let sseEventCount = 0;
8341
+ let sseBrowserFrameCount = 0;
8342
+ let sseWriteErrors = 0;
8175
8343
  const writeSSE = async (data) => {
8176
8344
  if (writerClosed) return;
8177
8345
  try {
8346
+ sseEventCount++;
8178
8347
  await writer.write(`data: ${data}
8179
8348
 
8180
8349
  `);
8181
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
+ }
8182
8355
  writerClosed = true;
8183
8356
  }
8184
8357
  };
8185
8358
  const safeClose = async () => {
8186
8359
  if (writerClosed) return;
8187
8360
  try {
8361
+ console.log(`[SSE:${streamId}] Stream closing. Total events: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}, write errors: ${sseWriteErrors}`);
8188
8362
  writerClosed = true;
8189
8363
  await writer.close();
8190
8364
  } catch {
@@ -8307,35 +8481,47 @@ ${prompt}` });
8307
8481
  const browserPort = progress.data?.browserStreamPort;
8308
8482
  const browserClosed = progress.data?.browserClosed;
8309
8483
  if (progress.toolName === "bash" && browserClosed) {
8310
- 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}`);
8311
8485
  destroyProxy(sessionId);
8312
8486
  } else if (progress.toolName === "bash" && browserPort) {
8313
- 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}`);
8314
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")}`);
8315
8490
  if (!sessionRecorders.has(sessionId)) {
8316
8491
  const recorder = new FrameRecorder(sessionId);
8317
8492
  recorder.start();
8318
8493
  sessionRecorders.set(sessionId, recorder);
8319
8494
  }
8320
8495
  if (proxy.listenerCount("frame") === 0) {
8496
+ console.log(`[BROWSER-STREAM:${streamId}] Attaching frame+status listeners to proxy`);
8321
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
+ }
8322
8504
  const rec = sessionRecorders.get(sessionId);
8323
8505
  rec?.addFrame(frame);
8324
8506
  writeSSE(JSON.stringify({
8325
8507
  type: "browser-frame",
8326
8508
  data: frame.data,
8327
8509
  metadata: frame.metadata
8328
- })).catch(() => {
8510
+ })).catch((err) => {
8511
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-frame via SSE:`, err);
8329
8512
  });
8330
8513
  });
8331
8514
  proxy.on("status", (s) => {
8332
- 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}`);
8333
8516
  writeSSE(JSON.stringify({
8334
8517
  type: "browser-status",
8335
8518
  ...s
8336
- })).catch(() => {
8519
+ })).catch((err) => {
8520
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-status via SSE:`, err);
8337
8521
  });
8338
8522
  });
8523
+ } else {
8524
+ console.log(`[BROWSER-STREAM:${streamId}] Frame listeners already attached (count=${proxy.listenerCount("frame")}), skipping`);
8339
8525
  }
8340
8526
  }
8341
8527
  },
@@ -8525,14 +8711,17 @@ ${prompt}` });
8525
8711
  }
8526
8712
  await messageQueries.create(id, { role: "user", content: userMessageContent });
8527
8713
  const streamId = `stream_${id}_${nanoid6(10)}`;
8714
+ console.log(`[STREAM] Creating stream ${streamId} for session ${id}`);
8528
8715
  await activeStreamQueries.create(id, streamId);
8529
8716
  const stream = await streamContext.resumableStream(
8530
8717
  streamId,
8531
8718
  createAgentStreamProducer(id, prompt, streamId, streamAttachments)
8532
8719
  );
8533
8720
  if (!stream) {
8721
+ console.error(`[STREAM] Failed to create resumable stream ${streamId}`);
8534
8722
  return c.json({ error: "Failed to create stream" }, 500);
8535
8723
  }
8724
+ console.log(`[STREAM] Stream ${streamId} created successfully`);
8536
8725
  const encodedStream = stream.pipeThrough(new TextEncoderStream());
8537
8726
  return new Response(encodedStream, {
8538
8727
  headers: {
@@ -8561,17 +8750,20 @@ agents.get("/:id/watch", async (c) => {
8561
8750
  }
8562
8751
  streamId = activeStream.streamId;
8563
8752
  }
8753
+ console.log(`[STREAM] Watch request for session ${sessionId}, streamId=${streamId}, resumeAt=${resumeAt || "none"}`);
8564
8754
  const stream = await streamContext.resumeExistingStream(
8565
8755
  streamId,
8566
8756
  resumeAt ? parseInt(resumeAt, 10) : void 0
8567
8757
  );
8568
8758
  if (!stream) {
8759
+ console.log(`[STREAM] Watch failed \u2014 stream ${streamId} is no longer active`);
8569
8760
  return c.json({
8570
8761
  error: "Stream is no longer active",
8571
8762
  streamId,
8572
8763
  hint: "The stream may have finished. Check /agents/:id/approvals or start a new run."
8573
8764
  }, 422);
8574
8765
  }
8766
+ console.log(`[STREAM] Client watching stream ${streamId}`);
8575
8767
  const encodedStream = stream.pipeThrough(new TextEncoderStream());
8576
8768
  return new Response(encodedStream, {
8577
8769
  headers: {
@@ -8733,19 +8925,28 @@ agents.post(
8733
8925
  const toolCallStarts = /* @__PURE__ */ new Set();
8734
8926
  const abortController = new AbortController();
8735
8927
  streamAbortControllers.set(streamId, abortController);
8928
+ let sseEventCount = 0;
8929
+ let sseBrowserFrameCount = 0;
8930
+ let sseWriteErrors = 0;
8736
8931
  const writeSSE = async (data) => {
8737
8932
  if (writerClosed) return;
8738
8933
  try {
8934
+ sseEventCount++;
8739
8935
  await writer.write(`data: ${data}
8740
8936
 
8741
8937
  `);
8742
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
+ }
8743
8943
  writerClosed = true;
8744
8944
  }
8745
8945
  };
8746
8946
  const safeClose = async () => {
8747
8947
  if (writerClosed) return;
8748
8948
  try {
8949
+ console.log(`[SSE:${streamId}] Stream closing. Total events: ${sseEventCount}, browser frames: ${sseBrowserFrameCount}, write errors: ${sseWriteErrors}`);
8749
8950
  writerClosed = true;
8750
8951
  await writer.close();
8751
8952
  } catch {
@@ -8805,35 +9006,47 @@ agents.post(
8805
9006
  const browserPort = progress.data?.browserStreamPort;
8806
9007
  const browserClosed = progress.data?.browserClosed;
8807
9008
  if (progress.toolName === "bash" && browserClosed) {
8808
- console.log(`[BROWSER-STREAM] agent-browser close detected`);
9009
+ console.log(`[BROWSER-STREAM:${streamId}] agent-browser close detected, destroying proxy for session ${session.id}`);
8809
9010
  destroyProxy(session.id);
8810
9011
  } else if (progress.toolName === "bash" && browserPort) {
8811
- 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}`);
8812
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")}`);
8813
9015
  if (!sessionRecorders.has(session.id)) {
8814
9016
  const recorder = new FrameRecorder(session.id);
8815
9017
  recorder.start();
8816
9018
  sessionRecorders.set(session.id, recorder);
8817
9019
  }
8818
9020
  if (proxy.listenerCount("frame") === 0) {
9021
+ console.log(`[BROWSER-STREAM:${streamId}] Attaching frame+status listeners to proxy`);
8819
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
+ }
8820
9029
  const rec = sessionRecorders.get(session.id);
8821
9030
  rec?.addFrame(frame);
8822
9031
  writeSSE(JSON.stringify({
8823
9032
  type: "browser-frame",
8824
9033
  data: frame.data,
8825
9034
  metadata: frame.metadata
8826
- })).catch(() => {
9035
+ })).catch((err) => {
9036
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-frame via SSE:`, err);
8827
9037
  });
8828
9038
  });
8829
9039
  proxy.on("status", (s) => {
8830
- 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}`);
8831
9041
  writeSSE(JSON.stringify({
8832
9042
  type: "browser-status",
8833
9043
  ...s
8834
- })).catch(() => {
9044
+ })).catch((err) => {
9045
+ console.warn(`[BROWSER-STREAM:${streamId}] Failed to send browser-status via SSE:`, err);
8835
9046
  });
8836
9047
  });
9048
+ } else {
9049
+ console.log(`[BROWSER-STREAM:${streamId}] Frame listeners already attached (count=${proxy.listenerCount("frame")}), skipping`);
8837
9050
  }
8838
9051
  }
8839
9052
  },
@@ -9482,6 +9695,7 @@ init_db();
9482
9695
  import { Hono as Hono5 } from "hono";
9483
9696
  import { zValidator as zValidator5 } from "@hono/zod-validator";
9484
9697
  import { z as z19 } from "zod";
9698
+ import { nanoid as nanoid7 } from "nanoid";
9485
9699
  init_config();
9486
9700
  var tasks = new Hono5();
9487
9701
  var taskAbortControllers = /* @__PURE__ */ new Map();
@@ -9519,45 +9733,74 @@ tasks.post(
9519
9733
  const taskId = agent.sessionId;
9520
9734
  const abortController = new AbortController();
9521
9735
  taskAbortControllers.set(taskId, abortController);
9522
- (async () => {
9523
- try {
9524
- await agent.runTask({
9525
- prompt: body.prompt,
9526
- taskConfig,
9527
- abortSignal: abortController.signal
9528
- });
9529
- } catch (err) {
9530
- if (err.name === "AbortError" || abortController.signal.aborted) {
9531
- console.log(`[TASK] Task ${taskId} was cancelled`);
9532
- } else {
9533
- console.error(`[TASK] Error in task ${taskId}:`, err.message);
9534
- const errorMsg = err.message || "Unknown error";
9535
- const failedTask = {
9536
- ...taskConfig,
9537
- status: "failed",
9538
- error: errorMsg
9539
- };
9540
- await sessionQueries.update(taskId, {
9541
- config: {
9542
- toolApprovals: { bash: false, write_file: false, read_file: false },
9543
- task: failedTask
9544
- }
9736
+ const streamId = `stream_${taskId}_${nanoid7(10)}`;
9737
+ await activeStreamQueries.create(taskId, streamId);
9738
+ const taskStreamProducer = () => {
9739
+ const { readable, writable } = new TransformStream();
9740
+ const writer = writable.getWriter();
9741
+ let writerClosed = false;
9742
+ const writeSSE = async (data) => {
9743
+ if (writerClosed) return;
9744
+ try {
9745
+ await writer.write(`data: ${data}
9746
+
9747
+ `);
9748
+ } catch {
9749
+ writerClosed = true;
9750
+ }
9751
+ };
9752
+ (async () => {
9753
+ await writeSSE(JSON.stringify({ type: "data-stream-id", streamId }));
9754
+ try {
9755
+ await agent.runTask({
9756
+ prompt: body.prompt,
9757
+ taskConfig,
9758
+ abortSignal: abortController.signal,
9759
+ writeSSE
9545
9760
  });
9546
- if (taskConfig.webhookUrl) {
9547
- const { sendWebhook: sendWebhook2 } = await Promise.resolve().then(() => (init_webhook(), webhook_exports));
9548
- sendWebhook2(taskConfig.webhookUrl, {
9549
- type: "task.failed",
9550
- taskId,
9551
- sessionId: taskId,
9552
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9553
- data: { status: "failed", error: errorMsg }
9761
+ await writeSSE(JSON.stringify({ type: "finish" }));
9762
+ } catch (err) {
9763
+ if (err.name === "AbortError" || abortController.signal.aborted) {
9764
+ console.log(`[TASK] Task ${taskId} was cancelled`);
9765
+ await writeSSE(JSON.stringify({ type: "abort" }));
9766
+ } else {
9767
+ console.error(`[TASK] Error in task ${taskId}:`, err.message);
9768
+ const errorMsg = err.message || "Unknown error";
9769
+ await writeSSE(JSON.stringify({ type: "error", errorText: errorMsg }));
9770
+ const failedTask = {
9771
+ ...taskConfig,
9772
+ status: "failed",
9773
+ error: errorMsg
9774
+ };
9775
+ await sessionQueries.update(taskId, {
9776
+ config: {
9777
+ toolApprovals: { bash: false, write_file: false, read_file: false },
9778
+ task: failedTask
9779
+ }
9554
9780
  });
9781
+ if (taskConfig.webhookUrl) {
9782
+ const { sendWebhook: sendWebhook2 } = await Promise.resolve().then(() => (init_webhook(), webhook_exports));
9783
+ sendWebhook2(taskConfig.webhookUrl, {
9784
+ type: "task.failed",
9785
+ taskId,
9786
+ sessionId: taskId,
9787
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9788
+ data: { status: "failed", error: errorMsg }
9789
+ });
9790
+ }
9555
9791
  }
9792
+ } finally {
9793
+ await writeSSE("[DONE]");
9794
+ writer.close().catch(() => {
9795
+ });
9796
+ await activeStreamQueries.finish(streamId).catch(() => {
9797
+ });
9798
+ taskAbortControllers.delete(taskId);
9556
9799
  }
9557
- } finally {
9558
- taskAbortControllers.delete(taskId);
9559
- }
9560
- })();
9800
+ })();
9801
+ return readable;
9802
+ };
9803
+ await streamContext.resumableStream(streamId, taskStreamProducer);
9561
9804
  return c.json({ taskId, status: "running" }, 201);
9562
9805
  }
9563
9806
  );