jefrichat-mcp 0.48.12 → 0.48.13

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 (3) hide show
  1. package/dist/http.js +59 -45
  2. package/dist/index.js +59 -45
  3. package/package.json +1 -1
package/dist/http.js CHANGED
@@ -62113,6 +62113,54 @@ function declKey(extra, parts) {
62113
62113
  const ua = String((typeof h?.get === "function" ? h.get("user-agent") : h?.["user-agent"]) ?? "");
62114
62114
  return "d-" + createHash2("sha256").update(JSON.stringify([ua, rid, ...parts])).digest("hex").slice(0, 40);
62115
62115
  }
62116
+ var crossBasename = (p) => String(p).split(/[\\/]/).pop() || "file";
62117
+ var shPathArg = (p) => p.startsWith("~/") ? `"$HOME"${shq(p.slice(1))}` : shq(p);
62118
+ var psq = (s) => `'${String(s).replace(/'/g, "''")}'`;
62119
+ var psPathArg = (p) => p.startsWith("~/") || p.startsWith("~\\") ? `($HOME + ${psq(p.slice(1))})` : psq(p);
62120
+ var DATAURL_INLINE_MAX = 256 * 1024;
62121
+ var dataUrlTooBig = (dataUrl) => dataUrl.length > DATAURL_INLINE_MAX * 1.4 ? `That dataUrl is ~${MB(dataUrl.length * 0.75)} MB decoded \u2014 far past the ${Math.round(DATAURL_INLINE_MAX / 1024)}KB inline limit. NEVER read a local file and base64 it through the model. Call this tool again with the file's PATH \u2014 you'll get a single-use upload command that sends it in seconds.` : null;
62122
+ async function remoteUploadCommand(c, ctx, target, path3, caption, where) {
62123
+ const fname = crossBasename(path3);
62124
+ const fmime = mimeOf(fname);
62125
+ const hub = ctx.serverUrl.replace(/\/$/, "");
62126
+ try {
62127
+ const g = await fetch(`${hub}/api/files/grant`, {
62128
+ method: "POST",
62129
+ headers: { authorization: `Bearer ${c.token}`, "content-type": "application/json" },
62130
+ body: JSON.stringify({ ...target.to ? { to: target.to } : { groupId: target.groupId }, fileName: fname, ...caption ? { caption } : {} })
62131
+ });
62132
+ if (g.ok) {
62133
+ const { uploadUrl, expiresInMs } = await g.json();
62134
+ const mins = Math.round((expiresInMs ?? 9e5) / 6e4);
62135
+ return {
62136
+ ok: `This cloud connector can't read your disk \u2014 but here is the fast path. Run this ONE command in the terminal (it uploads AND delivers the file to ${where}):
62137
+
62138
+ curl -sS -X POST ${shq(uploadUrl)} -H ${shq(`Content-Type: ${fmime}`)} --data-binary @${shPathArg(path3)}
62139
+
62140
+ Windows PowerShell instead:
62141
+ Invoke-RestMethod -Uri ${psq(uploadUrl)} -Method Post -ContentType ${psq(fmime)} -InFile ${psPathArg(path3)}
62142
+
62143
+ The link is single-use and expires in ${mins} min; the file name and caption are already attached to it. Run it now, then confirm delivery from its JSON response ({"ok":true,...}). Do NOT read the file and base64 it through dataUrl \u2014 that is minutes of model output and fails over ~3MB.`
62144
+ };
62145
+ }
62146
+ } catch {
62147
+ }
62148
+ const web = hub.replace("acp-hub.", "acp-web.").replace(":4000", ":4321");
62149
+ const dropLink = target.to ? `${web}/?to=${encodeURIComponent(target.to)}` : `${web}/?group=${encodeURIComponent(target.groupId)}`;
62150
+ const q = (target.to ? `to=${encodeURIComponent(target.to)}` : `groupId=${encodeURIComponent(target.groupId)}`) + `&fileName=${encodeURIComponent(fname)}` + (caption ? `&caption=${encodeURIComponent(caption)}` : "");
62151
+ const cmd = `curl -s -X POST ${shq(`${hub}/api/files?${q}`)} -H "Authorization: Bearer $JEFRI_TOKEN" -H ${shq(`Content-Type: ${fmime}`)} --data-binary @${shPathArg(path3)}`;
62152
+ return {
62153
+ fail: `This is the cloud connector, so it can't read "${fname}" off your computer, and the upload-link service didn't answer. Options:
62154
+
62155
+ \u2705 open the Jefri Chat web app and DRAG "${fname}" into the chat with ${where}:
62156
+ ${dropLink}
62157
+
62158
+ \u2014 or from a terminal (set JEFRI_TOKEN from the app's Connect dialog first):
62159
+ ${cmd}
62160
+
62161
+ Do NOT base64 the file through dataUrl \u2014 that streams megabytes through the model and fails over ~3MB.`
62162
+ };
62163
+ }
62116
62164
  async function fetchHistory(c, convId) {
62117
62165
  if (isStateless(c)) return c.history(convId);
62118
62166
  const p = waitFor(c, "history", (e) => e.conversationId === convId, 4e3);
@@ -62729,12 +62777,12 @@ ${fp}`);
62729
62777
  "jefri_send_file",
62730
62778
  {
62731
62779
  title: "Send a file, PDF, or image",
62732
- description: 'Send a file to another Jefri Chat user/agent \u2014 PDF, image (jpg/png/gif/webp), video (mp4/mov), or any document. Give a local file `path` (e.g. ~/Downloads/report.pdf) and an optional `caption`.\n\nHOW IT WORKS: this reads the file where the connector runs. If you are connected via the LOCAL (stdio) connector, a `path` is read straight off this machine. If you are connected via the REMOTE/cloud connector (URL), this process runs in the cloud and CANNOT see your local disk \u2014 so for a local file, run the helper in your terminal instead (it reads + uploads the file locally):\n pnpm send-file --to <username> --path <absolute file path> [--caption "..."]\n(run from the acp repo; token + hub are auto-detected from your Claude config). Tiny inline content can be sent directly via `dataUrl` + `fileName`. If you only have a public URL for the file (e.g. an image you generated), pass it as `fileUrl` and the connector fetches the bytes and sends the real file.',
62780
+ description: "Send a file to another Jefri Chat user/agent \u2014 PDF, image (jpg/png/gif/webp), video (mp4/mov), or any document. ALWAYS give the local file `path` (e.g. ~/Downloads/report.pdf) and an optional `caption` \u2014 even on the remote/cloud connector: there this tool answers with ONE ready-to-run terminal command (a single-use upload link) that sends the file in seconds. NEVER read the file yourself and base64 it into `dataUrl` \u2014 that streams megabytes through the model, takes minutes, and fails over ~3MB; `dataUrl` is ONLY for tiny content you already hold inline (small generated snippets). If you only have a public URL for the file, pass `fileUrl` and the connector fetches the bytes itself.",
62733
62781
  inputSchema: {
62734
62782
  to: external_exports.string().describe("recipient username"),
62735
62783
  path: external_exports.string().optional().describe("local file path, e.g. ~/Downloads/report.pdf"),
62736
62784
  caption: external_exports.string().optional().describe("optional text caption to send with it"),
62737
- dataUrl: external_exports.string().optional().describe("alternatively, a data: URL of the file (small files only)"),
62785
+ dataUrl: external_exports.string().optional().describe("ONLY for tiny inline content you already hold (max 256KB decoded). NEVER construct this by reading a local file \u2014 pass `path` instead."),
62738
62786
  fileUrl: external_exports.string().optional().describe("alternatively, a public http(s) URL to fetch the file from (e.g. a generated image)"),
62739
62787
  fileName: external_exports.string().optional().describe("file name (used with dataUrl, or to name a fileUrl download)")
62740
62788
  }
@@ -62743,31 +62791,8 @@ ${fp}`);
62743
62791
  let name, mime, url;
62744
62792
  if (path3) {
62745
62793
  if (!ctx.local) {
62746
- const fname = np3.basename(path3);
62747
- const fmime = mimeOf(fname);
62748
- const hub = ctx.serverUrl.replace(/\/$/, "");
62749
- const web = hub.replace("acp-hub.", "acp-web.").replace(":4000", ":4321");
62750
- const dropLink = `${web}/?to=${encodeURIComponent(to)}`;
62751
- const q = `to=${encodeURIComponent(to)}&fileName=${encodeURIComponent(fname)}` + (caption ? `&caption=${encodeURIComponent(caption)}` : "");
62752
- const uploadUrl = `${hub}/api/files?${q}`;
62753
- const cmd = `curl -s -X POST ${shq(uploadUrl)} -H "Authorization: Bearer $JEFRI_TOKEN" -H "Content-Type: ${fmime}" --data-binary @${shq(path3)}`;
62754
- const psCmd = `Invoke-RestMethod -Uri "${uploadUrl}" -Method Post -Headers @{ Authorization = "Bearer $env:JEFRI_TOKEN" } -ContentType "${fmime}" -InFile "${path3}"`;
62755
- return fail(
62756
- `This is the cloud connector, so it can't read "${fname}" off your computer. Easiest fix:
62757
-
62758
- \u2705 SIMPLE \u2014 open the Jefri Chat web app and DRAG "${fname}" into the chat with @${to}:
62759
- ${dropLink}
62760
-
62761
- (If instead this is an image you GENERATED and have a public URL for, just call this tool again with \`fileUrl\` instead of \`path\` \u2014 the image sends with no drag.)
62762
-
62763
- \u2014 Advanced (only if you prefer a terminal): run one of these to upload it directly \u2014
62764
- \u2022 macOS / Linux:
62765
- ${cmd}
62766
- \u2022 Windows (PowerShell):
62767
- ${psCmd}
62768
-
62769
- (These read your token from the JEFRI_TOKEN env var \u2014 set it first from the app's Connect dialog: export JEFRI_TOKEN=\u2026 (macOS/Linux) or $env:JEFRI_TOKEN="\u2026" (PowerShell). The token isn't printed here on purpose.)`
62770
- );
62794
+ const r = await remoteUploadCommand(c, ctx, { to }, path3, caption, `@${to}`);
62795
+ return "ok" in r ? ok3(r.ok) : fail(r.fail);
62771
62796
  }
62772
62797
  const abs = resolveLocalFile(path3);
62773
62798
  if (!abs) {
@@ -62778,6 +62803,8 @@ ${psCmd}
62778
62803
  mime = mimeOf(name);
62779
62804
  url = `data:${mime};base64,${buf.toString("base64")}`;
62780
62805
  } else if (dataUrl && fileName) {
62806
+ const tooBig = dataUrlTooBig(dataUrl);
62807
+ if (tooBig) return fail(tooBig);
62781
62808
  name = fileName;
62782
62809
  mime = dataUrl.match(/^data:([^;]+)/)?.[1] ?? mimeOf(fileName);
62783
62810
  url = dataUrl;
@@ -63365,7 +63392,7 @@ Or just upload ${fname} from the agent's page in the web app.`
63365
63392
  groupId: external_exports.string().describe("the group's id (from jefri_groups or jefri_inbox)"),
63366
63393
  path: external_exports.string().optional().describe("local file path, e.g. ~/Downloads/report.pdf"),
63367
63394
  caption: external_exports.string().optional().describe("optional text caption"),
63368
- dataUrl: external_exports.string().optional().describe("alternatively, a data: URL of the file (small files only)"),
63395
+ dataUrl: external_exports.string().optional().describe("ONLY for tiny inline content you already hold (max 256KB decoded). NEVER construct this by reading a local file \u2014 pass `path` instead."),
63369
63396
  fileUrl: external_exports.string().optional().describe("alternatively, a public http(s) URL to fetch the file from"),
63370
63397
  fileName: external_exports.string().optional().describe("file name (used with dataUrl, or to name a fileUrl download)")
63371
63398
  }
@@ -63374,23 +63401,8 @@ Or just upload ${fname} from the agent's page in the web app.`
63374
63401
  let name, mime, url;
63375
63402
  if (path3) {
63376
63403
  if (!ctx.local) {
63377
- const hub = ctx.serverUrl.replace(/\/$/, "");
63378
- const web = hub.replace("acp-hub.", "acp-web.").replace(":4000", ":4321");
63379
- const dropLink = `${web}/?group=${encodeURIComponent(groupId)}`;
63380
- const fname = np3.basename(path3);
63381
- const fmime = mimeOf(fname);
63382
- const q = `groupId=${encodeURIComponent(groupId)}&fileName=${encodeURIComponent(fname)}` + (caption ? `&caption=${encodeURIComponent(caption)}` : "");
63383
- const cmd = `curl -s -X POST ${shq(`${hub}/api/files?${q}`)} -H "Authorization: Bearer $JEFRI_TOKEN" -H "Content-Type: ${fmime}" --data-binary @${shq(path3)}`;
63384
- return fail(
63385
- `This is the cloud connector, so it can't read "${fname}" off your computer. Easiest fix:
63386
-
63387
- \u2705 SIMPLE \u2014 open the Jefri Chat web app and DRAG "${fname}" into the group chat:
63388
- ${dropLink}
63389
-
63390
- (If this is an image you GENERATED and have a public URL for, call this tool again with \`fileUrl\` instead of \`path\`.)
63391
-
63392
- \u2014 Advanced (terminal): ${cmd}`
63393
- );
63404
+ const r = await remoteUploadCommand(c, ctx, { groupId }, path3, caption, "the group");
63405
+ return "ok" in r ? ok3(r.ok) : fail(r.fail);
63394
63406
  }
63395
63407
  const abs = resolveLocalFile(path3);
63396
63408
  if (!abs) return fail(`I can't find a file at ${path3} on this machine.`);
@@ -63399,6 +63411,8 @@ Or just upload ${fname} from the agent's page in the web app.`
63399
63411
  mime = mimeOf(name);
63400
63412
  url = `data:${mime};base64,${buf.toString("base64")}`;
63401
63413
  } else if (dataUrl && fileName) {
63414
+ const tooBig = dataUrlTooBig(dataUrl);
63415
+ if (tooBig) return fail(tooBig);
63402
63416
  name = fileName;
63403
63417
  mime = dataUrl.match(/^data:([^;]+)/)?.[1] ?? mimeOf(fileName);
63404
63418
  url = dataUrl;
package/dist/index.js CHANGED
@@ -40573,6 +40573,54 @@ function declKey(extra, parts) {
40573
40573
  const ua = String((typeof h?.get === "function" ? h.get("user-agent") : h?.["user-agent"]) ?? "");
40574
40574
  return "d-" + createHash("sha256").update(JSON.stringify([ua, rid, ...parts])).digest("hex").slice(0, 40);
40575
40575
  }
40576
+ var crossBasename = (p) => String(p).split(/[\\/]/).pop() || "file";
40577
+ var shPathArg = (p) => p.startsWith("~/") ? `"$HOME"${shq(p.slice(1))}` : shq(p);
40578
+ var psq = (s) => `'${String(s).replace(/'/g, "''")}'`;
40579
+ var psPathArg = (p) => p.startsWith("~/") || p.startsWith("~\\") ? `($HOME + ${psq(p.slice(1))})` : psq(p);
40580
+ var DATAURL_INLINE_MAX = 256 * 1024;
40581
+ var dataUrlTooBig = (dataUrl) => dataUrl.length > DATAURL_INLINE_MAX * 1.4 ? `That dataUrl is ~${MB(dataUrl.length * 0.75)} MB decoded \u2014 far past the ${Math.round(DATAURL_INLINE_MAX / 1024)}KB inline limit. NEVER read a local file and base64 it through the model. Call this tool again with the file's PATH \u2014 you'll get a single-use upload command that sends it in seconds.` : null;
40582
+ async function remoteUploadCommand(c2, ctx, target, path4, caption, where) {
40583
+ const fname = crossBasename(path4);
40584
+ const fmime = mimeOf(fname);
40585
+ const hub = ctx.serverUrl.replace(/\/$/, "");
40586
+ try {
40587
+ const g = await fetch(`${hub}/api/files/grant`, {
40588
+ method: "POST",
40589
+ headers: { authorization: `Bearer ${c2.token}`, "content-type": "application/json" },
40590
+ body: JSON.stringify({ ...target.to ? { to: target.to } : { groupId: target.groupId }, fileName: fname, ...caption ? { caption } : {} })
40591
+ });
40592
+ if (g.ok) {
40593
+ const { uploadUrl, expiresInMs } = await g.json();
40594
+ const mins = Math.round((expiresInMs ?? 9e5) / 6e4);
40595
+ return {
40596
+ ok: `This cloud connector can't read your disk \u2014 but here is the fast path. Run this ONE command in the terminal (it uploads AND delivers the file to ${where}):
40597
+
40598
+ curl -sS -X POST ${shq(uploadUrl)} -H ${shq(`Content-Type: ${fmime}`)} --data-binary @${shPathArg(path4)}
40599
+
40600
+ Windows PowerShell instead:
40601
+ Invoke-RestMethod -Uri ${psq(uploadUrl)} -Method Post -ContentType ${psq(fmime)} -InFile ${psPathArg(path4)}
40602
+
40603
+ The link is single-use and expires in ${mins} min; the file name and caption are already attached to it. Run it now, then confirm delivery from its JSON response ({"ok":true,...}). Do NOT read the file and base64 it through dataUrl \u2014 that is minutes of model output and fails over ~3MB.`
40604
+ };
40605
+ }
40606
+ } catch {
40607
+ }
40608
+ const web = hub.replace("acp-hub.", "acp-web.").replace(":4000", ":4321");
40609
+ const dropLink = target.to ? `${web}/?to=${encodeURIComponent(target.to)}` : `${web}/?group=${encodeURIComponent(target.groupId)}`;
40610
+ const q = (target.to ? `to=${encodeURIComponent(target.to)}` : `groupId=${encodeURIComponent(target.groupId)}`) + `&fileName=${encodeURIComponent(fname)}` + (caption ? `&caption=${encodeURIComponent(caption)}` : "");
40611
+ const cmd = `curl -s -X POST ${shq(`${hub}/api/files?${q}`)} -H "Authorization: Bearer $JEFRI_TOKEN" -H ${shq(`Content-Type: ${fmime}`)} --data-binary @${shPathArg(path4)}`;
40612
+ return {
40613
+ fail: `This is the cloud connector, so it can't read "${fname}" off your computer, and the upload-link service didn't answer. Options:
40614
+
40615
+ \u2705 open the Jefri Chat web app and DRAG "${fname}" into the chat with ${where}:
40616
+ ${dropLink}
40617
+
40618
+ \u2014 or from a terminal (set JEFRI_TOKEN from the app's Connect dialog first):
40619
+ ${cmd}
40620
+
40621
+ Do NOT base64 the file through dataUrl \u2014 that streams megabytes through the model and fails over ~3MB.`
40622
+ };
40623
+ }
40576
40624
  async function fetchHistory2(c2, convId) {
40577
40625
  if (isStateless(c2)) return c2.history(convId);
40578
40626
  const p = waitFor(c2, "history", (e) => e.conversationId === convId, 4e3);
@@ -41192,12 +41240,12 @@ ${fp}`);
41192
41240
  "jefri_send_file",
41193
41241
  {
41194
41242
  title: "Send a file, PDF, or image",
41195
- description: 'Send a file to another Jefri Chat user/agent \u2014 PDF, image (jpg/png/gif/webp), video (mp4/mov), or any document. Give a local file `path` (e.g. ~/Downloads/report.pdf) and an optional `caption`.\n\nHOW IT WORKS: this reads the file where the connector runs. If you are connected via the LOCAL (stdio) connector, a `path` is read straight off this machine. If you are connected via the REMOTE/cloud connector (URL), this process runs in the cloud and CANNOT see your local disk \u2014 so for a local file, run the helper in your terminal instead (it reads + uploads the file locally):\n pnpm send-file --to <username> --path <absolute file path> [--caption "..."]\n(run from the acp repo; token + hub are auto-detected from your Claude config). Tiny inline content can be sent directly via `dataUrl` + `fileName`. If you only have a public URL for the file (e.g. an image you generated), pass it as `fileUrl` and the connector fetches the bytes and sends the real file.',
41243
+ description: "Send a file to another Jefri Chat user/agent \u2014 PDF, image (jpg/png/gif/webp), video (mp4/mov), or any document. ALWAYS give the local file `path` (e.g. ~/Downloads/report.pdf) and an optional `caption` \u2014 even on the remote/cloud connector: there this tool answers with ONE ready-to-run terminal command (a single-use upload link) that sends the file in seconds. NEVER read the file yourself and base64 it into `dataUrl` \u2014 that streams megabytes through the model, takes minutes, and fails over ~3MB; `dataUrl` is ONLY for tiny content you already hold inline (small generated snippets). If you only have a public URL for the file, pass `fileUrl` and the connector fetches the bytes itself.",
41196
41244
  inputSchema: {
41197
41245
  to: external_exports.string().describe("recipient username"),
41198
41246
  path: external_exports.string().optional().describe("local file path, e.g. ~/Downloads/report.pdf"),
41199
41247
  caption: external_exports.string().optional().describe("optional text caption to send with it"),
41200
- dataUrl: external_exports.string().optional().describe("alternatively, a data: URL of the file (small files only)"),
41248
+ dataUrl: external_exports.string().optional().describe("ONLY for tiny inline content you already hold (max 256KB decoded). NEVER construct this by reading a local file \u2014 pass `path` instead."),
41201
41249
  fileUrl: external_exports.string().optional().describe("alternatively, a public http(s) URL to fetch the file from (e.g. a generated image)"),
41202
41250
  fileName: external_exports.string().optional().describe("file name (used with dataUrl, or to name a fileUrl download)")
41203
41251
  }
@@ -41206,31 +41254,8 @@ ${fp}`);
41206
41254
  let name, mime, url;
41207
41255
  if (path4) {
41208
41256
  if (!ctx.local) {
41209
- const fname = np4.basename(path4);
41210
- const fmime = mimeOf(fname);
41211
- const hub = ctx.serverUrl.replace(/\/$/, "");
41212
- const web = hub.replace("acp-hub.", "acp-web.").replace(":4000", ":4321");
41213
- const dropLink = `${web}/?to=${encodeURIComponent(to)}`;
41214
- const q = `to=${encodeURIComponent(to)}&fileName=${encodeURIComponent(fname)}` + (caption ? `&caption=${encodeURIComponent(caption)}` : "");
41215
- const uploadUrl = `${hub}/api/files?${q}`;
41216
- const cmd = `curl -s -X POST ${shq(uploadUrl)} -H "Authorization: Bearer $JEFRI_TOKEN" -H "Content-Type: ${fmime}" --data-binary @${shq(path4)}`;
41217
- const psCmd = `Invoke-RestMethod -Uri "${uploadUrl}" -Method Post -Headers @{ Authorization = "Bearer $env:JEFRI_TOKEN" } -ContentType "${fmime}" -InFile "${path4}"`;
41218
- return fail(
41219
- `This is the cloud connector, so it can't read "${fname}" off your computer. Easiest fix:
41220
-
41221
- \u2705 SIMPLE \u2014 open the Jefri Chat web app and DRAG "${fname}" into the chat with @${to}:
41222
- ${dropLink}
41223
-
41224
- (If instead this is an image you GENERATED and have a public URL for, just call this tool again with \`fileUrl\` instead of \`path\` \u2014 the image sends with no drag.)
41225
-
41226
- \u2014 Advanced (only if you prefer a terminal): run one of these to upload it directly \u2014
41227
- \u2022 macOS / Linux:
41228
- ${cmd}
41229
- \u2022 Windows (PowerShell):
41230
- ${psCmd}
41231
-
41232
- (These read your token from the JEFRI_TOKEN env var \u2014 set it first from the app's Connect dialog: export JEFRI_TOKEN=\u2026 (macOS/Linux) or $env:JEFRI_TOKEN="\u2026" (PowerShell). The token isn't printed here on purpose.)`
41233
- );
41257
+ const r = await remoteUploadCommand(c2, ctx, { to }, path4, caption, `@${to}`);
41258
+ return "ok" in r ? ok3(r.ok) : fail(r.fail);
41234
41259
  }
41235
41260
  const abs = resolveLocalFile(path4);
41236
41261
  if (!abs) {
@@ -41241,6 +41266,8 @@ ${psCmd}
41241
41266
  mime = mimeOf(name);
41242
41267
  url = `data:${mime};base64,${buf.toString("base64")}`;
41243
41268
  } else if (dataUrl && fileName) {
41269
+ const tooBig = dataUrlTooBig(dataUrl);
41270
+ if (tooBig) return fail(tooBig);
41244
41271
  name = fileName;
41245
41272
  mime = dataUrl.match(/^data:([^;]+)/)?.[1] ?? mimeOf(fileName);
41246
41273
  url = dataUrl;
@@ -41828,7 +41855,7 @@ Or just upload ${fname} from the agent's page in the web app.`
41828
41855
  groupId: external_exports.string().describe("the group's id (from jefri_groups or jefri_inbox)"),
41829
41856
  path: external_exports.string().optional().describe("local file path, e.g. ~/Downloads/report.pdf"),
41830
41857
  caption: external_exports.string().optional().describe("optional text caption"),
41831
- dataUrl: external_exports.string().optional().describe("alternatively, a data: URL of the file (small files only)"),
41858
+ dataUrl: external_exports.string().optional().describe("ONLY for tiny inline content you already hold (max 256KB decoded). NEVER construct this by reading a local file \u2014 pass `path` instead."),
41832
41859
  fileUrl: external_exports.string().optional().describe("alternatively, a public http(s) URL to fetch the file from"),
41833
41860
  fileName: external_exports.string().optional().describe("file name (used with dataUrl, or to name a fileUrl download)")
41834
41861
  }
@@ -41837,23 +41864,8 @@ Or just upload ${fname} from the agent's page in the web app.`
41837
41864
  let name, mime, url;
41838
41865
  if (path4) {
41839
41866
  if (!ctx.local) {
41840
- const hub = ctx.serverUrl.replace(/\/$/, "");
41841
- const web = hub.replace("acp-hub.", "acp-web.").replace(":4000", ":4321");
41842
- const dropLink = `${web}/?group=${encodeURIComponent(groupId)}`;
41843
- const fname = np4.basename(path4);
41844
- const fmime = mimeOf(fname);
41845
- const q = `groupId=${encodeURIComponent(groupId)}&fileName=${encodeURIComponent(fname)}` + (caption ? `&caption=${encodeURIComponent(caption)}` : "");
41846
- const cmd = `curl -s -X POST ${shq(`${hub}/api/files?${q}`)} -H "Authorization: Bearer $JEFRI_TOKEN" -H "Content-Type: ${fmime}" --data-binary @${shq(path4)}`;
41847
- return fail(
41848
- `This is the cloud connector, so it can't read "${fname}" off your computer. Easiest fix:
41849
-
41850
- \u2705 SIMPLE \u2014 open the Jefri Chat web app and DRAG "${fname}" into the group chat:
41851
- ${dropLink}
41852
-
41853
- (If this is an image you GENERATED and have a public URL for, call this tool again with \`fileUrl\` instead of \`path\`.)
41854
-
41855
- \u2014 Advanced (terminal): ${cmd}`
41856
- );
41867
+ const r = await remoteUploadCommand(c2, ctx, { groupId }, path4, caption, "the group");
41868
+ return "ok" in r ? ok3(r.ok) : fail(r.fail);
41857
41869
  }
41858
41870
  const abs = resolveLocalFile(path4);
41859
41871
  if (!abs) return fail(`I can't find a file at ${path4} on this machine.`);
@@ -41862,6 +41874,8 @@ Or just upload ${fname} from the agent's page in the web app.`
41862
41874
  mime = mimeOf(name);
41863
41875
  url = `data:${mime};base64,${buf.toString("base64")}`;
41864
41876
  } else if (dataUrl && fileName) {
41877
+ const tooBig = dataUrlTooBig(dataUrl);
41878
+ if (tooBig) return fail(tooBig);
41865
41879
  name = fileName;
41866
41880
  mime = dataUrl.match(/^data:([^;]+)/)?.[1] ?? mimeOf(fileName);
41867
41881
  url = dataUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jefrichat-mcp",
3
- "version": "0.48.12",
3
+ "version": "0.48.13",
4
4
  "description": "Jefri Chat connector — join the Jefri Chat network (WhatsApp for AI agents) from any MCP client (Claude, Codex, Cursor, …).",
5
5
  "type": "module",
6
6
  "bin": {