@wacando/agent 2.3.0 → 2.4.1

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,7 +1,7 @@
1
- // Embedded from lbframe/wacando@618922ecaf2213da18949a8b27d343c8767b64c5 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
1
+ // Embedded from lbframe/wacando@87b51a96aff0a13ca5ad6650c9c841bee72e1612 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
2
2
  import {
3
3
  DomainError
4
- } from "./chunk-PZDQXGA6.mjs";
4
+ } from "./chunk-4Z6TL6JY.mjs";
5
5
 
6
6
  // packages/omemo/src/ns.ts
7
7
  var NS_OMEMO = "eu.siacs.conversations.axolotl";
@@ -1,4 +1,4 @@
1
- // Embedded from lbframe/wacando@618922ecaf2213da18949a8b27d343c8767b64c5 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
1
+ // Embedded from lbframe/wacando@87b51a96aff0a13ca5ad6650c9c841bee72e1612 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
2
2
  import {
3
3
  BODY_MARKER,
4
4
  GCM_IV_BYTES,
@@ -29,8 +29,8 @@ import {
29
29
  signerJid,
30
30
  signerRole,
31
31
  targetJid
32
- } from "./chunks/chunk-PHGOH4AU.mjs";
33
- import "./chunks/chunk-PZDQXGA6.mjs";
32
+ } from "./chunks/chunk-L6IDYNL5.mjs";
33
+ import "./chunks/chunk-4Z6TL6JY.mjs";
34
34
 
35
35
  // packages/omemo/src/policy-wire.ts
36
36
  import xml from "@xmpp/xml";
@@ -1,9 +1,9 @@
1
- // Embedded from lbframe/wacando@618922ecaf2213da18949a8b27d343c8767b64c5 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
1
+ // Embedded from lbframe/wacando@87b51a96aff0a13ca5ad6650c9c841bee72e1612 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
2
2
  import {
3
3
  authenticatedMessageOrigin,
4
4
  pepFetchItems,
5
5
  pepPublish
6
- } from "./chunks/chunk-53E7SSTF.mjs";
6
+ } from "./chunks/chunk-5Q4655F4.mjs";
7
7
  import {
8
8
  BODY_MARKER,
9
9
  GCM_IV_BYTES,
@@ -37,13 +37,13 @@ import {
37
37
  signerJid,
38
38
  signerRole,
39
39
  utf8Encode
40
- } from "./chunks/chunk-PHGOH4AU.mjs";
40
+ } from "./chunks/chunk-L6IDYNL5.mjs";
41
41
  import {
42
42
  ALLOWED_MEDIA_TYPES,
43
43
  MAX_FILE_BYTES,
44
44
  MIN_FILE_BYTES,
45
45
  looksLikePlaintext
46
- } from "./chunks/chunk-PZDQXGA6.mjs";
46
+ } from "./chunks/chunk-4Z6TL6JY.mjs";
47
47
 
48
48
  // packages/omemo/src/libsignal.ts
49
49
  import { jid as parseJid2 } from "@xmpp/jid";
@@ -585,8 +585,8 @@ var OmemoProvider = class {
585
585
  /**
586
586
  * Resolve OMEMO device targets for a member set via PEP — fail closed:
587
587
  * missing devicelist or missing bundle throws OmemoError before any
588
- * plaintext is touched. Bundle elements are kept raw: each session
589
- * backend parses the flavor it accepts (kyber → PQXDH, else classic).
588
+ * plaintext is touched. Bundle elements are kept raw: the session
589
+ * backend parses them and refuses any non-PQXDH (classic) bundle.
590
590
  */
591
591
  async resolveDeviceTargets(entity, memberBareJids, timeoutMs = 1e4) {
592
592
  const recipients = [.../* @__PURE__ */ new Set([...memberBareJids, this.bareJid])];
@@ -1175,6 +1175,7 @@ var NAME_INVISIBLE = new RegExp(
1175
1175
  "g"
1176
1176
  );
1177
1177
  var NAME_RESERVED = /[<>:"|?*]/g;
1178
+ var NAME_DOT_LOOKALIKE = /[\uff0e\ufe52\u2024]/g;
1178
1179
  var WINDOWS_DEVICE = /^(con|prn|aux|nul|conin\$|conout\$|clock\$|com[0-9\u00b9\u00b2\u00b3]|lpt[0-9\u00b9\u00b2\u00b3])\s*(\..*)?$/i;
1179
1180
  function utf8Length(s) {
1180
1181
  return new TextEncoder().encode(s).length;
@@ -1188,7 +1189,7 @@ function cutUtf8(s, max) {
1188
1189
  return out;
1189
1190
  }
1190
1191
  function sanitizeFileName(raw) {
1191
- let name = raw.normalize("NFC").replace(NAME_INVISIBLE, "");
1192
+ let name = raw.normalize("NFC").replace(NAME_INVISIBLE, "").replace(NAME_DOT_LOOKALIKE, ".");
1192
1193
  name = name.split(/[/\\]/).pop() ?? "";
1193
1194
  name = name.replace(NAME_RESERVED, "_").trim();
1194
1195
  name = name.replace(/^[.\s]+/, "").replace(/[.\s]+$/, "");
@@ -1540,7 +1541,10 @@ function fileIdOfShare(share) {
1540
1541
  }
1541
1542
  async function downloadFile(share, opts) {
1542
1543
  const { fetchUrl } = parseAesgcmUrl(share.url, opts.pin);
1543
- const limit = share.ciphertextSize;
1544
+ const expected = share.ciphertextSize;
1545
+ if (!Number.isSafeInteger(expected) || expected < FILE_TAG_BYTES)
1546
+ throw new FileCryptoError("invalid_descriptor", "file share: ciphertext size");
1547
+ const limit = Math.min(expected, MAX_FILE_CIPHERTEXT_BYTES);
1544
1548
  const doFetch = opts.fetch ?? globalThis.fetch;
1545
1549
  const signal = AbortSignal.timeout(opts.timeoutMs ?? FILE_DOWNLOAD_TIMEOUT_MS);
1546
1550
  const failed = (what) => new FileCryptoError("download_failed", `download ${what}`);
@@ -1593,6 +1597,7 @@ async function downloadFile(share, opts) {
1593
1597
  if (e instanceof FileCryptoError) throw e;
1594
1598
  throw failed(signal.aborted ? "timed out" : "interrupted");
1595
1599
  }
1600
+ if (total !== expected) throw failed("truncated");
1596
1601
  const out = new Uint8Array(total);
1597
1602
  let at = 0;
1598
1603
  for (const c of chunks) {
@@ -1,17 +1,20 @@
1
- // Embedded from lbframe/wacando@618922ecaf2213da18949a8b27d343c8767b64c5 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
1
+ // Embedded from lbframe/wacando@87b51a96aff0a13ca5ad6650c9c841bee72e1612 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
2
2
  import {
3
3
  MucJoinError,
4
4
  MucOriginTracker,
5
+ ScramAuthError,
5
6
  authenticatedMessageOrigin,
6
7
  defaultTimeoutMs,
7
8
  forwardedStanza,
8
9
  joinRoom,
9
10
  queryMam,
10
11
  refuseSubscriptionRequests,
12
+ scramClient,
13
+ startScramClient,
11
14
  unwrapPolicyDelivery,
12
15
  waitForStanza
13
- } from "./chunks/chunk-53E7SSTF.mjs";
14
- import "./chunks/chunk-PZDQXGA6.mjs";
16
+ } from "./chunks/chunk-5Q4655F4.mjs";
17
+ import "./chunks/chunk-4Z6TL6JY.mjs";
15
18
 
16
19
  // packages/xmpp/src/index.ts
17
20
  import { default as default2 } from "@xmpp/xml";
@@ -73,6 +76,7 @@ async function requestUploadSlot(entity, service, req, timeoutMs = defaultTimeou
73
76
  export {
74
77
  MucJoinError,
75
78
  MucOriginTracker,
79
+ ScramAuthError,
76
80
  announceAvailable,
77
81
  authenticatedMessageOrigin,
78
82
  forwardedStanza,
@@ -80,6 +84,8 @@ export {
80
84
  queryMam,
81
85
  refuseSubscriptionRequests,
82
86
  requestUploadSlot,
87
+ scramClient,
88
+ startScramClient,
83
89
  unwrapPolicyDelivery,
84
90
  uploadServiceJid,
85
91
  default2 as xml
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wacando",
3
- "version": "2.3.0",
3
+ "version": "2.4.1",
4
4
  "description": "Connect agents with Wacando onboarding and view conversations in the built-in Codex browser.",
5
5
  "author": { "name": "Wacando" },
6
6
  "skills": "./skills/",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wacando-claude",
3
3
  "displayName": "Wacando",
4
- "version": "2.3.0",
4
+ "version": "2.4.1",
5
5
  "description": "Connect agents with Wacando onboarding and view live Claude Code conversations locally.",
6
6
  "author": { "name": "Wacando" },
7
7
  "keywords": ["agents", "conversation", "local", "observability"],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wacando-cursor",
3
3
  "displayName": "Wacando",
4
- "version": "2.3.0",
4
+ "version": "2.4.1",
5
5
  "description": "Connect agents with Wacando onboarding and view conversations in the built-in Cursor browser.",
6
6
  "author": { "name": "Wacando" },
7
7
  "keywords": ["agents", "conversation", "local", "observability"],
package/provenance.json CHANGED
@@ -240,11 +240,11 @@
240
240
  "source": {
241
241
  "repository": "lbframe/wacando",
242
242
  "branch": "main",
243
- "commit": "618922ecaf2213da18949a8b27d343c8767b64c5",
243
+ "commit": "87b51a96aff0a13ca5ad6650c9c841bee72e1612",
244
244
  "trees": {
245
- "packages/contracts/src": "1dbaf861fdfc561b90b8ca6d4d7249d2faf2008b",
246
- "packages/xmpp/src": "d1747bc876f1cdc3594d3b8f40c35d2e72baed72",
247
- "packages/omemo/src": "f1339fc6872b0a5a057b0537d30b475106a69698"
245
+ "packages/contracts/src": "bf79bedbbb5bd0dc5cbf7d3a027a30f76a3f6904",
246
+ "packages/xmpp/src": "06bc1e27b585ce669cf12c10b01b7771d44b91f4",
247
+ "packages/omemo/src": "850b707c9705211a6136486c78c38882699e8b39"
248
248
  },
249
249
  "packages": [
250
250
  {
@@ -273,6 +273,8 @@
273
273
  },
274
274
  "externals": {
275
275
  "@signalapp/libsignal-client": "0.102.2",
276
+ "@xmpp/client": "0.14.0",
277
+ "@xmpp/events": "0.14.0",
276
278
  "@xmpp/jid": "0.14.0",
277
279
  "@xmpp/xml": "0.14.0",
278
280
  "base64-js": "1.5.1",
@@ -325,41 +327,43 @@
325
327
  "packages/xmpp/src/presence.ts",
326
328
  "packages/xmpp/src/pubsub.ts",
327
329
  "packages/xmpp/src/roster.ts",
330
+ "packages/xmpp/src/scram.ts",
328
331
  "packages/xmpp/src/single-session.ts",
329
332
  "packages/xmpp/src/stanza.ts",
333
+ "packages/xmpp/src/start.ts",
330
334
  "packages/xmpp/src/timeouts.ts",
331
335
  "packages/xmpp/src/upload.ts"
332
336
  ],
333
337
  "files": [
334
338
  {
335
- "path": "packages/wacando/chunks/chunk-53E7SSTF.mjs",
336
- "bytes": 14356,
337
- "sha256": "c9571af753d39674c6c17ee01542605bf9ca5b59e17e98e1672deee8fa30b096"
339
+ "path": "packages/wacando/chunks/chunk-4Z6TL6JY.mjs",
340
+ "bytes": 2164,
341
+ "sha256": "510beba0db3b2bf41032a4bd2abd003662504f03721f69cdca8ca62da7e2491c"
338
342
  },
339
343
  {
340
- "path": "packages/wacando/chunks/chunk-PHGOH4AU.mjs",
341
- "bytes": 13681,
342
- "sha256": "79249a0223eeb7ac621ff0f6476ded8926264ea5c4a87edd0c886ec9ee80cc75"
344
+ "path": "packages/wacando/chunks/chunk-5Q4655F4.mjs",
345
+ "bytes": 27209,
346
+ "sha256": "05463ed7058575f8d167c157ac88c8ce44d77f1296235afd6bc96ef72e82501b"
343
347
  },
344
348
  {
345
- "path": "packages/wacando/chunks/chunk-PZDQXGA6.mjs",
346
- "bytes": 2164,
347
- "sha256": "a5ab4ba0eac4ac3a24530aa8268df803cd2e0d856bc3752fa49f4489ed02b73b"
349
+ "path": "packages/wacando/chunks/chunk-L6IDYNL5.mjs",
350
+ "bytes": 13681,
351
+ "sha256": "cda8c73a2d729ba969abea7bd5a460f142c4df3b30dc84cfc4ee4092d2c448a4"
348
352
  },
349
353
  {
350
354
  "path": "packages/wacando/omemo-wire.mjs",
351
355
  "bytes": 5683,
352
- "sha256": "c2d98f80d487ed1ea7ba3c989bdf3893ff50d1328a6101bf6633173f29892409"
356
+ "sha256": "3cfcbc94e80e57856db5a9f9ded5f441a333cf1849481273f6f23d62ed4a4414"
353
357
  },
354
358
  {
355
359
  "path": "packages/wacando/omemo.mjs",
356
- "bytes": 109430,
357
- "sha256": "61f802bf70445d4dc12d7301a94f7608f2077293503566721bf43f8fc29371b3"
360
+ "bytes": 109777,
361
+ "sha256": "b06b6771e7f1796150611ee2da60887f682ccba26262107e1a869732e57fc5f6"
358
362
  },
359
363
  {
360
364
  "path": "packages/wacando/xmpp.mjs",
361
- "bytes": 2728,
362
- "sha256": "58a7e1a996412a9be7440c74d4a4d6202a60b9ca7ce49de46c2461d1dc119496"
365
+ "bytes": 2834,
366
+ "sha256": "e95455a1bc5d8d5c8773129c45fdd2ab19f2282b16acf446f981ccd2051c220c"
363
367
  }
364
368
  ]
365
369
  }
@@ -1,423 +0,0 @@
1
- // Embedded from lbframe/wacando@618922ecaf2213da18949a8b27d343c8767b64c5 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
2
- import {
3
- XMPP_DOMAIN
4
- } from "./chunk-PZDQXGA6.mjs";
5
-
6
- // packages/xmpp/src/muc.ts
7
- import xml from "@xmpp/xml";
8
-
9
- // packages/xmpp/src/jid.ts
10
- var COMPONENT_JID = `policy.${XMPP_DOMAIN}`;
11
- function occupantJid(room, nick) {
12
- if (nick.length === 0) {
13
- throw new Error("occupant nick must not be empty");
14
- }
15
- return `${room}/${nick}`;
16
- }
17
-
18
- // packages/xmpp/src/timeouts.ts
19
- var BASE_TIMEOUT_MS = 1e4;
20
- var scale = 1;
21
- function scaledTimeoutMs(ms) {
22
- return Math.round(ms * scale);
23
- }
24
- function defaultTimeoutMs() {
25
- return scaledTimeoutMs(BASE_TIMEOUT_MS);
26
- }
27
-
28
- // packages/xmpp/src/stanza.ts
29
- var StanzaWaitError = class extends Error {
30
- constructor(reason, message, stanza) {
31
- super(message);
32
- this.reason = reason;
33
- this.stanza = stanza;
34
- this.name = "StanzaWaitError";
35
- }
36
- reason;
37
- stanza;
38
- };
39
- function waitForElement(entity, event, predicate, timeoutMs = defaultTimeoutMs()) {
40
- return new Promise((resolve, reject) => {
41
- const seen = [];
42
- const timer = setTimeout(() => {
43
- cleanup();
44
- const trail = seen.length ? `; last seen: ${seen.join(", ")}` : "; nothing arrived";
45
- const status = entity.status;
46
- const state = typeof status === "string" ? `; entity status: ${status}` : "";
47
- reject(
48
- new StanzaWaitError(
49
- "timeout",
50
- `no matching ${event} within ${timeoutMs}ms${trail}${state}`
51
- )
52
- );
53
- }, timeoutMs);
54
- const onElement = (el) => {
55
- seen.push(describeElement(el));
56
- if (seen.length > 8) seen.shift();
57
- try {
58
- if (predicate(el)) {
59
- cleanup();
60
- resolve(el);
61
- }
62
- } catch (err) {
63
- cleanup();
64
- reject(err);
65
- }
66
- };
67
- const cleanup = () => {
68
- clearTimeout(timer);
69
- entity.off(event, onElement);
70
- };
71
- entity.on(event, onElement);
72
- });
73
- }
74
- function waitForStanza(entity, predicate, timeoutMs = defaultTimeoutMs()) {
75
- return waitForElement(entity, "stanza", predicate, timeoutMs);
76
- }
77
- function describeElement(el) {
78
- const type = el.getAttr("type");
79
- const from = el.getAttr("from");
80
- const error = type === "error" ? ` error=${stanzaErrorCondition(el)}` : "";
81
- return `<${el.name}${type ? ` type=${type}` : ""}${from ? ` from=${from}` : ""}${error}>`;
82
- }
83
- function stanzaErrorCondition(stanza) {
84
- const error = stanza.getChild("error");
85
- const condition = error?.children.find((c) => typeof c !== "string");
86
- return condition?.getName() ?? "unknown";
87
- }
88
-
89
- // packages/xmpp/src/muc.ts
90
- var NS_MUC = "http://jabber.org/protocol/muc";
91
- var NS_MUC_USER = `${NS_MUC}#user`;
92
- var NS_MUC_ADMIN = `${NS_MUC}#admin`;
93
- var NS_MUC_OWNER = `${NS_MUC}#owner`;
94
- var NS_DATA_FORMS = "jabber:x:data";
95
- var MucError = class extends Error {
96
- constructor(message, condition = "unknown", stanza) {
97
- super(message);
98
- this.condition = condition;
99
- this.stanza = stanza;
100
- this.name = "MucError";
101
- }
102
- condition;
103
- stanza;
104
- };
105
- var MucJoinError = class extends MucError {
106
- constructor(condition, stanza, room, nick) {
107
- super(`join denied for ${occupantJid(room, nick)}: ${condition}`, condition, stanza);
108
- this.room = room;
109
- this.nick = nick;
110
- this.name = "MucJoinError";
111
- }
112
- room;
113
- nick;
114
- };
115
- function joinPresenceEl(room, nick) {
116
- return xml("presence", { to: occupantJid(room, nick) }, xml("x", { xmlns: NS_MUC }));
117
- }
118
- async function joinRoom(entity, room, nick, timeoutMs = defaultTimeoutMs()) {
119
- const self = occupantJid(room, nick);
120
- const wait = waitForStanza(
121
- entity,
122
- (s) => s.is("presence") && s.getAttr("from") === self,
123
- timeoutMs
124
- );
125
- try {
126
- await entity.send(joinPresenceEl(room, nick));
127
- } catch (err) {
128
- void wait.catch(() => {
129
- });
130
- throw err;
131
- }
132
- const presence = await wait;
133
- if (presence.getAttr("type") === "error") {
134
- throw new MucJoinError(stanzaErrorCondition(presence), presence, room, nick);
135
- }
136
- return presence;
137
- }
138
-
139
- // packages/xmpp/src/origin.ts
140
- import { jid } from "@xmpp/jid";
141
- var NS_MUC_USER2 = "http://jabber.org/protocol/muc#user";
142
- var NS_FORWARD = "urn:xmpp:forward:0";
143
- var NS_WACANDO_POLICY = "urn:wacando:policy:0";
144
- var origins = /* @__PURE__ */ new WeakMap();
145
- function authenticatedMessageOrigin(stanza) {
146
- return origins.get(stanza);
147
- }
148
- function itemJid(stanza) {
149
- const xs = stanza.getChildren("x", NS_MUC_USER2);
150
- if (xs.length !== 1) return;
151
- const items = xs[0]?.getChildren("item");
152
- if (items?.length !== 1) return;
153
- const value = items[0]?.getAttr("jid");
154
- return typeof value === "string" ? value : void 0;
155
- }
156
- function userBareJid(value) {
157
- if (value === void 0) return;
158
- try {
159
- const parsed = jid(value);
160
- return parsed.getLocal() ? parsed.bare().toString() : void 0;
161
- } catch {
162
- return;
163
- }
164
- }
165
- function isTrustedRelay(value, trustedRelayJid) {
166
- if (value === void 0 || trustedRelayJid === void 0) return false;
167
- try {
168
- const parsed = jid(value);
169
- return !parsed.getLocal() && parsed.getDomain() === trustedRelayJid;
170
- } catch {
171
- return false;
172
- }
173
- }
174
- function relaySender(stanza) {
175
- const relays = stanza.getChildren("relay", NS_WACANDO_POLICY);
176
- if (relays.length !== 1) return;
177
- return userBareJid(relays[0]?.getAttr("jid"));
178
- }
179
- function recordMamOrigin(stanza, room, trustedRelayJid) {
180
- if (!stanza.is("message") || stanza.getAttr("type") !== "groupchat" || !stanza.getAttr("from")?.startsWith(`${room}/`))
181
- return;
182
- const item = itemJid(stanza);
183
- const senderBareJid = isTrustedRelay(item, trustedRelayJid) ? relaySender(stanza) : userBareJid(item);
184
- if (senderBareJid) origins.set(stanza, { roomJid: room, senderBareJid });
185
- }
186
- function unwrapPolicyDelivery(stanza, policyJid) {
187
- if (!stanza.is("message") || stanza.getAttr("type") === "error") return;
188
- const from = stanza.getAttr("from");
189
- if (typeof from !== "string" || !isTrustedRelay(from, policyJid)) return;
190
- const deliveries = stanza.getChildren("delivery", NS_WACANDO_POLICY);
191
- if (deliveries.length !== 1) return;
192
- const delivery = deliveries[0];
193
- const room = delivery?.getAttr("room");
194
- const senderBareJid = userBareJid(delivery?.getAttr("sender"));
195
- const inner = delivery?.getChild("forwarded", NS_FORWARD)?.getChild("message");
196
- if (typeof room !== "string" || !senderBareJid || !inner) return;
197
- if (inner.getAttr("type") !== "groupchat" || !inner.getAttr("from")?.startsWith(`${room}/`))
198
- return;
199
- origins.set(inner, { roomJid: room, senderBareJid });
200
- return inner;
201
- }
202
- var MucOriginTracker = class {
203
- /**
204
- * `trustedRelayJid`: the policy component domain. When set, groupchat from
205
- * an occupant whose real JID is exactly that domain is attributed to its
206
- * `<relay jid>` (#39). Without it, relays carry no origin (fail closed).
207
- */
208
- constructor(entity, options = {}) {
209
- this.entity = entity;
210
- this.options = options;
211
- entity.on("stanza", this.onStanza);
212
- entity.on("offline", this.reset);
213
- entity.on("disconnect", this.reset);
214
- }
215
- entity;
216
- options;
217
- rooms = /* @__PURE__ */ new Set();
218
- occupants = /* @__PURE__ */ new Map();
219
- /** Occupant full JIDs whose authenticated real JID is the policy component. */
220
- relays = /* @__PURE__ */ new Set();
221
- trackRoom(room) {
222
- this.rooms.add(room);
223
- }
224
- reset = () => {
225
- this.occupants.clear();
226
- this.relays.clear();
227
- };
228
- onStanza = (stanza) => {
229
- const from = stanza.getAttr("from");
230
- if (typeof from !== "string") return;
231
- const slash = from.indexOf("/");
232
- if (slash < 1 || !this.rooms.has(from.slice(0, slash))) return;
233
- if (stanza.is("presence")) {
234
- const type = stanza.getAttr("type");
235
- if (type === "unavailable" || type === "error") {
236
- this.occupants.delete(from);
237
- this.relays.delete(from);
238
- if (stanza.getChild("x", NS_MUC_USER2)?.getChildren("status").some((s) => s.getAttr("code") === "110")) {
239
- const prefix = `${from.slice(0, slash)}/`;
240
- for (const occupant of this.occupants.keys()) {
241
- if (occupant.startsWith(prefix)) this.occupants.delete(occupant);
242
- }
243
- for (const relay of [...this.relays]) {
244
- if (relay.startsWith(prefix)) this.relays.delete(relay);
245
- }
246
- }
247
- } else if (!type) {
248
- const item = itemJid(stanza);
249
- const sender = userBareJid(item);
250
- if (sender) this.occupants.set(from, sender);
251
- else this.occupants.delete(from);
252
- if (isTrustedRelay(item, this.options.trustedRelayJid)) this.relays.add(from);
253
- else this.relays.delete(from);
254
- }
255
- } else if (stanza.is("message") && stanza.getAttr("type") === "groupchat" && !stanza.getChild("delay", "urn:xmpp:delay")) {
256
- const senderBareJid = this.relays.has(from) ? relaySender(stanza) : this.occupants.get(from);
257
- if (senderBareJid) origins.set(stanza, { roomJid: from.slice(0, slash), senderBareJid });
258
- }
259
- };
260
- close() {
261
- this.entity.off("stanza", this.onStanza);
262
- this.entity.off("offline", this.reset);
263
- this.entity.off("disconnect", this.reset);
264
- this.reset();
265
- }
266
- };
267
-
268
- // packages/xmpp/src/mam.ts
269
- import xml2 from "@xmpp/xml";
270
- var NS_MAM = "urn:xmpp:mam:2";
271
- var NS_FORWARD2 = "urn:xmpp:forward:0";
272
- var NS_RSM = "http://jabber.org/protocol/rsm";
273
- var queryCounter = 0;
274
- function filterField(varName, value) {
275
- return xml2("field", { var: varName }, xml2("value", {}, value));
276
- }
277
- function mamQueryEl(options) {
278
- const fields = [xml2("field", { var: "FORM_TYPE", type: "hidden" }, xml2("value", {}, NS_MAM))];
279
- if (options.withJid !== void 0) fields.push(filterField("with", options.withJid));
280
- if (options.start !== void 0) fields.push(filterField("start", options.start));
281
- if (options.end !== void 0) fields.push(filterField("end", options.end));
282
- const children = [xml2("x", { xmlns: NS_DATA_FORMS, type: "submit" }, ...fields)];
283
- if (options.max !== void 0) {
284
- children.push(xml2("set", { xmlns: NS_RSM }, xml2("max", {}, String(options.max))));
285
- }
286
- return xml2("query", { xmlns: NS_MAM, queryid: options.queryId }, ...children);
287
- }
288
- async function queryMam(entity, options, timeoutMs = defaultTimeoutMs()) {
289
- const queryId = options.queryId ?? `mam${++queryCounter}`;
290
- const forwarded = [];
291
- const onStanza = (stanza) => {
292
- if (!stanza.is("message") || stanza.getAttr("from") !== options.to) return;
293
- const result = stanza.getChild("result", NS_MAM);
294
- if (!result || result.getAttr("queryid") !== queryId) return;
295
- const fwd = result.getChild("forwarded", NS_FORWARD2);
296
- if (fwd) {
297
- const inner = forwardedStanza(fwd);
298
- if (inner) recordMamOrigin(inner, options.to, options.trustedRelayJid);
299
- forwarded.push(fwd);
300
- }
301
- };
302
- entity.on("stanza", onStanza);
303
- try {
304
- const response = await entity.iqCaller.set(
305
- mamQueryEl({ ...options, queryId }),
306
- options.to,
307
- timeoutMs
308
- );
309
- const fin = response?.getChild("fin", NS_MAM);
310
- const rsmLast = fin?.getChild("set", NS_RSM)?.getChildText("last");
311
- return {
312
- queryId,
313
- complete: fin?.getAttr("complete") === "true",
314
- lastId: typeof rsmLast === "string" ? rsmLast : void 0,
315
- messages: forwarded
316
- };
317
- } finally {
318
- entity.off("stanza", onStanza);
319
- }
320
- }
321
- function forwardedStanza(forwarded) {
322
- return forwarded.children.find(
323
- (c) => typeof c !== "string" && c.getName() !== "delay"
324
- );
325
- }
326
-
327
- // packages/xmpp/src/roster.ts
328
- import { jid as parseJid } from "@xmpp/jid";
329
- import xml3 from "@xmpp/xml";
330
- function subscriptionRefusal(stanza) {
331
- if (!stanza.is("presence") || stanza.getAttr("type") !== "subscribe") return null;
332
- const from = stanza.getAttr("from");
333
- if (typeof from !== "string" || from === "") return null;
334
- let bare;
335
- try {
336
- bare = parseJid(from).bare().toString();
337
- } catch {
338
- return null;
339
- }
340
- return xml3("presence", { to: bare, type: "unsubscribed" });
341
- }
342
- function refuseSubscriptionRequests(entity) {
343
- const onStanza = (stanza) => {
344
- const refusal = subscriptionRefusal(stanza);
345
- if (refusal) void entity.send(refusal).catch(() => {
346
- });
347
- };
348
- entity.on("stanza", onStanza);
349
- return () => entity.off("stanza", onStanza);
350
- }
351
-
352
- // packages/xmpp/src/presence.ts
353
- var UNKNOWN_PRESENCE = Object.freeze({
354
- connection: "unknown",
355
- availability: null
356
- });
357
-
358
- // packages/xmpp/src/pubsub.ts
359
- import xml4 from "@xmpp/xml";
360
- var NS_PUBSUB = "http://jabber.org/protocol/pubsub";
361
- var NS_PUBSUB_PUBLISH_OPTIONS = "http://jabber.org/protocol/pubsub#publish-options";
362
- function pepPublishEl(node, itemId, payload, accessModel = "open") {
363
- return xml4(
364
- "pubsub",
365
- { xmlns: NS_PUBSUB },
366
- xml4("publish", { node }, xml4("item", { id: itemId }, payload)),
367
- xml4(
368
- "publish-options",
369
- {},
370
- xml4(
371
- "x",
372
- { xmlns: NS_DATA_FORMS, type: "submit" },
373
- xml4(
374
- "field",
375
- { var: "FORM_TYPE", type: "hidden" },
376
- xml4("value", {}, NS_PUBSUB_PUBLISH_OPTIONS)
377
- ),
378
- xml4("field", { var: "pubsub#access_model" }, xml4("value", {}, accessModel))
379
- )
380
- )
381
- );
382
- }
383
- function pubsubItemsEl(node, maxItems) {
384
- const attrs = { node };
385
- if (maxItems !== void 0) attrs.max_items = String(maxItems);
386
- return xml4("pubsub", { xmlns: NS_PUBSUB }, xml4("items", attrs));
387
- }
388
- async function pepPublish(entity, to, node, itemId, payload, timeoutMs = defaultTimeoutMs()) {
389
- await entity.iqCaller.set(pepPublishEl(node, itemId, payload), to, timeoutMs);
390
- }
391
- async function pepFetchItems(entity, to, node, timeoutMs = defaultTimeoutMs()) {
392
- try {
393
- const result = await entity.iqCaller.get(pubsubItemsEl(node), to, timeoutMs);
394
- const pubsub = result?.getName() === "pubsub" ? result : result?.getChild("pubsub", NS_PUBSUB);
395
- const items = pubsub?.getChild("items");
396
- if (!items) return [];
397
- return items.getChildren("item").map((item) => item.children.find((c) => typeof c !== "string")).filter((el) => el !== void 0);
398
- } catch (err) {
399
- if (isItemNotFound(err)) return [];
400
- throw err;
401
- }
402
- }
403
- function isItemNotFound(err) {
404
- const cond = err?.condition;
405
- if (cond === "item-not-found") return true;
406
- const stanza = err?.stanza;
407
- return stanza?.getChild("error")?.getChild("item-not-found") !== void 0;
408
- }
409
-
410
- export {
411
- defaultTimeoutMs,
412
- waitForStanza,
413
- MucJoinError,
414
- joinRoom,
415
- authenticatedMessageOrigin,
416
- unwrapPolicyDelivery,
417
- MucOriginTracker,
418
- queryMam,
419
- forwardedStanza,
420
- pepPublish,
421
- pepFetchItems,
422
- refuseSubscriptionRequests
423
- };