@decentnetwork/beagle 0.1.55 → 0.1.56

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.
@@ -1,4 +1,4 @@
1
- window.__DK_UI_VERSION="0.1.55";
1
+ window.__DK_UI_VERSION="0.1.56";
2
2
  const ICON_PATHS = {
3
3
  // ---- tab bar (the four must feel like one set) ----
4
4
  users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
@@ -25,23 +25,16 @@ const OUTBOX_MAX_FILE_BYTES = 25 * 1024 * 1024;
25
25
  /** Inline envelope ceiling for a JS peer: base64 (~1.34x) inside a 16MB
26
26
  * bulkmsg cap. */
27
27
  const INLINE_MAX_BYTES = 11 * 1024 * 1024;
28
- /** Inline ceiling for a NATIVE (iOS/Android) peer tiny files only.
29
- *
30
- * History: 11MB (the JS receiver's figure) created a dead band where
31
- * multi-MB inline sends died silently in the native kernel (5.2MB failed,
32
- * 52MB streamed fine); 2.5MB still sat inside the band where the envelope's
33
- * only confirmation the toxcore send window draining is structurally
34
- * unreliable: an 8.5MB envelope is ~11k bulkmsg fragments on a channel with
35
- * no congestion control, and three live 8.5MB sends all timed out
36
- * unconfirmed at 180s.
37
- *
38
- * Streaming (sendFile → DNFT1 for natives, peer >= 0.1.141) is the path
39
- * built for size: offset acks, FEC, resume, and a real delivery verdict
40
- * (verified 100MB JS→iPad, sent strictly after the receiver's disk write).
41
- * Inline stays only as the one-round-trip shortcut for a thumbnail or a
42
- * voice note: at 256KB (~350 fragments) the send window drains in seconds,
43
- * so the transport ack actually means something. */
44
- const INLINE_MAX_BYTES_NATIVE = 256 * 1024;
28
+ /** Native (iOS/Android) peers get NO inline shortcut at any size — they
29
+ * stream via sendFile → DNFT1 (peer >= 0.1.141) like everyone else, because
30
+ * the inline envelope has no usable confirmation against a native peer:
31
+ * protoVersion is structurally 0 (no text-ack), the bare FileModel carries no
32
+ * deliveryId to ack, and the transport-ack signal (our send window draining)
33
+ * was FIELD-FALSIFIED at every scale a 282-BYTE single-fragment PNG sat
34
+ * unconfirmed for 20s on the same session that streamed 100MB at 0.0% loss.
35
+ * Gates of 11MB and 2.5MB and 256KB all just manufactured failed chips for
36
+ * files that had actually arrived. DNFT1's contiguous ack is the only true
37
+ * delivery signal a native can give; the cost is one offer round trip. */
45
38
  const MEDIA_RE = /\.(jpe?g|png|gif|webp|heic|bmp|svg|mp4|mov|m4v|webm|mp3|m4a|wav|aac|ogg|flac)$/i;
46
39
  const isMediaFileName = (n) => MEDIA_RE.test(n);
47
40
  /** Strip any directory component and characters that would let a peer-supplied
@@ -638,29 +631,27 @@ export class EmbeddedHost {
638
631
  this.#events.emit("event", { type: "chat", userid, dir: "out" });
639
632
  return { queued: true, name: safe, size: data.length };
640
633
  }
641
- // A NATIVE friend (iOS/Android/C Carrier) takes the inline envelope for
642
- // small files (single blob, the Beagle apps' own fast path). Larger files
643
- // go through the normal sendFile below — peer >= 0.1.141 carries those to
644
- // natives as DNFT1 frames inside friend messages (offset acks, FEC,
645
- // resume; verified 100MB JS→iPad). Only route to inline what fits it.
634
+ // Everyone streams a native friend's packets ride DNFT1 frames inside
635
+ // friend messages (see the note on the deleted native inline gate above).
646
636
  const native = this.#node.isNativeFriend(userid);
647
- // Per-peer ceiling: a native receiver's inline limit is far lower than a
648
- // JS one's, and using the JS number for both is what created the dead
649
- // band (see INLINE_MAX_BYTES_NATIVE).
650
- const inlineLimit = native ? INLINE_MAX_BYTES_NATIVE : INLINE_MAX_BYTES;
651
- const inlineNative = native && data.length <= inlineLimit;
652
637
  const msg = this.#messages.appendFile(userid, "out", { name: safe, size: data.length, status: "sending", sent: 0 });
653
638
  if (!msg)
654
639
  throw new Error("Could not create file message");
655
640
  await mkdir(this.outboxDir, { recursive: true });
656
641
  await writeFile(resolve(this.outboxDir, msg.id), data);
657
- const fileId = inlineNative ? null : this.#node.sendFile(userid, new Uint8Array(data), safe);
642
+ const fileId = this.#node.sendFile(userid, new Uint8Array(data), safe);
658
643
  if (!fileId) {
659
- // Native friend, or no transfer slot the inline envelope path.
660
- if (data.length > inlineLimit) {
644
+ // No transfer slot. The inline fallback only helps a JS friend (their
645
+ // text-ack makes it confirmable); to a native it is unconfirmable by
646
+ // construction, so fail honestly instead.
647
+ if (native) {
648
+ this.#messages.patchFile(userid, msg.id, { status: "failed" });
649
+ throw new Error("No free transfer slot — wait for a current transfer to finish and retry.");
650
+ }
651
+ if (data.length > INLINE_MAX_BYTES) {
661
652
  this.#messages.patchFile(userid, msg.id, { status: "failed" });
662
653
  throw new Error(`Could not start the transfer, and the file is too large (${(data.length / 1024 / 1024).toFixed(1)} MB) ` +
663
- `for the inline fallback (limit ${(inlineLimit / 1024 / 1024).toFixed(1)} MB).`);
654
+ `for the inline fallback (limit ${(INLINE_MAX_BYTES / 1024 / 1024).toFixed(1)} MB).`);
664
655
  }
665
656
  // "sent" means the PEER CONFIRMED receipt — nothing less (the fake-sent
666
657
  // of INBOX 2026-08-21). And sends are NON-BLOCKING (the 2026-08-05
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/beagle",
3
- "version": "0.1.55",
3
+ "version": "0.1.56",
4
4
  "description": "Beagle — P2P chat, file transfer and calls for regular users, on the Decent Network. No admin privilege required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@decentnetwork/chat-components": "^0.1.3",
29
- "@decentnetwork/lan": "^0.1.282",
29
+ "@decentnetwork/lan": "^0.1.283",
30
30
  "@decentnetwork/peer": "^0.1.141",
31
31
  "@decentnetwork/peer-webrtc": "^0.2.16",
32
32
  "js-yaml": "^4.1.0",