sparkecoder 0.1.142 → 0.1.143

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 (111) hide show
  1. package/dist/agent/index.d.ts +3 -3
  2. package/dist/agent/index.js +105 -19
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +109 -23
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +2 -2
  7. package/dist/{index-Cl_eUatM.d.ts → index-BAsQWqZj.d.ts} +96 -96
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.js +109 -23
  10. package/dist/index.js.map +1 -1
  11. package/dist/{schema-BSz4MzhJ.d.ts → schema-Dz-wABVY.d.ts} +3 -3
  12. package/dist/{search-DOzC4ojH.d.ts → search-CVVfuBPZ.d.ts} +4 -4
  13. package/dist/server/index.js +109 -23
  14. package/dist/server/index.js.map +1 -1
  15. package/dist/tools/index.d.ts +3 -3
  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/_global-error.html +2 -2
  22. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  23. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  24. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  25. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  31. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  32. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
  37. package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
  38. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
  39. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
  40. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
  41. package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
  43. package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
  44. package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
  48. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
  50. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
  51. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  52. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
  60. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  61. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  62. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
  65. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  70. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  71. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  73. package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
  74. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
  77. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
  78. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  79. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  80. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  81. package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
  82. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
  83. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
  84. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
  85. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  86. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
  87. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  88. package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
  89. package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
  90. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
  91. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
  92. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
  93. package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  94. package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  95. package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  96. package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  97. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  98. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  99. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  100. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  101. package/web/.next/standalone/web/runtime-config.json +2 -2
  102. package/web/.next/standalone/web/src/app/(main)/settings/page.tsx +1 -1
  103. /package/web/.next/standalone/web/.next/static/{EH_lLivb0xQQlTlBqPnCj → static/ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
  104. /package/web/.next/standalone/web/.next/static/{EH_lLivb0xQQlTlBqPnCj → static/ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
  105. /package/web/.next/standalone/web/.next/static/{EH_lLivb0xQQlTlBqPnCj → static/ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
  106. /package/web/.next/standalone/web/.next/static/{static/EH_lLivb0xQQlTlBqPnCj → ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
  107. /package/web/.next/standalone/web/.next/static/{static/EH_lLivb0xQQlTlBqPnCj → ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
  108. /package/web/.next/standalone/web/.next/static/{static/EH_lLivb0xQQlTlBqPnCj → ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
  109. /package/web/.next/static/{EH_lLivb0xQQlTlBqPnCj → ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
  110. /package/web/.next/static/{EH_lLivb0xQQlTlBqPnCj → ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
  111. /package/web/.next/static/{EH_lLivb0xQQlTlBqPnCj → ySf1FIgV1p24IEJCK27zG}/_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: "completed" | "error" | "active" | "waiting";
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;
@@ -814,7 +814,7 @@ declare const terminals: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
814
814
  tableName: "terminals";
815
815
  dataType: "string";
816
816
  columnType: "SQLiteText";
817
- data: "error" | "running" | "stopped";
817
+ data: "running" | "error" | "stopped";
818
818
  driverParam: string;
819
819
  notNull: true;
820
820
  hasDefault: true;
@@ -16,11 +16,11 @@ interface BashToolOptions {
16
16
  declare function createBashTool(options: BashToolOptions): ai.Tool<{
17
17
  background: boolean;
18
18
  id?: string | undefined;
19
- command?: string | undefined;
20
19
  input?: string | undefined;
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;
@@ -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: "running" | "completed" | "error" | "stopped";
70
70
  message?: undefined;
71
71
  error?: undefined;
72
72
  } | {
@@ -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;
@@ -9458,9 +9458,9 @@ function slackEventToInboundResult(event, opts = {}) {
9458
9458
  if (event.type === "message" && event.subtype && IGNORED_MESSAGE_SUBTYPES.has(event.subtype)) {
9459
9459
  return { event: null, dropReason: "ignored_subtype" };
9460
9460
  }
9461
- const isDm = event.type === "message" && event.channel_type === "im";
9461
+ const isDm = event.type === "message" && (event.channel_type === "im" || event.channel_type === "mpim");
9462
9462
  const isThreadReply = event.type === "message" && !isDm && typeof event.thread_ts === "string" && event.thread_ts !== event.ts;
9463
- const isNonThreadChannelMsg = event.type === "message" && !isDm && !isThreadReply && (event.channel_type === "channel" || event.channel_type === "group" || event.channel_type === "mpim" || // Some payload shapes omit channel_type for channel messages.
9463
+ const isNonThreadChannelMsg = event.type === "message" && !isDm && !isThreadReply && (event.channel_type === "channel" || event.channel_type === "group" || // Some payload shapes omit channel_type for channel messages.
9464
9464
  typeof event.channel === "string");
9465
9465
  if (event.type !== "app_mention" && !isDm && !isThreadReply) {
9466
9466
  if (isNonThreadChannelMsg) {
@@ -9766,8 +9766,31 @@ function formatBytes(n) {
9766
9766
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
9767
9767
  return `${(n / 1024 / 1024).toFixed(2)} MB`;
9768
9768
  }
9769
- function sleep(ms) {
9770
- return new Promise((resolve13) => setTimeout(resolve13, ms));
9769
+ function abortError() {
9770
+ const err = new Error("aborted");
9771
+ err.name = "AbortError";
9772
+ return err;
9773
+ }
9774
+ function throwIfAborted(signal) {
9775
+ if (signal?.aborted) throw abortError();
9776
+ }
9777
+ function isAbortLike(err) {
9778
+ return err?.name === "AbortError" || String(err?.message || err).toLowerCase().includes("aborted");
9779
+ }
9780
+ function sleep(ms, signal) {
9781
+ throwIfAborted(signal);
9782
+ return new Promise((resolve13, reject) => {
9783
+ const t = setTimeout(() => {
9784
+ signal?.removeEventListener("abort", onAbort);
9785
+ resolve13();
9786
+ }, ms);
9787
+ const onAbort = () => {
9788
+ clearTimeout(t);
9789
+ signal?.removeEventListener("abort", onAbort);
9790
+ reject(abortError());
9791
+ };
9792
+ signal?.addEventListener("abort", onAbort, { once: true });
9793
+ });
9771
9794
  }
9772
9795
  function imageMagic(bytes) {
9773
9796
  if (bytes.length < 12) return null;
@@ -9787,19 +9810,21 @@ function validateDownloadedBytes(bytes, declaredContentType) {
9787
9810
  if (!actual) return "invalid_image_bytes";
9788
9811
  return null;
9789
9812
  }
9790
- async function fetchSlackPrivateFile(sourceUrl, botToken) {
9813
+ async function fetchSlackPrivateFile(sourceUrl, botToken, signal) {
9791
9814
  let lastError = "unknown";
9792
9815
  for (let attempt = 0; attempt < 3; attempt++) {
9793
9816
  try {
9817
+ throwIfAborted(signal);
9794
9818
  const res = await fetch(sourceUrl, {
9795
- headers: { Authorization: `Bearer ${botToken}` }
9819
+ headers: { Authorization: `Bearer ${botToken}` },
9820
+ signal
9796
9821
  });
9797
9822
  if (res.status === 429 || res.status >= 500) {
9798
9823
  lastError = `slack_fetch_${res.status}`;
9799
9824
  const retryAfter = Number(res.headers.get("retry-after"));
9800
9825
  const waitMs = Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter * 1e3, 2e3) : 250 * (attempt + 1);
9801
9826
  if (attempt < 2) {
9802
- await sleep(waitMs);
9827
+ await sleep(waitMs, signal);
9803
9828
  continue;
9804
9829
  }
9805
9830
  }
@@ -9810,25 +9835,58 @@ async function fetchSlackPrivateFile(sourceUrl, botToken) {
9810
9835
  if (Number.isFinite(contentLength) && contentLength > MAX_BYTES) {
9811
9836
  return { ok: false, error: "size_exceeded" };
9812
9837
  }
9813
- const ab = await res.arrayBuffer();
9814
- if (ab.byteLength > MAX_BYTES) {
9815
- return { ok: false, error: "size_exceeded" };
9816
- }
9817
- return { ok: true, bytes: Buffer.from(ab) };
9838
+ return await readResponseBodyWithCap(res, signal);
9818
9839
  } catch (err) {
9840
+ if (isAbortLike(err) || signal?.aborted) {
9841
+ return { ok: false, error: "aborted" };
9842
+ }
9819
9843
  lastError = `slack_fetch_error:${err?.message || "unknown"}`;
9820
9844
  if (attempt < 2) {
9821
- await sleep(250 * (attempt + 1));
9845
+ await sleep(250 * (attempt + 1), signal);
9822
9846
  continue;
9823
9847
  }
9824
9848
  }
9825
9849
  }
9826
9850
  return { ok: false, error: lastError };
9827
9851
  }
9828
- function withTimeout(p, ms, label) {
9852
+ async function readResponseBodyWithCap(res, signal) {
9853
+ const body = res.body;
9854
+ if (!body) {
9855
+ const ab = await res.arrayBuffer();
9856
+ if (ab.byteLength > MAX_BYTES) return { ok: false, error: "size_exceeded" };
9857
+ return { ok: true, bytes: Buffer.from(ab) };
9858
+ }
9859
+ const reader = body.getReader();
9860
+ const chunks = [];
9861
+ let total = 0;
9862
+ try {
9863
+ while (true) {
9864
+ throwIfAborted(signal);
9865
+ const { done, value } = await reader.read();
9866
+ if (done) break;
9867
+ if (!value) continue;
9868
+ total += value.byteLength;
9869
+ if (total > MAX_BYTES) {
9870
+ await reader.cancel().catch(() => void 0);
9871
+ return { ok: false, error: "size_exceeded" };
9872
+ }
9873
+ chunks.push(Buffer.from(value));
9874
+ }
9875
+ } catch (err) {
9876
+ await reader.cancel().catch(() => void 0);
9877
+ if (isAbortLike(err) || signal?.aborted) return { ok: false, error: "aborted" };
9878
+ throw err;
9879
+ }
9880
+ return { ok: true, bytes: Buffer.concat(chunks, total) };
9881
+ }
9882
+ function withAbortTimeout(run, ms, label) {
9829
9883
  return new Promise((resolve13, reject) => {
9830
- const t = setTimeout(() => reject(new Error(`${label}_timeout`)), ms);
9831
- p.then(
9884
+ const controller = new AbortController();
9885
+ const t = setTimeout(() => {
9886
+ controller.abort();
9887
+ reject(new Error(`${label}_timeout`));
9888
+ }, ms);
9889
+ run(controller.signal).then(
9832
9890
  (v) => {
9833
9891
  clearTimeout(t);
9834
9892
  resolve13(v);
@@ -9840,7 +9898,8 @@ function withTimeout(p, ms, label) {
9840
9898
  );
9841
9899
  });
9842
9900
  }
9843
- async function ingestOne(file, sessionId, botToken) {
9901
+ async function ingestOne(file, sessionId, botToken, signal) {
9902
+ throwIfAborted(signal);
9844
9903
  const fileName = inferFileName(file);
9845
9904
  const contentType = inferContentType(file);
9846
9905
  const declaredSize = typeof file.size === "number" ? file.size : 0;
@@ -9858,7 +9917,8 @@ async function ingestOne(file, sessionId, botToken) {
9858
9917
  return { ...base, shortUrl: null, error: "size_exceeded" };
9859
9918
  }
9860
9919
  let bytes;
9861
- const fetched = await fetchSlackPrivateFile(sourceUrl, botToken);
9920
+ const fetched = await fetchSlackPrivateFile(sourceUrl, botToken, signal);
9921
+ throwIfAborted(signal);
9862
9922
  if (!fetched.ok) {
9863
9923
  return { ...base, shortUrl: null, error: fetched.error };
9864
9924
  }
@@ -9871,18 +9931,27 @@ async function ingestOne(file, sessionId, botToken) {
9871
9931
  return { ...base, sizeBytes: bytes.length, shortUrl: null, error: byteError };
9872
9932
  }
9873
9933
  const { storageQueries: storageQueries2 } = await Promise.resolve().then(() => (init_remote(), remote_exports));
9874
- let upload;
9934
+ let upload = null;
9875
9935
  try {
9936
+ throwIfAborted(signal);
9876
9937
  upload = await storageQueries2.getUploadUrl(sessionId, fileName, contentType, "slack");
9938
+ throwIfAborted(signal);
9877
9939
  } catch (err) {
9940
+ if (isAbortLike(err) || signal.aborted) {
9941
+ if (upload?.fileId) await cleanupAbortedUpload(storageQueries2, upload.fileId);
9942
+ throw err;
9943
+ }
9878
9944
  return { ...base, sizeBytes: bytes.length, shortUrl: null, error: `presign_failed:${err?.message || "unknown"}` };
9879
9945
  }
9880
9946
  try {
9947
+ throwIfAborted(signal);
9881
9948
  const putRes = await fetch(upload.uploadUrl, {
9882
9949
  method: "PUT",
9883
9950
  headers: { "Content-Type": contentType },
9884
- body: bytes
9951
+ body: bytes,
9952
+ signal
9885
9953
  });
9954
+ throwIfAborted(signal);
9886
9955
  if (!putRes.ok) {
9887
9956
  return {
9888
9957
  ...base,
@@ -9892,6 +9961,10 @@ async function ingestOne(file, sessionId, botToken) {
9892
9961
  };
9893
9962
  }
9894
9963
  } catch (err) {
9964
+ if (isAbortLike(err) || signal.aborted) {
9965
+ await cleanupAbortedUpload(storageQueries2, upload.fileId);
9966
+ throw err;
9967
+ }
9895
9968
  return {
9896
9969
  ...base,
9897
9970
  sizeBytes: bytes.length,
@@ -9900,8 +9973,13 @@ async function ingestOne(file, sessionId, botToken) {
9900
9973
  };
9901
9974
  }
9902
9975
  try {
9976
+ throwIfAborted(signal);
9903
9977
  await storageQueries2.updateFile(upload.fileId, { sizeBytes: bytes.length });
9904
9978
  } catch (err) {
9979
+ if (isAbortLike(err) || signal.aborted) {
9980
+ await cleanupAbortedUpload(storageQueries2, upload.fileId);
9981
+ throw err;
9982
+ }
9905
9983
  console.warn(`[slack-files] sizeBytes patch failed for ${upload.fileId}:`, err?.message || err);
9906
9984
  }
9907
9985
  const shortUrl = upload.shortUrl || // Defensive fallback: build it from the upload URL's origin if the
@@ -9913,6 +9991,14 @@ async function ingestOne(file, sessionId, botToken) {
9913
9991
  shortUrl
9914
9992
  };
9915
9993
  }
9994
+ async function cleanupAbortedUpload(storageQueries2, fileId) {
9995
+ if (typeof storageQueries2?.deleteFile !== "function") return;
9996
+ try {
9997
+ await storageQueries2.deleteFile(fileId);
9998
+ } catch (err) {
9999
+ console.warn(`[slack-files] cleanup after aborted upload failed for ${fileId}:`, err?.message || err);
10000
+ }
10001
+ }
9916
10002
  function inferShortUrlFromUploadUrl(uploadUrl, fileId) {
9917
10003
  try {
9918
10004
  const u = new URL(uploadUrl);
@@ -9952,7 +10038,7 @@ async function ingestSlackFiles(files, sessionId, options = {}) {
9952
10038
  const startedAt = Date.now();
9953
10039
  const pipeline = Promise.allSettled(
9954
10040
  files.map(
9955
- (f) => withTimeout(ingestOne(f, sessionId, botToken), timeoutMs, `ingest:${f.id}`).catch((err) => {
10041
+ (f) => withAbortTimeout((signal) => ingestOne(f, sessionId, botToken, signal), timeoutMs, `ingest:${f.id}`).catch((err) => {
9956
10042
  if (String(err?.message || err).includes("_timeout")) {
9957
10043
  return {
9958
10044
  slackFileId: f.id,
@@ -16429,7 +16515,7 @@ slack.post("/events", async (c) => {
16429
16515
  const self = await ensureSlackSelfIdentity();
16430
16516
  const { event: inbound, dropReason } = slackEventToInboundResult(ev, { self });
16431
16517
  if (inbound) {
16432
- const isThreadReply = ev.type === "message" && ev.channel_type !== "im" && typeof ev.thread_ts === "string" && ev.thread_ts !== ev.ts;
16518
+ const isThreadReply = ev.type === "message" && ev.channel_type !== "im" && ev.channel_type !== "mpim" && typeof ev.thread_ts === "string" && ev.thread_ts !== ev.ts;
16433
16519
  if (isThreadReply) {
16434
16520
  const ours = isThreadOwned(ev.channel, ev.thread_ts) || await botParticipatedInThread(ev.channel, ev.thread_ts);
16435
16521
  if (!ours) {
@@ -16442,7 +16528,7 @@ slack.post("/events", async (c) => {
16442
16528
  if (ev.type === "app_mention" && ev.channel && (ev.thread_ts || ev.ts)) {
16443
16529
  markThreadOwned(ev.channel, ev.thread_ts || ev.ts);
16444
16530
  }
16445
- if (ev.type === "message" && ev.channel_type === "im" && ev.channel && (ev.thread_ts || ev.ts)) {
16531
+ if (ev.type === "message" && (ev.channel_type === "im" || ev.channel_type === "mpim") && ev.channel && (ev.thread_ts || ev.ts)) {
16446
16532
  markThreadOwned(ev.channel, ev.thread_ts || ev.ts);
16447
16533
  }
16448
16534
  if (wasHandled(ev.channel, ev.ts)) {