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.
- package/dist/agent/index.d.ts +3 -3
- package/dist/agent/index.js +105 -19
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +109 -23
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-Cl_eUatM.d.ts → index-BAsQWqZj.d.ts} +96 -96
- package/dist/index.d.ts +5 -5
- package/dist/index.js +109 -23
- package/dist/index.js.map +1 -1
- package/dist/{schema-BSz4MzhJ.d.ts → schema-Dz-wABVY.d.ts} +3 -3
- package/dist/{search-DOzC4ojH.d.ts → search-CVVfuBPZ.d.ts} +4 -4
- package/dist/server/index.js +109 -23
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +3 -3
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.html +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.html +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/web/runtime-config.json +2 -2
- package/web/.next/standalone/web/src/app/(main)/settings/page.tsx +1 -1
- /package/web/.next/standalone/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → static/ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → static/ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → static/ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{static/T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{static/T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{static/T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_ssgManifest.js +0 -0
- /package/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_buildManifest.js +0 -0
- /package/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → ySf1FIgV1p24IEJCK27zG}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{T0ihp-rxOYsKtonqcYLfo → 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: "
|
|
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: "
|
|
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: "
|
|
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?: "
|
|
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: "
|
|
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;
|
package/dist/server/index.js
CHANGED
|
@@ -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" ||
|
|
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
|
|
9770
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
9831
|
-
|
|
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) =>
|
|
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)) {
|