sparkecoder 0.1.76 → 0.1.78
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 +28 -17
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +43 -25
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-DRscBFFX.d.ts → index-DT1l57s0.d.ts} +25 -25
- package/dist/index.d.ts +5 -5
- package/dist/index.js +43 -25
- package/dist/index.js.map +1 -1
- package/dist/{schema-C7Mm4Ykn.d.ts → schema-XcP0dedO.d.ts} +3 -3
- package/dist/{search-CVVfuBPZ.d.ts → search-CCffrVJE.d.ts} +4 -4
- package/dist/server/index.js +43 -25
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +3 -3
- package/dist/tools/index.js +19 -14
- package/dist/tools/index.js.map +1 -1
- 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/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/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/package-lock.json +3 -3
- /package/web/.next/standalone/web/.next/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_ssgManifest.js +0 -0
- /package/web/.next/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_buildManifest.js +0 -0
- /package/web/.next/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{nZpzcWd5nqIPZFd3PiefU → q5xKLVzzjdkOykOwVu4eK}/_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: "error" | "completed" | "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: "error" | "completed" | "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: "error" | "running" | "stopped";
|
|
818
818
|
driverParam: string;
|
|
819
819
|
notNull: true;
|
|
820
820
|
hasDefault: true;
|
|
@@ -15,12 +15,12 @@ interface BashToolOptions {
|
|
|
15
15
|
}
|
|
16
16
|
declare function createBashTool(options: BashToolOptions): ai.Tool<{
|
|
17
17
|
background: boolean;
|
|
18
|
-
id?: string | undefined;
|
|
19
18
|
input?: string | undefined;
|
|
19
|
+
id?: string | undefined;
|
|
20
20
|
command?: string | undefined;
|
|
21
21
|
kill?: boolean | undefined;
|
|
22
22
|
tail?: number | undefined;
|
|
23
|
-
key?: "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "
|
|
23
|
+
key?: "y" | "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "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: "error" | "completed" | "running" | "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
|
-
query: string;
|
|
222
221
|
context: string;
|
|
222
|
+
query: string;
|
|
223
223
|
}, {
|
|
224
224
|
success: boolean;
|
|
225
225
|
error: string;
|
package/dist/server/index.js
CHANGED
|
@@ -2957,26 +2957,29 @@ function cacheKey(buffer) {
|
|
|
2957
2957
|
return createHash("sha256").update(buffer).digest("hex");
|
|
2958
2958
|
}
|
|
2959
2959
|
async function resizeImageIfNeeded(buffer, mediaType) {
|
|
2960
|
+
const inputMediaType = mediaType || "image/png";
|
|
2960
2961
|
let metadata;
|
|
2961
2962
|
try {
|
|
2962
2963
|
metadata = await sharp(buffer).metadata();
|
|
2963
2964
|
} catch {
|
|
2964
|
-
return buffer;
|
|
2965
|
+
return { buffer, mediaType: inputMediaType };
|
|
2965
2966
|
}
|
|
2966
2967
|
const { width, height } = metadata;
|
|
2967
|
-
if (!width || !height) return buffer;
|
|
2968
|
+
if (!width || !height) return { buffer, mediaType: inputMediaType };
|
|
2968
2969
|
const longEdge = Math.max(width, height);
|
|
2969
2970
|
const needsResize = longEdge > MAX_LONG_EDGE;
|
|
2970
2971
|
const needsShrink = buffer.length > MAX_FILE_BYTES;
|
|
2971
|
-
if (!needsResize && !needsShrink) return buffer;
|
|
2972
|
+
if (!needsResize && !needsShrink) return { buffer, mediaType: inputMediaType };
|
|
2972
2973
|
const key = cacheKey(buffer);
|
|
2973
2974
|
const cacheDir = getCacheDir();
|
|
2974
|
-
const isPng =
|
|
2975
|
-
const
|
|
2975
|
+
const isPng = inputMediaType.includes("png");
|
|
2976
|
+
const willConvertToJpeg = isPng && (needsShrink || buffer.length > 2 * 1024 * 1024);
|
|
2977
|
+
const outputMediaType = willConvertToJpeg || !isPng ? "image/jpeg" : "image/png";
|
|
2978
|
+
const ext = outputMediaType === "image/png" ? ".png" : ".jpg";
|
|
2976
2979
|
const cachePath = join3(cacheDir, key + ext);
|
|
2977
2980
|
if (existsSync3(cachePath)) {
|
|
2978
2981
|
console.log(`[image-resize] Cache hit for ${width}x${height} image`);
|
|
2979
|
-
return readFileSync2(cachePath);
|
|
2982
|
+
return { buffer: readFileSync2(cachePath), mediaType: outputMediaType };
|
|
2980
2983
|
}
|
|
2981
2984
|
let pipeline = sharp(buffer);
|
|
2982
2985
|
if (needsResize) {
|
|
@@ -2986,25 +2989,27 @@ async function resizeImageIfNeeded(buffer, mediaType) {
|
|
|
2986
2989
|
});
|
|
2987
2990
|
}
|
|
2988
2991
|
let result;
|
|
2989
|
-
if (
|
|
2992
|
+
if (willConvertToJpeg) {
|
|
2990
2993
|
result = await pipeline.jpeg({ quality: 85 }).toBuffer();
|
|
2991
2994
|
} else if (isPng) {
|
|
2992
2995
|
result = await pipeline.png().toBuffer();
|
|
2993
2996
|
} else {
|
|
2994
2997
|
result = await pipeline.jpeg({ quality: 85 }).toBuffer();
|
|
2995
2998
|
}
|
|
2999
|
+
let finalMediaType = outputMediaType;
|
|
2996
3000
|
if (result.length > MAX_FILE_BYTES) {
|
|
2997
3001
|
for (const quality of [70, 50, 30]) {
|
|
2998
3002
|
result = await sharp(buffer).resize(MAX_LONG_EDGE, MAX_LONG_EDGE, { fit: "inside", withoutEnlargement: true }).jpeg({ quality }).toBuffer();
|
|
2999
3003
|
if (result.length <= MAX_FILE_BYTES) break;
|
|
3000
3004
|
}
|
|
3005
|
+
finalMediaType = "image/jpeg";
|
|
3001
3006
|
}
|
|
3002
3007
|
writeFileSync2(cachePath, result);
|
|
3003
3008
|
const resultMeta = await sharp(result).metadata();
|
|
3004
3009
|
console.log(
|
|
3005
|
-
`[image-resize] ${width}x${height} -> ${resultMeta.width}x${resultMeta.height} (${(buffer.length / 1024).toFixed(0)}KB -> ${(result.length / 1024).toFixed(0)}KB)`
|
|
3010
|
+
`[image-resize] ${width}x${height} -> ${resultMeta.width}x${resultMeta.height} (${(buffer.length / 1024).toFixed(0)}KB -> ${(result.length / 1024).toFixed(0)}KB, ${finalMediaType})`
|
|
3006
3011
|
);
|
|
3007
|
-
return result;
|
|
3012
|
+
return { buffer: result, mediaType: finalMediaType };
|
|
3008
3013
|
}
|
|
3009
3014
|
|
|
3010
3015
|
// src/tools/read-file.ts
|
|
@@ -3071,15 +3076,15 @@ Use this to understand existing code, check file contents, view screenshots, or
|
|
|
3071
3076
|
};
|
|
3072
3077
|
}
|
|
3073
3078
|
const rawBuffer = await readFile2(absolutePath);
|
|
3074
|
-
const
|
|
3075
|
-
const
|
|
3076
|
-
const base64 = buffer.toString("base64");
|
|
3079
|
+
const originalMediaType = getImageMediaType(absolutePath);
|
|
3080
|
+
const resized = await resizeImageIfNeeded(rawBuffer, originalMediaType);
|
|
3081
|
+
const base64 = resized.buffer.toString("base64");
|
|
3077
3082
|
return {
|
|
3078
3083
|
success: true,
|
|
3079
3084
|
path: absolutePath,
|
|
3080
3085
|
relativePath: relative(options.workingDirectory, absolutePath),
|
|
3081
|
-
content: `[Image: ${relativePath} (${mediaType}, ${(stats.size / 1024).toFixed(1)}KB)]`,
|
|
3082
|
-
mediaType,
|
|
3086
|
+
content: `[Image: ${relativePath} (${resized.mediaType}, ${(stats.size / 1024).toFixed(1)}KB)]`,
|
|
3087
|
+
mediaType: resized.mediaType,
|
|
3083
3088
|
imageData: base64,
|
|
3084
3089
|
sizeBytes: stats.size
|
|
3085
3090
|
};
|
|
@@ -6841,6 +6846,13 @@ function truncateWriteFileInput(input) {
|
|
|
6841
6846
|
return out;
|
|
6842
6847
|
}
|
|
6843
6848
|
var approvalResolvers = /* @__PURE__ */ new Map();
|
|
6849
|
+
function stripDataUrlPrefix(data) {
|
|
6850
|
+
const commaIdx = data.indexOf(",");
|
|
6851
|
+
if (commaIdx !== -1 && data.startsWith("data:")) {
|
|
6852
|
+
return data.slice(commaIdx + 1);
|
|
6853
|
+
}
|
|
6854
|
+
return data;
|
|
6855
|
+
}
|
|
6844
6856
|
var Agent = class _Agent {
|
|
6845
6857
|
session;
|
|
6846
6858
|
context;
|
|
@@ -6941,8 +6953,7 @@ ${prompt}` });
|
|
|
6941
6953
|
if (attachment.type === "image") {
|
|
6942
6954
|
contentParts.push({
|
|
6943
6955
|
type: "image",
|
|
6944
|
-
image: attachment.data,
|
|
6945
|
-
// base64 data URL or raw base64
|
|
6956
|
+
image: stripDataUrlPrefix(attachment.data),
|
|
6946
6957
|
mediaType: attachment.mediaType,
|
|
6947
6958
|
filename: attachment.filename,
|
|
6948
6959
|
savedPath: attachment.savedPath
|
|
@@ -6950,7 +6961,7 @@ ${prompt}` });
|
|
|
6950
6961
|
} else {
|
|
6951
6962
|
contentParts.push({
|
|
6952
6963
|
type: "file",
|
|
6953
|
-
data: attachment.data,
|
|
6964
|
+
data: stripDataUrlPrefix(attachment.data),
|
|
6954
6965
|
mediaType: attachment.mediaType || "application/octet-stream",
|
|
6955
6966
|
filename: attachment.filename,
|
|
6956
6967
|
savedPath: attachment.savedPath
|
|
@@ -8619,14 +8630,22 @@ async function saveAttachmentToDisk(sessionId, attachment, index) {
|
|
|
8619
8630
|
}
|
|
8620
8631
|
let buffer = Buffer.from(base64Data, "base64");
|
|
8621
8632
|
if (attachment.type === "image") {
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
attachment.
|
|
8633
|
+
const resized = await resizeImageIfNeeded(buffer, attachment.mediaType);
|
|
8634
|
+
buffer = resized.buffer;
|
|
8635
|
+
attachment.mediaType = resized.mediaType;
|
|
8636
|
+
attachment.data = buffer.toString("base64");
|
|
8625
8637
|
}
|
|
8626
8638
|
const filePath = join9(attachmentsDir, filename);
|
|
8627
8639
|
writeFileSync4(filePath, buffer);
|
|
8628
8640
|
return filePath;
|
|
8629
8641
|
}
|
|
8642
|
+
function stripDataUrlPrefix2(data) {
|
|
8643
|
+
const commaIdx = data.indexOf(",");
|
|
8644
|
+
if (commaIdx !== -1 && data.startsWith("data:")) {
|
|
8645
|
+
return data.slice(commaIdx + 1);
|
|
8646
|
+
}
|
|
8647
|
+
return data;
|
|
8648
|
+
}
|
|
8630
8649
|
function getExtensionFromMediaType(mediaType, type) {
|
|
8631
8650
|
if (!mediaType) {
|
|
8632
8651
|
return type === "image" ? ".png" : ".bin";
|
|
@@ -8718,7 +8737,7 @@ ${prompt}` });
|
|
|
8718
8737
|
if (attachment.type === "image") {
|
|
8719
8738
|
contentParts.push({
|
|
8720
8739
|
type: "image",
|
|
8721
|
-
image: attachment.data,
|
|
8740
|
+
image: stripDataUrlPrefix2(attachment.data),
|
|
8722
8741
|
mediaType: attachment.mediaType,
|
|
8723
8742
|
filename: attachment.filename,
|
|
8724
8743
|
savedPath: attachment.savedPath
|
|
@@ -8726,7 +8745,7 @@ ${prompt}` });
|
|
|
8726
8745
|
} else {
|
|
8727
8746
|
contentParts.push({
|
|
8728
8747
|
type: "file",
|
|
8729
|
-
data: attachment.data,
|
|
8748
|
+
data: stripDataUrlPrefix2(attachment.data),
|
|
8730
8749
|
mediaType: attachment.mediaType || "application/octet-stream",
|
|
8731
8750
|
filename: attachment.filename,
|
|
8732
8751
|
savedPath: attachment.savedPath
|
|
@@ -9013,8 +9032,7 @@ ${prompt}` });
|
|
|
9013
9032
|
if (attachment.type === "image") {
|
|
9014
9033
|
contentParts.push({
|
|
9015
9034
|
type: "image",
|
|
9016
|
-
image: attachment.data,
|
|
9017
|
-
// base64 data URL or raw base64
|
|
9035
|
+
image: stripDataUrlPrefix2(attachment.data),
|
|
9018
9036
|
mediaType: attachment.mediaType,
|
|
9019
9037
|
filename: attachment.filename,
|
|
9020
9038
|
savedPath: attachment.savedPath
|
|
@@ -9022,7 +9040,7 @@ ${prompt}` });
|
|
|
9022
9040
|
} else {
|
|
9023
9041
|
contentParts.push({
|
|
9024
9042
|
type: "file",
|
|
9025
|
-
data: attachment.data,
|
|
9043
|
+
data: stripDataUrlPrefix2(attachment.data),
|
|
9026
9044
|
mediaType: attachment.mediaType || "application/octet-stream",
|
|
9027
9045
|
filename: attachment.filename,
|
|
9028
9046
|
savedPath: attachment.savedPath
|