@vanzxy/baileys 1.6.7 → 1.7.0

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.

Potentially problematic release.


This version of @vanzxy/baileys might be problematic. Click here for more details.

@@ -763,6 +763,46 @@ class Button extends BaseBuilder {
763
763
  // - a node can carry a builder-only `ref: 'name'` tag; another prop can then point back
764
764
  // at it with `{ $ref: 'name' }`, resolved to that node's real id after the whole tree
765
765
  // is walked (order-independent). `ref` itself is stripped and never reaches the wire.
766
+ //
767
+ // Vanz@Add 01-09-26 --- JSDoc typedefs for the "basic" A2UI catalog below (component set +
768
+ // props confirmed from captured traffic — see /areas/vanzxy-baileys.md). This is NOT the
769
+ // official A2UI spec (there isn't a public one we have access to), just what's been observed
770
+ // on the wire, so BloksNode ends with a permissive `AnyBloksNode` fallback: known components
771
+ // get full editor autocomplete + prop hints, anything else still type-checks and still works
772
+ // at runtime (setBloksWidget()'s own validation only ever requires a "component" string).
773
+ /**
774
+ * @typedef {{ $ref: string }} BloksRef
775
+ * Points back at a sibling node tagged `ref: 'name'` elsewhere in the same tree (currently
776
+ * only needed for `Modal.trigger`/`Modal.content` — everything else nests directly).
777
+ */
778
+ /**
779
+ * @typedef {Object} BloksNodeBase
780
+ * @property {string} [ref] Builder-only tag so another node can reference this one via `{ $ref: ref }`. Stripped before send.
781
+ */
782
+ /**
783
+ * @typedef {BloksNodeBase & { component: 'Column'|'Row', weight?: number, justify?: string, children?: BloksNode[] }} ColumnRowNode
784
+ * @typedef {BloksNodeBase & { component: 'Text', text: string, variant?: string }} TextNode
785
+ * @typedef {BloksNodeBase & { component: 'Icon', name: string }} IconNode
786
+ * @typedef {BloksNodeBase & { component: 'Divider' }} DividerNode
787
+ * @typedef {BloksNodeBase & { component: 'Image', url: string, variant?: string, fit?: string }} ImageNode
788
+ * @typedef {BloksNodeBase & { component: 'Video', url: string }} VideoNode
789
+ * @typedef {BloksNodeBase & { component: 'List', children?: BloksNode[] }} ListNode
790
+ * @typedef {BloksNodeBase & { component: 'TextField', label?: string, value?: string, variant?: string }} TextFieldNode
791
+ * @typedef {BloksNodeBase & { component: 'DateTimeInput', label?: string, value?: string, enableDate?: boolean, enableTime?: boolean }} DateTimeInputNode
792
+ * @typedef {BloksNodeBase & { component: 'Slider', label?: string, min?: number, max?: number, value?: number }} SliderNode
793
+ * @typedef {BloksNodeBase & { component: 'CheckBox', label?: string, value?: boolean }} CheckBoxNode
794
+ * @typedef {BloksNodeBase & { component: 'ChoicePicker', label?: string, variant?: string, displayStyle?: string, options?: Array<{label: string, value: string}>, value?: string }} ChoicePickerNode
795
+ * @typedef {BloksNodeBase & { component: 'Button', child?: BloksNode, variant?: string, action?: { call: string, args?: Record<string, any> } }} BloksButtonNode
796
+ * Note: unlike the CTA/native-flow `Button` class elsewhere in this file, an A2UI Button node
797
+ * has no `label`/`type`+`name` — its label comes from a nested `child` (usually a `Text` node),
798
+ * and tapping it fires `action.call` (with `action.args`), not a native-flow button name.
799
+ * @typedef {BloksNodeBase & { component: 'Modal', trigger: string|BloksRef, content: BloksNode|string|BloksRef }} ModalNode
800
+ * @typedef {BloksNodeBase & { component: 'Tabs', tabs: Array<{title: string, child: BloksNode}> }} TabsNode
801
+ * @typedef {BloksNodeBase & { component: 'Card', child?: BloksNode }} CardNode
802
+ * @typedef {BloksNodeBase & { component: 'AudioPlayer', url: string, description?: string }} AudioPlayerNode
803
+ * @typedef {BloksNodeBase & { component: string, [key: string]: any }} AnyBloksNode Fallback for components not yet confirmed on the wire — still works, just no prop-level autocomplete.
804
+ * @typedef {ColumnRowNode|TextNode|IconNode|DividerNode|ImageNode|VideoNode|ListNode|TextFieldNode|DateTimeInputNode|SliderNode|CheckBoxNode|ChoicePickerNode|BloksButtonNode|ModalNode|TabsNode|CardNode|AudioPlayerNode|AnyBloksNode} BloksNode
805
+ */
766
806
  #flattenBloks(tree, out, ctx = { n: 0, refs: new Map(), pending: [] }, id = 'root') {
767
807
  if (!tree || typeof tree !== 'object') throw new TypeError('setBloksWidget: every node needs a "component" type');
768
808
  const { component, children, child, ref, ...rest } = tree;
@@ -804,7 +844,7 @@ class Button extends BaseBuilder {
804
844
  * `Modal.trigger` — tag the source node with `ref: 'someName'` and point at it with
805
845
  * `{ $ref: 'someName' }`. Everything else (including `Modal.content`) can just be nested
806
846
  * directly, no special key needed.
807
- * @param {Record<string, any>} tree Root node, e.g. `{ component: 'Column', children: [...] }`.
847
+ * @param {BloksNode} tree Root node, e.g. `{ component: 'Column', children: [...] }`.
808
848
  * @param {{uuid?: string, catalogId?: string, surfaceId?: string, version?: string}} [options]
809
849
  */
810
850
  setBloksWidget(tree, { uuid = crypto.randomUUID(), catalogId = 'https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json', surfaceId, version = 'v0.9' } = {}) {
@@ -2102,6 +2142,19 @@ class AIRich extends BaseBuilder {
2102
2142
  // last item that belongs to the block named by insertAt. Blocks are tracked by *object
2103
2143
  // reference*, not saved numeric index, so earlier insertions shifting the array around never
2104
2144
  // invalidates a later insertAt lookup (indexOf on the reference always finds the live position).
2145
+ //
2146
+ // Vanz@Note (bug 71, behavior — not fixed, documented) --- insertAt always inserts right after
2147
+ // the ANCHOR's block, not after "whatever was most recently inserted there". Chaining (each new
2148
+ // item gets its own id, and the next call's insertAt points at THAT id — exactly what the
2149
+ // addText/addSuggest streaming-reveal example does) produces the expected order. But calling
2150
+ // insertAt at the SAME static anchor id repeatedly, without giving each new item its own id to
2151
+ // chain onto, inserts every one of them right after the original anchor — so the order comes out
2152
+ // reversed relative to call order (confirmed by test: id:'x' then 3x insertAt:'x' with no id of
2153
+ // their own on the new items produces [x, third, second, first], not [x, first, second, third]).
2154
+ // Left as-is rather than "fixed": making insertAt self-advance (re-pointing the anchor's block at
2155
+ // whatever was just inserted) would silently change what an id resolves to for any OTHER caller
2156
+ // still holding that id for a later replace()/delete()/insertAt() — a subtler, harder-to-diagnose
2157
+ // bug than the surprising-but-deterministic order this produces. Chain with fresh ids instead.
2105
2158
  this._blocks = new Map(); // id -> { subItems: object[], secItems: object[] }
2106
2159
  return new Proxy(this, {
2107
2160
  get(target, prop, receiver) {
@@ -2129,6 +2182,19 @@ class AIRich extends BaseBuilder {
2129
2182
  const insertAt = opts?.insertAt;
2130
2183
  const replace = opts?.replace;
2131
2184
 
2185
+ // Vanz@Fix (bug 70) --- `id` reuse across two different add*/set* calls was silently
2186
+ // accepted: target._blocks.set(id, ...) below just clobbers the previous registration,
2187
+ // so the FIRST block with that id becomes an untracked ghost — still in _sections/
2188
+ // _submessages (still renders), but no longer reachable via hasId/peek/delete/replace/
2189
+ // insertAt (the id now only resolves to the second block). Confirmed by direct test:
2190
+ // addText('first',{id:'dup'}); addText('second',{id:'dup'}) left both in the message
2191
+ // but getIds() only ever had one 'dup', pointing at 'second'. Fail fast instead — same
2192
+ // as re-registering the same id you're actively `replace`-ing (that's a legitimate
2193
+ // "update this block, keep its id" call, not a collision).
2194
+ if (id && target._blocks.has(id) && replace !== id) {
2195
+ throw new Error(`add*/set*: id "${id}" is already registered — each id must be unique (pass { replace: "${id}" } to update that block instead, or use a different id)`);
2196
+ }
2197
+
2132
2198
  const subBefore = target._submessages.length;
2133
2199
  const secBefore = target._sections.length;
2134
2200
 
@@ -2977,6 +3043,14 @@ class AIRich extends BaseBuilder {
2977
3043
  addWidget(data = {}, { layout } = {}) {
2978
3044
  const items = Array.isArray(data) ? data : [data];
2979
3045
 
3046
+ // Vanz@Fix (bug 44) --- layout: 'Single' forces `widgets[0]` below (a "Single" layout's
3047
+ // view_model can only ever hold one `primitive`, never a `primitives` array — see
3048
+ // newLayout()). Previously an explicit { layout: 'Single' } combined with a multi-item
3049
+ // array silently dropped every item past the first with no error. Fail loud instead.
3050
+ if (layout === 'Single' && items.length > 1) {
3051
+ throw new TypeError(`addWidget(): layout "Single" can only hold one widget (got ${items.length}) — use "HScroll"/"ActionRow" (or omit layout) for multiple`);
3052
+ }
3053
+
2980
3054
  items.forEach((item, i) => {
2981
3055
  // header.title or top-level title required
2982
3056
  const hasTitle = item?.title || item?.header?.title;
@@ -2994,6 +3068,13 @@ class AIRich extends BaseBuilder {
2994
3068
  messageText: items.map((item) => item.header?.title ?? item.title).join(', '),
2995
3069
  });
2996
3070
 
3071
+ // Vanz@Fix (bug 45) --- auto tool_call_id used to be `idx` scoped per-item (ctas.map's own
3072
+ // index), resetting to 0 for every widget item. Two items (or two separate addWidget()
3073
+ // calls) that both omit tool_call_id/id ended up minting the identical auto id ("00"),
3074
+ // so a CTA tap could route to the wrong widget's tool call. Track the counter on the
3075
+ // instance instead so every auto-generated id is unique for this AIRich's lifetime.
3076
+ this._widgetCtaCounter ??= 0;
3077
+
2997
3078
  const widgets = items.map((item) => {
2998
3079
  const ctas = item.ctas ?? item.actions;
2999
3080
  // header accepts either a string title (legacy) or an object { title, subtitle }
@@ -3007,11 +3088,11 @@ class AIRich extends BaseBuilder {
3007
3088
  },
3008
3089
  body: {
3009
3090
  sections: item.sections ?? [],
3010
- ctas: ctas.map((cta, idx) => ({
3091
+ ctas: ctas.map((cta) => ({
3011
3092
  label: cta.label ?? '',
3012
3093
  state: cta.state ?? 'PENDING',
3013
3094
  kind: cta.kind ?? 'OTHER',
3014
- tool_call_id: cta.tool_call_id ?? cta.id ?? String(idx).padStart(2, '0'),
3095
+ tool_call_id: cta.tool_call_id ?? cta.id ?? String(this._widgetCtaCounter++).padStart(2, '0'),
3015
3096
  ...(cta.toast !== false && {
3016
3097
  toast: { label: typeof cta.toast === 'string' ? cta.toast : headerTitle, __typename: 'GenAI3PExtWidgetToast' },
3017
3098
  }),
@@ -37,6 +37,138 @@ export interface TapTargetConfigurationParams {
37
37
  buttonIndex?: number;
38
38
  }
39
39
 
40
+ /**
41
+ * A2UI/Bloks "basic" catalog node types — confirmed from captured traffic (see
42
+ * /areas/vanzxy-baileys.md), not a public spec, so treat this as best-effort autocomplete
43
+ * rather than an exhaustive guarantee. `ref` is a builder-only tag (stripped before send) so
44
+ * another node can reference this one via `BloksRef`.
45
+ */
46
+ export interface BloksRef {
47
+ $ref: string;
48
+ }
49
+ export interface BloksNodeBase {
50
+ /** Builder-only tag so another node can reference this one via `{ $ref: ref }`. Stripped before send. */
51
+ ref?: string;
52
+ }
53
+ export interface ColumnRowNode extends BloksNodeBase {
54
+ component: 'Column' | 'Row';
55
+ weight?: number;
56
+ justify?: string;
57
+ children?: BloksNode[];
58
+ }
59
+ export interface TextNode extends BloksNodeBase {
60
+ component: 'Text';
61
+ text: string;
62
+ variant?: string;
63
+ }
64
+ export interface IconNode extends BloksNodeBase {
65
+ component: 'Icon';
66
+ name: string;
67
+ }
68
+ export interface DividerNode extends BloksNodeBase {
69
+ component: 'Divider';
70
+ }
71
+ export interface ImageNode extends BloksNodeBase {
72
+ component: 'Image';
73
+ url: string;
74
+ variant?: string;
75
+ fit?: string;
76
+ }
77
+ export interface VideoNode extends BloksNodeBase {
78
+ component: 'Video';
79
+ url: string;
80
+ }
81
+ export interface ListNode extends BloksNodeBase {
82
+ component: 'List';
83
+ children?: BloksNode[];
84
+ }
85
+ export interface TextFieldNode extends BloksNodeBase {
86
+ component: 'TextField';
87
+ label?: string;
88
+ value?: string;
89
+ variant?: string;
90
+ }
91
+ export interface DateTimeInputNode extends BloksNodeBase {
92
+ component: 'DateTimeInput';
93
+ label?: string;
94
+ value?: string;
95
+ enableDate?: boolean;
96
+ enableTime?: boolean;
97
+ }
98
+ export interface SliderNode extends BloksNodeBase {
99
+ component: 'Slider';
100
+ label?: string;
101
+ min?: number;
102
+ max?: number;
103
+ value?: number;
104
+ }
105
+ export interface CheckBoxNode extends BloksNodeBase {
106
+ component: 'CheckBox';
107
+ label?: string;
108
+ value?: boolean;
109
+ }
110
+ export interface ChoicePickerNode extends BloksNodeBase {
111
+ component: 'ChoicePicker';
112
+ label?: string;
113
+ variant?: string;
114
+ displayStyle?: string;
115
+ options?: Array<{ label: string; value: string }>;
116
+ value?: string;
117
+ }
118
+ /**
119
+ * Unlike the CTA/native-flow `Button` class elsewhere in this file, an A2UI Button node has no
120
+ * `label`/`type`+`name` — its label comes from a nested `child` (usually a `Text` node), and
121
+ * tapping it fires `action.call` (with `action.args`), not a native-flow button name.
122
+ */
123
+ export interface BloksButtonNode extends BloksNodeBase {
124
+ component: 'Button';
125
+ child?: BloksNode;
126
+ variant?: string;
127
+ action?: { call: string; args?: Record<string, any> };
128
+ }
129
+ export interface ModalNode extends BloksNodeBase {
130
+ component: 'Modal';
131
+ trigger: string | BloksRef;
132
+ content: BloksNode | string | BloksRef;
133
+ }
134
+ export interface TabsNode extends BloksNodeBase {
135
+ component: 'Tabs';
136
+ tabs: Array<{ title: string; child: BloksNode }>;
137
+ }
138
+ export interface CardNode extends BloksNodeBase {
139
+ component: 'Card';
140
+ child?: BloksNode;
141
+ }
142
+ export interface AudioPlayerNode extends BloksNodeBase {
143
+ component: 'AudioPlayer';
144
+ url: string;
145
+ description?: string;
146
+ }
147
+ /** Fallback for components not yet confirmed on the wire — still works at runtime, just no prop-level autocomplete. */
148
+ export interface AnyBloksNode extends BloksNodeBase {
149
+ component: string;
150
+ [key: string]: any;
151
+ }
152
+ export type BloksNode =
153
+ | ColumnRowNode
154
+ | TextNode
155
+ | IconNode
156
+ | DividerNode
157
+ | ImageNode
158
+ | VideoNode
159
+ | ListNode
160
+ | TextFieldNode
161
+ | DateTimeInputNode
162
+ | SliderNode
163
+ | CheckBoxNode
164
+ | ChoicePickerNode
165
+ | BloksButtonNode
166
+ | ModalNode
167
+ | TabsNode
168
+ | CardNode
169
+ | AudioPlayerNode
170
+ | AnyBloksNode;
171
+
40
172
  export class Button extends BaseBuilder {
41
173
  constructor(client: any);
42
174
  setVideo(path: string | Buffer, options?: Record<string, any>): this;
@@ -45,7 +177,7 @@ export class Button extends BaseBuilder {
45
177
  setMedia(obj: Record<string, any>): this;
46
178
  clearButtons(): this;
47
179
  setParams(obj: Record<string, any>): this;
48
- setBloksWidget(tree: Record<string, any>, options?: { uuid?: string; catalogId?: string; surfaceId?: string; version?: string }): this;
180
+ setBloksWidget(tree: BloksNode, options?: { uuid?: string; catalogId?: string; surfaceId?: string; version?: string }): this;
49
181
  addButton(name: string, params: string | Record<string, any>): this;
50
182
  makeRow(header?: string, title?: string, description?: string, id?: string): this;
51
183
  makeSection(title?: string, highlight_label?: string): this;
@@ -80,12 +80,20 @@ export class MessageStore {
80
80
  stored.isDeleted = true;
81
81
  stored.deletedAt = now;
82
82
  stored.deletedBy = deletedBy;
83
+ // Vanz@Fix (bug 66): the old check (`deletedBy === stored.message.key.participant`)
84
+ // only works in groups, where `participant` identifies who sent/revoked a message.
85
+ // In a private chat `key.participant` is always undefined (it's a group-only field),
86
+ // while `deletedBy` there falls back to `remoteJid` — so the comparison could never
87
+ // match and isRevokedBySender was always false for every DM, even though
88
+ // delete-for-everyone in a DM can only be done by the original sender. Treat a
89
+ // missing `participant` (i.e. not a group message) as "revoked by sender" by definition.
90
+ const isGroupMessage = !!stored.message.key.participant;
83
91
  const info = {
84
92
  originalMessage: stored.message,
85
93
  key,
86
94
  deletedAt: now,
87
95
  deletedBy,
88
- isRevokedBySender: !deletedBy || deletedBy === stored.message.key.participant
96
+ isRevokedBySender: !deletedBy || !isGroupMessage || deletedBy === stored.message.key.participant
89
97
  };
90
98
  this.deletedMessages.set(this.getKey(key), info);
91
99
  return info;
@@ -71,7 +71,25 @@ export const encodeBigEndian = (e, t = 4) => {
71
71
  };
72
72
  export const toNumber = (t) => typeof t === 'object' && t ? ('toNumber' in t ? t.toNumber() : t.low) : t || 0;
73
73
  /** unix timestamp of a date in seconds */
74
- export const unixTimestampSeconds = (date = new Date()) => date.getTime() / 1000 | 0;
74
+ // Vanz@Fix (bug 69): unixTimestampSeconds(date) assumed `date` is always a real Date
75
+ // instance and called date.getTime() unconditionally. Any caller that passed a raw
76
+ // number (Date.now(), or an already-converted unix timestamp) or an ISO string instead
77
+ // of a Date crashed here with "date.getTime is not a function" — this is a coercion
78
+ // bug in THIS function, not a proto/BloksWidget/InteractiveMessage issue (traced and
79
+ // confirmed: normalizeMessageContent/getContentType never touch nested message content,
80
+ // and this function is called before any encode/serialize step even starts). Coerce the
81
+ // common input shapes instead of assuming Date, but keep throwing on genuinely invalid
82
+ // input (NaN) so silent bad-timestamp bugs don't get hidden.
83
+ export const unixTimestampSeconds = (date) => {
84
+ if (date == null) date = new Date(); // null AND undefined both mean "now" (default params only catch undefined)
85
+ const d = date instanceof Date
86
+ ? date
87
+ : new Date(typeof date === 'number' && date < 1e12 ? date * 1000 : date); // treat sub-1e12 numbers as already-seconds
88
+ if (Number.isNaN(d.getTime())) {
89
+ throw new TypeError(`unixTimestampSeconds: invalid timestamp input (${typeof date}): ${date}`);
90
+ }
91
+ return d.getTime() / 1000 | 0;
92
+ };
75
93
  export const debouncedTimeout = (intervalMs = 1000, task) => {
76
94
  let timeout;
77
95
  return {
@@ -145,7 +145,11 @@ export const groupLabel = async (jid, text, sock) => {
145
145
  type: 30,
146
146
  memberLabel: {
147
147
  label: text.slice(0, 30),
148
- labelTimestamp: Date.now()
148
+ // Vanz@Fix (bug 67): this used Date.now() (milliseconds) while the
149
+ // sibling groupSetMemberLabel() correctly uses unixTimestampSeconds()
150
+ // for the same proto field — WA's *Timestamp fields are unix-seconds,
151
+ // so this was sending a timestamp ~1000x too large.
152
+ labelTimestamp: unixTimestampSeconds() || Date.now()
149
153
  }
150
154
  }
151
155
  }, {
@@ -346,7 +346,7 @@ global.importScripts = function (...urls) {
346
346
  const code = fs.readFileSync(url, "utf8");
347
347
  eval(code);
348
348
  }
349
- catch (e) { }
349
+ catch (e) { console.error(`[VoIP worker-bootstrap] importScripts failed for "${url}":`, e); }
350
350
  }
351
351
  };
352
352
  if (typeof global.location === "undefined") {
@@ -550,7 +550,7 @@ const resolveLoaderModule = () => {
550
550
  return resolved;
551
551
  }
552
552
  }
553
- catch (e) { }
553
+ catch (e) { console.error(`[VoIP worker-bootstrap] resolveLoaderModule failed for "${moduleName}":`, e); }
554
554
  }
555
555
  return null;
556
556
  };
@@ -621,7 +621,7 @@ global.self.WhatsAppVoipWasmWorkerCompatibleCallbacks = {
621
621
  try {
622
622
  e.postMessage(Object.assign({ type: "waWasmWorkerCompatibleCallback", __name: "loggingCallback" }, n));
623
623
  }
624
- catch (err) { }
624
+ catch (err) { console.error("[VoIP worker-bootstrap] loggingCallback postMessage failed:", err); }
625
625
  },
626
626
  initCaptureDriverJS: function (n) {
627
627
  e.postMessage(Object.assign({ type: "waWasmWorkerCompatibleCallback", __name: "initCaptureDriverJS" }, n));
@@ -762,9 +762,9 @@ if (typedWorkerData && (typedWorkerData.loaderCode || typedWorkerData.workerModu
762
762
  WAWebVoipJsWorkerMessageHandler = jsWorkerModule.default ?? jsWorkerModule;
763
763
  }
764
764
  }
765
- catch (e) { }
765
+ catch (e) { console.error("[VoIP worker-bootstrap] WAWebVoipJsWorkerMessageHandler resolution failed:", e); }
766
766
  }
767
- catch (e) { }
767
+ catch (e) { console.error("[VoIP worker-bootstrap] loaderCode block failed:", e); }
768
768
  }
769
769
  if (!wasmLoader) {
770
770
  const resourcesPath = typedWorkerData?.resourcesPath || path.join(__dirname, "wasm-resources");
@@ -780,7 +780,7 @@ if (!wasmLoader) {
780
780
  }
781
781
  wasmLoader = resolveLoaderModule();
782
782
  }
783
- catch (e) { }
783
+ catch (e) { console.error(`[VoIP worker-bootstrap] failed to run loader.js from "${rsrcPath}":`, e); }
784
784
  }
785
785
  }
786
786
  let s = {};
@@ -936,7 +936,7 @@ function f(t) {
936
936
  try {
937
937
  yield WAWebVoipPersistentFS.initPersistentFS(_);
938
938
  }
939
- catch (err) { }
939
+ catch (err) { console.error("[VoIP worker-bootstrap] initPersistentFS failed:", err); }
940
940
  }));
941
941
  }
942
942
  else {
@@ -1035,7 +1035,7 @@ e.addMessageListener("waWasmWorkerCompatibleCallback", function (msg) {
1035
1035
  global.self.WhatsAppVoipWasmWorkerCompatibleCallbacks[callbackName](args);
1036
1036
  }
1037
1037
  }
1038
- catch (err) { }
1038
+ catch (err) { console.error("[VoIP worker-bootstrap] message handler failed:", err); }
1039
1039
  });
1040
1040
  if (parentPort) {
1041
1041
  parentPort.postMessage({ type: "worker_ready" });
@@ -160,7 +160,9 @@ const FLOWS_MAP = {
160
160
  // routed anything real; kept as a harmless alias in case any external caller
161
161
  // is still constructing a raw button object with the old (wrong) name.
162
162
  flow: true,
163
- flow_action: true,
163
+ // Vanz@Fix (bug 68): removed duplicate `flow_action: true` key — already declared
164
+ // above (Vanzxy extended button types block); this was a leftover copy-paste dupe,
165
+ // harmless (same value) but confusing on re-read.
164
166
  // Vanz@Fix (single_select never renders alone) --- single_select must NEVER get
165
167
  // its own dedicated native_flow node here. WhatsApp only renders a single_select
166
168
  // button through the generic <native_flow v='9' name='mixed'> node — the same one
package/lib/index.js CHANGED
@@ -8,6 +8,9 @@ export * from './WABinary/index.js';
8
8
  export * from './WAM/index.js';
9
9
  export * from './WAUSync/index.js';
10
10
  export { Dugong } from './Socket/dugong.js';
11
+ // Vanz@Port --- Enterprise Bot Framework (Bot/Context/SessionManager/
12
+ // StatsManager/MediaManager/SQLiteStore). See lib/Framework/index.js.
13
+ export { Bot, Context, MediaManager, SessionManager, StatsManager, SQLiteStore } from './Framework/index.js';
11
14
  // Vanz@Add --- ported from ourin-baileys 9.0.11. Audio-only WhatsApp voice-call
12
15
  // handling (WASM call stack + WebRTC relay via optional `@roamhq/wrtc`). See
13
16
  // lib/VoIP/index.js for usage — instantiate VoipClient(sock) after connection.open.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanzxy/baileys",
3
- "version": "1.6.7",
3
+ "version": "1.7.0",
4
4
  "description": "Enhanced Baileys fork by Vanzxy \u2014 based on @itsliaaa/baileys + @whiskeysockets/baileys with fixes for audio group status and clean media without newsletter button.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -34,39 +34,39 @@
34
34
  "NOTICE.md"
35
35
  ],
36
36
  "keywords": [
37
- "vanzxy",
38
- "vanzxybaileys",
39
- "vanzxy-baileys",
40
- "vanzxy-whatsapp",
41
- "vanzxy-baileys-md",
42
- "baileys-fork-vanzxy",
43
- "baileys",
44
- "baileys-md",
45
- "baileys-multi-device",
46
- "baileys-multidevice",
47
- "baileys-whatsapp",
48
- "baileys-whatsapp-api",
49
- "baileys-whatsapp-bot",
50
- "baileys-bot",
51
- "baileys-api",
52
- "baileys-library",
53
- "baileys-node",
54
- "baileys-nodejs",
55
- "baileys-javascript",
56
- "baileys-js",
57
- "baileys-esm",
58
- "baileys-fork",
59
- "whatsapp-baileys",
60
- "whatsapp-bot-baileys",
61
- "whatsapp-api-baileys",
62
- "whatsapp-web-baileys",
63
- "whatsapp-multi-device",
64
- "whatsapp-automation",
65
- "whatsapp-bot",
66
- "whatsapp-api",
67
- "whatsapp-web",
68
- "multi-device",
69
- "interactive-messages"
37
+ "vanzxy",
38
+ "vanzxybaileys",
39
+ "vanzxy-baileys",
40
+ "vanzxy-whatsapp",
41
+ "vanzxy-baileys-md",
42
+ "baileys-fork-vanzxy",
43
+ "baileys",
44
+ "baileys-md",
45
+ "baileys-multi-device",
46
+ "baileys-multidevice",
47
+ "baileys-whatsapp",
48
+ "baileys-whatsapp-api",
49
+ "baileys-whatsapp-bot",
50
+ "baileys-bot",
51
+ "baileys-api",
52
+ "baileys-library",
53
+ "baileys-node",
54
+ "baileys-nodejs",
55
+ "baileys-javascript",
56
+ "baileys-js",
57
+ "baileys-esm",
58
+ "baileys-fork",
59
+ "whatsapp-baileys",
60
+ "whatsapp-bot-baileys",
61
+ "whatsapp-api-baileys",
62
+ "whatsapp-web-baileys",
63
+ "whatsapp-multi-device",
64
+ "whatsapp-automation",
65
+ "whatsapp-bot",
66
+ "whatsapp-api",
67
+ "whatsapp-web",
68
+ "multi-device",
69
+ "interactive-messages"
70
70
  ],
71
71
  "homepage": "https://github.com/vanzxysenpai/vanzxybaileys#readme",
72
72
  "author": "Vanzxy",
@@ -98,7 +98,8 @@
98
98
  "mongodb": "^6.10.0",
99
99
  "mysql2": "^3.11.0",
100
100
  "pg": "^8.13.0",
101
- "sharp": "*"
101
+ "sharp": "*",
102
+ "node-webpmux": "^3.2.0"
102
103
  },
103
104
  "peerDependenciesMeta": {
104
105
  "@napi-rs/image": {
@@ -133,6 +134,9 @@
133
134
  },
134
135
  "pg": {
135
136
  "optional": true
137
+ },
138
+ "node-webpmux": {
139
+ "optional": true
136
140
  }
137
141
  },
138
142
  "resolutions": {