sparkecoder 0.1.141 → 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/{T0ihp-rxOYsKtonqcYLfo → static/ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
  104. /package/web/.next/standalone/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → static/ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
  105. /package/web/.next/standalone/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → static/ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
  106. /package/web/.next/standalone/web/.next/static/{static/T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
  107. /package/web/.next/standalone/web/.next/static/{static/T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
  108. /package/web/.next/standalone/web/.next/static/{static/T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
  109. /package/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
  110. /package/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
  111. /package/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
package/dist/cli.js CHANGED
@@ -10201,9 +10201,9 @@ function slackEventToInboundResult(event, opts = {}) {
10201
10201
  if (event.type === "message" && event.subtype && IGNORED_MESSAGE_SUBTYPES.has(event.subtype)) {
10202
10202
  return { event: null, dropReason: "ignored_subtype" };
10203
10203
  }
10204
- const isDm = event.type === "message" && event.channel_type === "im";
10204
+ const isDm = event.type === "message" && (event.channel_type === "im" || event.channel_type === "mpim");
10205
10205
  const isThreadReply = event.type === "message" && !isDm && typeof event.thread_ts === "string" && event.thread_ts !== event.ts;
10206
- 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.
10206
+ const isNonThreadChannelMsg = event.type === "message" && !isDm && !isThreadReply && (event.channel_type === "channel" || event.channel_type === "group" || // Some payload shapes omit channel_type for channel messages.
10207
10207
  typeof event.channel === "string");
10208
10208
  if (event.type !== "app_mention" && !isDm && !isThreadReply) {
10209
10209
  if (isNonThreadChannelMsg) {
@@ -10509,8 +10509,31 @@ function formatBytes(n) {
10509
10509
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
10510
10510
  return `${(n / 1024 / 1024).toFixed(2)} MB`;
10511
10511
  }
10512
- function sleep2(ms) {
10513
- return new Promise((resolve14) => setTimeout(resolve14, ms));
10512
+ function abortError() {
10513
+ const err = new Error("aborted");
10514
+ err.name = "AbortError";
10515
+ return err;
10516
+ }
10517
+ function throwIfAborted(signal) {
10518
+ if (signal?.aborted) throw abortError();
10519
+ }
10520
+ function isAbortLike(err) {
10521
+ return err?.name === "AbortError" || String(err?.message || err).toLowerCase().includes("aborted");
10522
+ }
10523
+ function sleep2(ms, signal) {
10524
+ throwIfAborted(signal);
10525
+ return new Promise((resolve14, reject) => {
10526
+ const t = setTimeout(() => {
10527
+ signal?.removeEventListener("abort", onAbort);
10528
+ resolve14();
10529
+ }, ms);
10530
+ const onAbort = () => {
10531
+ clearTimeout(t);
10532
+ signal?.removeEventListener("abort", onAbort);
10533
+ reject(abortError());
10534
+ };
10535
+ signal?.addEventListener("abort", onAbort, { once: true });
10536
+ });
10514
10537
  }
10515
10538
  function imageMagic(bytes) {
10516
10539
  if (bytes.length < 12) return null;
@@ -10530,19 +10553,21 @@ function validateDownloadedBytes(bytes, declaredContentType) {
10530
10553
  if (!actual) return "invalid_image_bytes";
10531
10554
  return null;
10532
10555
  }
10533
- async function fetchSlackPrivateFile(sourceUrl, botToken) {
10556
+ async function fetchSlackPrivateFile(sourceUrl, botToken, signal) {
10534
10557
  let lastError = "unknown";
10535
10558
  for (let attempt = 0; attempt < 3; attempt++) {
10536
10559
  try {
10560
+ throwIfAborted(signal);
10537
10561
  const res = await fetch(sourceUrl, {
10538
- headers: { Authorization: `Bearer ${botToken}` }
10562
+ headers: { Authorization: `Bearer ${botToken}` },
10563
+ signal
10539
10564
  });
10540
10565
  if (res.status === 429 || res.status >= 500) {
10541
10566
  lastError = `slack_fetch_${res.status}`;
10542
10567
  const retryAfter = Number(res.headers.get("retry-after"));
10543
10568
  const waitMs = Number.isFinite(retryAfter) && retryAfter > 0 ? Math.min(retryAfter * 1e3, 2e3) : 250 * (attempt + 1);
10544
10569
  if (attempt < 2) {
10545
- await sleep2(waitMs);
10570
+ await sleep2(waitMs, signal);
10546
10571
  continue;
10547
10572
  }
10548
10573
  }
@@ -10553,25 +10578,58 @@ async function fetchSlackPrivateFile(sourceUrl, botToken) {
10553
10578
  if (Number.isFinite(contentLength) && contentLength > MAX_BYTES) {
10554
10579
  return { ok: false, error: "size_exceeded" };
10555
10580
  }
10556
- const ab = await res.arrayBuffer();
10557
- if (ab.byteLength > MAX_BYTES) {
10558
- return { ok: false, error: "size_exceeded" };
10559
- }
10560
- return { ok: true, bytes: Buffer.from(ab) };
10581
+ return await readResponseBodyWithCap(res, signal);
10561
10582
  } catch (err) {
10583
+ if (isAbortLike(err) || signal?.aborted) {
10584
+ return { ok: false, error: "aborted" };
10585
+ }
10562
10586
  lastError = `slack_fetch_error:${err?.message || "unknown"}`;
10563
10587
  if (attempt < 2) {
10564
- await sleep2(250 * (attempt + 1));
10588
+ await sleep2(250 * (attempt + 1), signal);
10565
10589
  continue;
10566
10590
  }
10567
10591
  }
10568
10592
  }
10569
10593
  return { ok: false, error: lastError };
10570
10594
  }
10571
- function withTimeout(p, ms, label) {
10595
+ async function readResponseBodyWithCap(res, signal) {
10596
+ const body = res.body;
10597
+ if (!body) {
10598
+ const ab = await res.arrayBuffer();
10599
+ if (ab.byteLength > MAX_BYTES) return { ok: false, error: "size_exceeded" };
10600
+ return { ok: true, bytes: Buffer.from(ab) };
10601
+ }
10602
+ const reader = body.getReader();
10603
+ const chunks = [];
10604
+ let total = 0;
10605
+ try {
10606
+ while (true) {
10607
+ throwIfAborted(signal);
10608
+ const { done, value } = await reader.read();
10609
+ if (done) break;
10610
+ if (!value) continue;
10611
+ total += value.byteLength;
10612
+ if (total > MAX_BYTES) {
10613
+ await reader.cancel().catch(() => void 0);
10614
+ return { ok: false, error: "size_exceeded" };
10615
+ }
10616
+ chunks.push(Buffer.from(value));
10617
+ }
10618
+ } catch (err) {
10619
+ await reader.cancel().catch(() => void 0);
10620
+ if (isAbortLike(err) || signal?.aborted) return { ok: false, error: "aborted" };
10621
+ throw err;
10622
+ }
10623
+ return { ok: true, bytes: Buffer.concat(chunks, total) };
10624
+ }
10625
+ function withAbortTimeout(run, ms, label) {
10572
10626
  return new Promise((resolve14, reject) => {
10573
- const t = setTimeout(() => reject(new Error(`${label}_timeout`)), ms);
10574
- p.then(
10627
+ const controller = new AbortController();
10628
+ const t = setTimeout(() => {
10629
+ controller.abort();
10630
+ reject(new Error(`${label}_timeout`));
10631
+ }, ms);
10632
+ run(controller.signal).then(
10575
10633
  (v) => {
10576
10634
  clearTimeout(t);
10577
10635
  resolve14(v);
@@ -10583,7 +10641,8 @@ function withTimeout(p, ms, label) {
10583
10641
  );
10584
10642
  });
10585
10643
  }
10586
- async function ingestOne(file, sessionId, botToken) {
10644
+ async function ingestOne(file, sessionId, botToken, signal) {
10645
+ throwIfAborted(signal);
10587
10646
  const fileName = inferFileName(file);
10588
10647
  const contentType = inferContentType(file);
10589
10648
  const declaredSize = typeof file.size === "number" ? file.size : 0;
@@ -10601,7 +10660,8 @@ async function ingestOne(file, sessionId, botToken) {
10601
10660
  return { ...base, shortUrl: null, error: "size_exceeded" };
10602
10661
  }
10603
10662
  let bytes;
10604
- const fetched = await fetchSlackPrivateFile(sourceUrl, botToken);
10663
+ const fetched = await fetchSlackPrivateFile(sourceUrl, botToken, signal);
10664
+ throwIfAborted(signal);
10605
10665
  if (!fetched.ok) {
10606
10666
  return { ...base, shortUrl: null, error: fetched.error };
10607
10667
  }
@@ -10614,18 +10674,27 @@ async function ingestOne(file, sessionId, botToken) {
10614
10674
  return { ...base, sizeBytes: bytes.length, shortUrl: null, error: byteError };
10615
10675
  }
10616
10676
  const { storageQueries: storageQueries2 } = await Promise.resolve().then(() => (init_remote(), remote_exports));
10617
- let upload;
10677
+ let upload = null;
10618
10678
  try {
10679
+ throwIfAborted(signal);
10619
10680
  upload = await storageQueries2.getUploadUrl(sessionId, fileName, contentType, "slack");
10681
+ throwIfAborted(signal);
10620
10682
  } catch (err) {
10683
+ if (isAbortLike(err) || signal.aborted) {
10684
+ if (upload?.fileId) await cleanupAbortedUpload(storageQueries2, upload.fileId);
10685
+ throw err;
10686
+ }
10621
10687
  return { ...base, sizeBytes: bytes.length, shortUrl: null, error: `presign_failed:${err?.message || "unknown"}` };
10622
10688
  }
10623
10689
  try {
10690
+ throwIfAborted(signal);
10624
10691
  const putRes = await fetch(upload.uploadUrl, {
10625
10692
  method: "PUT",
10626
10693
  headers: { "Content-Type": contentType },
10627
- body: bytes
10694
+ body: bytes,
10695
+ signal
10628
10696
  });
10697
+ throwIfAborted(signal);
10629
10698
  if (!putRes.ok) {
10630
10699
  return {
10631
10700
  ...base,
@@ -10635,6 +10704,10 @@ async function ingestOne(file, sessionId, botToken) {
10635
10704
  };
10636
10705
  }
10637
10706
  } catch (err) {
10707
+ if (isAbortLike(err) || signal.aborted) {
10708
+ await cleanupAbortedUpload(storageQueries2, upload.fileId);
10709
+ throw err;
10710
+ }
10638
10711
  return {
10639
10712
  ...base,
10640
10713
  sizeBytes: bytes.length,
@@ -10643,8 +10716,13 @@ async function ingestOne(file, sessionId, botToken) {
10643
10716
  };
10644
10717
  }
10645
10718
  try {
10719
+ throwIfAborted(signal);
10646
10720
  await storageQueries2.updateFile(upload.fileId, { sizeBytes: bytes.length });
10647
10721
  } catch (err) {
10722
+ if (isAbortLike(err) || signal.aborted) {
10723
+ await cleanupAbortedUpload(storageQueries2, upload.fileId);
10724
+ throw err;
10725
+ }
10648
10726
  console.warn(`[slack-files] sizeBytes patch failed for ${upload.fileId}:`, err?.message || err);
10649
10727
  }
10650
10728
  const shortUrl = upload.shortUrl || // Defensive fallback: build it from the upload URL's origin if the
@@ -10656,6 +10734,14 @@ async function ingestOne(file, sessionId, botToken) {
10656
10734
  shortUrl
10657
10735
  };
10658
10736
  }
10737
+ async function cleanupAbortedUpload(storageQueries2, fileId) {
10738
+ if (typeof storageQueries2?.deleteFile !== "function") return;
10739
+ try {
10740
+ await storageQueries2.deleteFile(fileId);
10741
+ } catch (err) {
10742
+ console.warn(`[slack-files] cleanup after aborted upload failed for ${fileId}:`, err?.message || err);
10743
+ }
10744
+ }
10659
10745
  function inferShortUrlFromUploadUrl(uploadUrl, fileId) {
10660
10746
  try {
10661
10747
  const u = new URL(uploadUrl);
@@ -10695,7 +10781,7 @@ async function ingestSlackFiles(files, sessionId, options = {}) {
10695
10781
  const startedAt = Date.now();
10696
10782
  const pipeline = Promise.allSettled(
10697
10783
  files.map(
10698
- (f) => withTimeout(ingestOne(f, sessionId, botToken), timeoutMs, `ingest:${f.id}`).catch((err) => {
10784
+ (f) => withAbortTimeout((signal) => ingestOne(f, sessionId, botToken, signal), timeoutMs, `ingest:${f.id}`).catch((err) => {
10699
10785
  if (String(err?.message || err).includes("_timeout")) {
10700
10786
  return {
10701
10787
  slackFileId: f.id,
@@ -17400,7 +17486,7 @@ slack.post("/events", async (c) => {
17400
17486
  const self = await ensureSlackSelfIdentity();
17401
17487
  const { event: inbound, dropReason } = slackEventToInboundResult(ev, { self });
17402
17488
  if (inbound) {
17403
- const isThreadReply = ev.type === "message" && ev.channel_type !== "im" && typeof ev.thread_ts === "string" && ev.thread_ts !== ev.ts;
17489
+ const isThreadReply = ev.type === "message" && ev.channel_type !== "im" && ev.channel_type !== "mpim" && typeof ev.thread_ts === "string" && ev.thread_ts !== ev.ts;
17404
17490
  if (isThreadReply) {
17405
17491
  const ours = isThreadOwned(ev.channel, ev.thread_ts) || await botParticipatedInThread(ev.channel, ev.thread_ts);
17406
17492
  if (!ours) {
@@ -17413,7 +17499,7 @@ slack.post("/events", async (c) => {
17413
17499
  if (ev.type === "app_mention" && ev.channel && (ev.thread_ts || ev.ts)) {
17414
17500
  markThreadOwned(ev.channel, ev.thread_ts || ev.ts);
17415
17501
  }
17416
- if (ev.type === "message" && ev.channel_type === "im" && ev.channel && (ev.thread_ts || ev.ts)) {
17502
+ if (ev.type === "message" && (ev.channel_type === "im" || ev.channel_type === "mpim") && ev.channel && (ev.thread_ts || ev.ts)) {
17417
17503
  markThreadOwned(ev.channel, ev.thread_ts || ev.ts);
17418
17504
  }
17419
17505
  if (wasHandled(ev.channel, ev.ts)) {