@wacando/agent 2.2.0 → 2.4.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.
- package/README.md +1 -1
- package/STATUS.md +45 -0
- package/bin/wacando-agent.mjs +28 -11
- package/docs/AGENT_TOOLS.md +60 -11
- package/docs/ONBOARDING.md +5 -1
- package/docs/WACANDO_PACKAGES.md +12 -1
- package/package.json +2 -2
- package/packages/mcp/agent-tools.mjs +6 -4
- package/packages/onboarding/network.mjs +36 -6
- package/packages/onboarding/service.mjs +29 -3
- package/packages/onboarding/version.mjs +1 -1
- package/packages/runtime/conversations.mjs +17 -7
- package/packages/runtime/files.mjs +171 -20
- package/packages/runtime/pairing.mjs +6 -1
- package/packages/runtime/runtime.mjs +23 -5
- package/packages/runtime/session.mjs +42 -6
- package/packages/wacando/chunks/{chunk-PHGOH4AU.mjs → chunk-F7J3K43U.mjs} +2 -2
- package/packages/wacando/chunks/{chunk-PZDQXGA6.mjs → chunk-FFLYSYV6.mjs} +1 -1
- package/packages/wacando/chunks/{chunk-53E7SSTF.mjs → chunk-FUNUGIGH.mjs} +384 -21
- package/packages/wacando/omemo-wire.mjs +3 -3
- package/packages/wacando/omemo.mjs +13 -8
- package/packages/wacando/xmpp.mjs +9 -3
- package/plugins/wacando/.codex-plugin/plugin.json +1 -1
- package/plugins/wacando-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/wacando-cursor/.cursor-plugin/plugin.json +1 -1
- package/provenance.json +20 -18
|
@@ -1,10 +1,370 @@
|
|
|
1
|
-
// Embedded from lbframe/wacando@
|
|
1
|
+
// Embedded from lbframe/wacando@40dd0c30b3653095f08994f9534fd5110e1d0925 by scripts/embed-wacando.mjs. Do not edit; see provenance.json.
|
|
2
2
|
import {
|
|
3
3
|
XMPP_DOMAIN
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FFLYSYV6.mjs";
|
|
5
5
|
|
|
6
|
-
// packages/xmpp/src/
|
|
6
|
+
// packages/xmpp/src/scram.ts
|
|
7
|
+
import { client } from "@xmpp/client";
|
|
7
8
|
import xml from "@xmpp/xml";
|
|
9
|
+
var SASL1_NS = "urn:ietf:params:xml:ns:xmpp-sasl";
|
|
10
|
+
var SASL2_NS = "urn:xmpp:sasl:2";
|
|
11
|
+
var SCRAM_MIN_ITERATIONS = 4096;
|
|
12
|
+
var SCRAM_MAX_ITERATIONS = 1e5;
|
|
13
|
+
var HASH_BYTES = { "SHA-1": 20, "SHA-256": 32 };
|
|
14
|
+
var REASON_TEXT = {
|
|
15
|
+
"missing-server-signature": "server sent no ServerSignature (v=)",
|
|
16
|
+
"server-signature-mismatch": "server ServerSignature (v=) does not match",
|
|
17
|
+
"malformed-server-message": "malformed SCRAM server message",
|
|
18
|
+
"server-error": "server reported a SCRAM error (e=)",
|
|
19
|
+
"nonce-mismatch": "server nonce does not extend the client nonce",
|
|
20
|
+
"weak-iteration-count": `server iteration count below ${SCRAM_MIN_ITERATIONS}`,
|
|
21
|
+
"excessive-iteration-count": `server iteration count above ${SCRAM_MAX_ITERATIONS}`,
|
|
22
|
+
"sasl2-refused": "server offers SASL2, which this client refuses (SASL1 SCRAM only)",
|
|
23
|
+
"no-scram-mechanism": "server offers no supported SCRAM mechanism",
|
|
24
|
+
"out-of-order": "SCRAM message out of order"
|
|
25
|
+
};
|
|
26
|
+
var ScramAuthError = class extends Error {
|
|
27
|
+
reason;
|
|
28
|
+
mechanism;
|
|
29
|
+
constructor(reason, mechanism) {
|
|
30
|
+
super(
|
|
31
|
+
`SCRAM authentication refused${mechanism ? ` (${mechanism})` : ""}: ${REASON_TEXT[reason]}`
|
|
32
|
+
);
|
|
33
|
+
this.name = "ScramAuthError";
|
|
34
|
+
this.reason = reason;
|
|
35
|
+
this.mechanism = mechanism;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var encoder = new TextEncoder();
|
|
39
|
+
function utf8(text) {
|
|
40
|
+
return new Uint8Array(encoder.encode(text));
|
|
41
|
+
}
|
|
42
|
+
function bytesToBinary(bytes) {
|
|
43
|
+
let out = "";
|
|
44
|
+
for (const b of bytes) out += String.fromCharCode(b);
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function binaryToBytes(binary) {
|
|
48
|
+
const out = new Uint8Array(binary.length);
|
|
49
|
+
for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i) & 255;
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function base64Encode(bytes) {
|
|
53
|
+
return globalThis.btoa(bytesToBinary(bytes));
|
|
54
|
+
}
|
|
55
|
+
function base64Decode(text) {
|
|
56
|
+
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(text)) {
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
return binaryToBytes(globalThis.atob(text));
|
|
61
|
+
} catch {
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function constantTimeEqual(a, b) {
|
|
66
|
+
let diff = a.length ^ b.length;
|
|
67
|
+
const n = Math.max(a.length, b.length);
|
|
68
|
+
for (let i = 0; i < n; i++) diff |= (a[i] ?? 0) ^ (b[i] ?? 0);
|
|
69
|
+
return diff === 0;
|
|
70
|
+
}
|
|
71
|
+
function xor(a, b) {
|
|
72
|
+
const out = new Uint8Array(a.length);
|
|
73
|
+
for (let i = 0; i < a.length; i++) out[i] = (a[i] ?? 0) ^ (b[i] ?? 0);
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
async function hmac(hash, key, data) {
|
|
77
|
+
const k = await globalThis.crypto.subtle.importKey("raw", key, { name: "HMAC", hash }, false, [
|
|
78
|
+
"sign"
|
|
79
|
+
]);
|
|
80
|
+
return new Uint8Array(await globalThis.crypto.subtle.sign("HMAC", k, data));
|
|
81
|
+
}
|
|
82
|
+
async function digest(hash, data) {
|
|
83
|
+
return new Uint8Array(await globalThis.crypto.subtle.digest(hash, data));
|
|
84
|
+
}
|
|
85
|
+
async function hi(hash, password, salt, iterations) {
|
|
86
|
+
const key = await globalThis.crypto.subtle.importKey("raw", utf8(password), "PBKDF2", false, [
|
|
87
|
+
"deriveBits"
|
|
88
|
+
]);
|
|
89
|
+
return new Uint8Array(
|
|
90
|
+
await globalThis.crypto.subtle.deriveBits(
|
|
91
|
+
{ name: "PBKDF2", hash, salt, iterations },
|
|
92
|
+
key,
|
|
93
|
+
HASH_BYTES[hash] * 8
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
function parseAttributes(message) {
|
|
98
|
+
const attrs = /* @__PURE__ */ new Map();
|
|
99
|
+
for (const part of message.split(",")) {
|
|
100
|
+
const m = /^([A-Za-z])=(.*)$/s.exec(part);
|
|
101
|
+
if (!m) return void 0;
|
|
102
|
+
const [, key, value] = m;
|
|
103
|
+
if (attrs.has(key)) return void 0;
|
|
104
|
+
attrs.set(key, value);
|
|
105
|
+
}
|
|
106
|
+
return attrs;
|
|
107
|
+
}
|
|
108
|
+
function saslname(name) {
|
|
109
|
+
return name.replace(/=/g, "=3D").replace(/,/g, "=2C");
|
|
110
|
+
}
|
|
111
|
+
async function scramProofs(hash, password, salt, iterations, authMessage) {
|
|
112
|
+
const salted = await hi(hash, password, salt, iterations);
|
|
113
|
+
const clientKey = await hmac(hash, salted, utf8("Client Key"));
|
|
114
|
+
const storedKey = await digest(hash, clientKey);
|
|
115
|
+
const am = utf8(authMessage);
|
|
116
|
+
const clientSignature = await hmac(hash, storedKey, am);
|
|
117
|
+
const serverKey = await hmac(hash, salted, utf8("Server Key"));
|
|
118
|
+
return {
|
|
119
|
+
clientProof: xor(clientKey, clientSignature),
|
|
120
|
+
serverSignature: await hmac(hash, serverKey, am)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function verifyServerFinal(serverFinal, expected, mechanism) {
|
|
124
|
+
if (serverFinal === void 0 || serverFinal === "") {
|
|
125
|
+
throw new ScramAuthError("missing-server-signature", mechanism);
|
|
126
|
+
}
|
|
127
|
+
const attrs = parseAttributes(serverFinal);
|
|
128
|
+
if (!attrs) throw new ScramAuthError("malformed-server-message", mechanism);
|
|
129
|
+
if (attrs.has("e")) throw new ScramAuthError("server-error", mechanism);
|
|
130
|
+
const v = attrs.get("v");
|
|
131
|
+
if (v === void 0) throw new ScramAuthError("missing-server-signature", mechanism);
|
|
132
|
+
const received = base64Decode(v);
|
|
133
|
+
if (!received) throw new ScramAuthError("malformed-server-message", mechanism);
|
|
134
|
+
if (!constantTimeEqual(received, expected)) {
|
|
135
|
+
throw new ScramAuthError("server-signature-mismatch", mechanism);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
var ScramMechanism = class {
|
|
139
|
+
constructor(hash, genNonce = defaultNonce) {
|
|
140
|
+
this.hash = hash;
|
|
141
|
+
this.genNonce = genNonce;
|
|
142
|
+
this.name = hash === "SHA-1" ? "SCRAM-SHA-1" : "SCRAM-SHA-256";
|
|
143
|
+
}
|
|
144
|
+
hash;
|
|
145
|
+
genNonce;
|
|
146
|
+
name;
|
|
147
|
+
clientFirst = true;
|
|
148
|
+
stage = "initial";
|
|
149
|
+
clientNonce = "";
|
|
150
|
+
clientFirstBare = "";
|
|
151
|
+
serverFirst = "";
|
|
152
|
+
expectedServerSignature;
|
|
153
|
+
pendingServerFinal;
|
|
154
|
+
verifiedFlag = false;
|
|
155
|
+
/** True once the server's ServerSignature has been verified. */
|
|
156
|
+
get verified() {
|
|
157
|
+
return this.verifiedFlag;
|
|
158
|
+
}
|
|
159
|
+
/** True once the client-final-message was sent (a `v=` is now due). */
|
|
160
|
+
get awaitingServerFinal() {
|
|
161
|
+
return this.stage === "final";
|
|
162
|
+
}
|
|
163
|
+
async response(cred) {
|
|
164
|
+
switch (this.stage) {
|
|
165
|
+
case "initial":
|
|
166
|
+
return this.clientFirstMessage(cred);
|
|
167
|
+
case "challenge":
|
|
168
|
+
return this.clientFinalMessage(cred);
|
|
169
|
+
case "final":
|
|
170
|
+
await this.final(this.pendingServerFinal);
|
|
171
|
+
return "";
|
|
172
|
+
default:
|
|
173
|
+
throw new ScramAuthError("out-of-order", this.name);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
challenge(chal) {
|
|
177
|
+
if (this.stage === "challenge") {
|
|
178
|
+
this.serverFirst = utf8Decode(chal);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (this.stage === "final") {
|
|
182
|
+
this.pendingServerFinal = chal;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
throw new ScramAuthError("out-of-order", this.name);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* server-final-message (binary string, as decoded from base64) from
|
|
189
|
+
* <success/> (SASL1), <additional-data/> (SASL2) or a last <challenge/>.
|
|
190
|
+
*/
|
|
191
|
+
async final(data) {
|
|
192
|
+
if (this.verifiedFlag) return;
|
|
193
|
+
if (this.stage !== "final" || !this.expectedServerSignature) {
|
|
194
|
+
throw new ScramAuthError("out-of-order", this.name);
|
|
195
|
+
}
|
|
196
|
+
this.stage = "done";
|
|
197
|
+
const expected = this.expectedServerSignature;
|
|
198
|
+
this.expectedServerSignature = void 0;
|
|
199
|
+
verifyServerFinal(data === void 0 ? void 0 : utf8Decode(data), expected, this.name);
|
|
200
|
+
this.verifiedFlag = true;
|
|
201
|
+
}
|
|
202
|
+
clientFirstMessage(cred) {
|
|
203
|
+
this.clientNonce = this.genNonce();
|
|
204
|
+
this.clientFirstBare = `n=${saslname(cred.username ?? "")},r=${this.clientNonce}`;
|
|
205
|
+
this.stage = "challenge";
|
|
206
|
+
return utf8Binary(`n,,${this.clientFirstBare}`);
|
|
207
|
+
}
|
|
208
|
+
async clientFinalMessage(cred) {
|
|
209
|
+
const attrs = parseAttributes(this.serverFirst);
|
|
210
|
+
const nonce = attrs?.get("r");
|
|
211
|
+
const saltText = attrs?.get("s");
|
|
212
|
+
const iterText = attrs?.get("i");
|
|
213
|
+
if (attrs?.has("e")) throw new ScramAuthError("server-error", this.name);
|
|
214
|
+
if (!attrs || attrs.has("m") || !nonce || !saltText || !iterText) {
|
|
215
|
+
throw new ScramAuthError("malformed-server-message", this.name);
|
|
216
|
+
}
|
|
217
|
+
if (!nonce.startsWith(this.clientNonce) || nonce.length <= this.clientNonce.length) {
|
|
218
|
+
throw new ScramAuthError("nonce-mismatch", this.name);
|
|
219
|
+
}
|
|
220
|
+
const salt = base64Decode(saltText);
|
|
221
|
+
if (!salt || salt.length === 0 || !/^[1-9][0-9]{0,9}$/.test(iterText)) {
|
|
222
|
+
throw new ScramAuthError("malformed-server-message", this.name);
|
|
223
|
+
}
|
|
224
|
+
const iterations = Number(iterText);
|
|
225
|
+
if (iterations < SCRAM_MIN_ITERATIONS) {
|
|
226
|
+
throw new ScramAuthError("weak-iteration-count", this.name);
|
|
227
|
+
}
|
|
228
|
+
if (iterations > SCRAM_MAX_ITERATIONS) {
|
|
229
|
+
throw new ScramAuthError("excessive-iteration-count", this.name);
|
|
230
|
+
}
|
|
231
|
+
const withoutProof = `c=biws,r=${nonce}`;
|
|
232
|
+
const authMessage = `${this.clientFirstBare},${this.serverFirst},${withoutProof}`;
|
|
233
|
+
const { clientProof, serverSignature } = await scramProofs(
|
|
234
|
+
this.hash,
|
|
235
|
+
cred.password ?? "",
|
|
236
|
+
salt,
|
|
237
|
+
iterations,
|
|
238
|
+
authMessage
|
|
239
|
+
);
|
|
240
|
+
this.expectedServerSignature = serverSignature;
|
|
241
|
+
this.stage = "final";
|
|
242
|
+
return utf8Binary(`${withoutProof},p=${base64Encode(clientProof)}`);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
function utf8Binary(text) {
|
|
246
|
+
return bytesToBinary(utf8(text));
|
|
247
|
+
}
|
|
248
|
+
function utf8Decode(binary) {
|
|
249
|
+
return new TextDecoder().decode(binaryToBytes(binary));
|
|
250
|
+
}
|
|
251
|
+
function defaultNonce() {
|
|
252
|
+
const bytes = new Uint8Array(24);
|
|
253
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
254
|
+
return base64Encode(bytes);
|
|
255
|
+
}
|
|
256
|
+
var SCRAM_HASHES = ["SHA-256", "SHA-1"];
|
|
257
|
+
var SCRAM_NAMES = SCRAM_HASHES.map(
|
|
258
|
+
(h) => h === "SHA-1" ? "SCRAM-SHA-1" : "SCRAM-SHA-256"
|
|
259
|
+
);
|
|
260
|
+
var NS_STREAM = "http://etherx.jabber.org/streams";
|
|
261
|
+
function saslFeaturesRefusal(features) {
|
|
262
|
+
if (features.getChild("authentication", SASL2_NS)) return "sasl2-refused";
|
|
263
|
+
const sasl1 = features.getChild("mechanisms", SASL1_NS);
|
|
264
|
+
if (!sasl1) return void 0;
|
|
265
|
+
const offered = sasl1.getChildren("mechanism").map((m) => m.text().trim());
|
|
266
|
+
return SCRAM_NAMES.some((name) => offered.includes(name)) ? void 0 : "no-scram-mechanism";
|
|
267
|
+
}
|
|
268
|
+
var states = /* @__PURE__ */ new WeakMap();
|
|
269
|
+
function scramClient(options) {
|
|
270
|
+
const { username, password, ...rest } = options;
|
|
271
|
+
let current;
|
|
272
|
+
let rejectFailure = () => {
|
|
273
|
+
};
|
|
274
|
+
const state = {
|
|
275
|
+
failure: new Promise((_, reject) => {
|
|
276
|
+
rejectFailure = reject;
|
|
277
|
+
})
|
|
278
|
+
};
|
|
279
|
+
state.failure.catch(() => {
|
|
280
|
+
});
|
|
281
|
+
const userAgent = xml("user-agent", { id: globalThis.crypto.randomUUID() });
|
|
282
|
+
const cut = (entity, err) => {
|
|
283
|
+
state.cutting ??= (async () => {
|
|
284
|
+
entity.reconnect?.stop();
|
|
285
|
+
await entity.stop().catch(() => {
|
|
286
|
+
});
|
|
287
|
+
rejectFailure(err);
|
|
288
|
+
})();
|
|
289
|
+
return state.cutting;
|
|
290
|
+
};
|
|
291
|
+
let refused;
|
|
292
|
+
const xmpp = client({
|
|
293
|
+
...rest,
|
|
294
|
+
credentials: async (authenticate, mechanisms, _fast, entity) => {
|
|
295
|
+
const failClosed = async (err) => {
|
|
296
|
+
await cut(entity, err);
|
|
297
|
+
throw err;
|
|
298
|
+
};
|
|
299
|
+
if (refused) return failClosed(refused);
|
|
300
|
+
const mechanism = SCRAM_NAMES.find((name) => mechanisms.includes(name));
|
|
301
|
+
if (!mechanism) return failClosed(new ScramAuthError("no-scram-mechanism"));
|
|
302
|
+
let successData;
|
|
303
|
+
const onNonza = (el) => {
|
|
304
|
+
if (el.is("success", SASL1_NS)) successData = decodeSuccess(el.text());
|
|
305
|
+
};
|
|
306
|
+
entity.on("nonza", onNonza);
|
|
307
|
+
current = void 0;
|
|
308
|
+
try {
|
|
309
|
+
await authenticate({ username, password }, mechanism, userAgent);
|
|
310
|
+
const mech = current;
|
|
311
|
+
if (!mech) throw new ScramAuthError("out-of-order", mechanism);
|
|
312
|
+
if (!mech.verified) await mech.final(successData);
|
|
313
|
+
} catch (err) {
|
|
314
|
+
if (err instanceof ScramAuthError) return failClosed(err);
|
|
315
|
+
throw err;
|
|
316
|
+
} finally {
|
|
317
|
+
entity.removeListener("nonza", onNonza);
|
|
318
|
+
current = void 0;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
const factory = xmpp.saslFactory;
|
|
323
|
+
const bound = SCRAM_HASHES.map((hash) => ({
|
|
324
|
+
name: hash === "SHA-1" ? "SCRAM-SHA-1" : "SCRAM-SHA-256",
|
|
325
|
+
mech: class extends ScramMechanism {
|
|
326
|
+
constructor() {
|
|
327
|
+
super(hash);
|
|
328
|
+
current = this;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}));
|
|
332
|
+
factory._mechs.splice(0, factory._mechs.length, ...bound);
|
|
333
|
+
xmpp.on("nonza", (el) => {
|
|
334
|
+
if (!el.is("features", NS_STREAM)) return;
|
|
335
|
+
const reason = saslFeaturesRefusal(el);
|
|
336
|
+
if (!reason) return;
|
|
337
|
+
refused = new ScramAuthError(reason);
|
|
338
|
+
void cut(xmpp, refused);
|
|
339
|
+
});
|
|
340
|
+
states.set(xmpp, state);
|
|
341
|
+
return xmpp;
|
|
342
|
+
}
|
|
343
|
+
function decodeSuccess(text) {
|
|
344
|
+
const trimmed = text.trim();
|
|
345
|
+
if (trimmed === "" || trimmed === "=") return void 0;
|
|
346
|
+
try {
|
|
347
|
+
return globalThis.atob(trimmed);
|
|
348
|
+
} catch {
|
|
349
|
+
return void 0;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async function startScramClient(xmpp) {
|
|
353
|
+
const state = states.get(xmpp);
|
|
354
|
+
if (!state) return xmpp.start();
|
|
355
|
+
try {
|
|
356
|
+
return await Promise.race([xmpp.start(), state.failure]);
|
|
357
|
+
} catch (err) {
|
|
358
|
+
if (state.cutting) {
|
|
359
|
+
await state.cutting;
|
|
360
|
+
return state.failure;
|
|
361
|
+
}
|
|
362
|
+
throw err;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// packages/xmpp/src/muc.ts
|
|
367
|
+
import xml2 from "@xmpp/xml";
|
|
8
368
|
|
|
9
369
|
// packages/xmpp/src/jid.ts
|
|
10
370
|
var COMPONENT_JID = `policy.${XMPP_DOMAIN}`;
|
|
@@ -113,7 +473,7 @@ var MucJoinError = class extends MucError {
|
|
|
113
473
|
nick;
|
|
114
474
|
};
|
|
115
475
|
function joinPresenceEl(room, nick) {
|
|
116
|
-
return
|
|
476
|
+
return xml2("presence", { to: occupantJid(room, nick) }, xml2("x", { xmlns: NS_MUC }));
|
|
117
477
|
}
|
|
118
478
|
async function joinRoom(entity, room, nick, timeoutMs = defaultTimeoutMs()) {
|
|
119
479
|
const self = occupantJid(room, nick);
|
|
@@ -266,24 +626,24 @@ var MucOriginTracker = class {
|
|
|
266
626
|
};
|
|
267
627
|
|
|
268
628
|
// packages/xmpp/src/mam.ts
|
|
269
|
-
import
|
|
629
|
+
import xml3 from "@xmpp/xml";
|
|
270
630
|
var NS_MAM = "urn:xmpp:mam:2";
|
|
271
631
|
var NS_FORWARD2 = "urn:xmpp:forward:0";
|
|
272
632
|
var NS_RSM = "http://jabber.org/protocol/rsm";
|
|
273
633
|
var queryCounter = 0;
|
|
274
634
|
function filterField(varName, value) {
|
|
275
|
-
return
|
|
635
|
+
return xml3("field", { var: varName }, xml3("value", {}, value));
|
|
276
636
|
}
|
|
277
637
|
function mamQueryEl(options) {
|
|
278
|
-
const fields = [
|
|
638
|
+
const fields = [xml3("field", { var: "FORM_TYPE", type: "hidden" }, xml3("value", {}, NS_MAM))];
|
|
279
639
|
if (options.withJid !== void 0) fields.push(filterField("with", options.withJid));
|
|
280
640
|
if (options.start !== void 0) fields.push(filterField("start", options.start));
|
|
281
641
|
if (options.end !== void 0) fields.push(filterField("end", options.end));
|
|
282
|
-
const children = [
|
|
642
|
+
const children = [xml3("x", { xmlns: NS_DATA_FORMS, type: "submit" }, ...fields)];
|
|
283
643
|
if (options.max !== void 0) {
|
|
284
|
-
children.push(
|
|
644
|
+
children.push(xml3("set", { xmlns: NS_RSM }, xml3("max", {}, String(options.max))));
|
|
285
645
|
}
|
|
286
|
-
return
|
|
646
|
+
return xml3("query", { xmlns: NS_MAM, queryid: options.queryId }, ...children);
|
|
287
647
|
}
|
|
288
648
|
async function queryMam(entity, options, timeoutMs = defaultTimeoutMs()) {
|
|
289
649
|
const queryId = options.queryId ?? `mam${++queryCounter}`;
|
|
@@ -326,7 +686,7 @@ function forwardedStanza(forwarded) {
|
|
|
326
686
|
|
|
327
687
|
// packages/xmpp/src/roster.ts
|
|
328
688
|
import { jid as parseJid } from "@xmpp/jid";
|
|
329
|
-
import
|
|
689
|
+
import xml4 from "@xmpp/xml";
|
|
330
690
|
function subscriptionRefusal(stanza) {
|
|
331
691
|
if (!stanza.is("presence") || stanza.getAttr("type") !== "subscribe") return null;
|
|
332
692
|
const from = stanza.getAttr("from");
|
|
@@ -337,7 +697,7 @@ function subscriptionRefusal(stanza) {
|
|
|
337
697
|
} catch {
|
|
338
698
|
return null;
|
|
339
699
|
}
|
|
340
|
-
return
|
|
700
|
+
return xml4("presence", { to: bare, type: "unsubscribed" });
|
|
341
701
|
}
|
|
342
702
|
function refuseSubscriptionRequests(entity) {
|
|
343
703
|
const onStanza = (stanza) => {
|
|
@@ -356,26 +716,26 @@ var UNKNOWN_PRESENCE = Object.freeze({
|
|
|
356
716
|
});
|
|
357
717
|
|
|
358
718
|
// packages/xmpp/src/pubsub.ts
|
|
359
|
-
import
|
|
719
|
+
import xml5 from "@xmpp/xml";
|
|
360
720
|
var NS_PUBSUB = "http://jabber.org/protocol/pubsub";
|
|
361
721
|
var NS_PUBSUB_PUBLISH_OPTIONS = "http://jabber.org/protocol/pubsub#publish-options";
|
|
362
722
|
function pepPublishEl(node, itemId, payload, accessModel = "open") {
|
|
363
|
-
return
|
|
723
|
+
return xml5(
|
|
364
724
|
"pubsub",
|
|
365
725
|
{ xmlns: NS_PUBSUB },
|
|
366
|
-
|
|
367
|
-
|
|
726
|
+
xml5("publish", { node }, xml5("item", { id: itemId }, payload)),
|
|
727
|
+
xml5(
|
|
368
728
|
"publish-options",
|
|
369
729
|
{},
|
|
370
|
-
|
|
730
|
+
xml5(
|
|
371
731
|
"x",
|
|
372
732
|
{ xmlns: NS_DATA_FORMS, type: "submit" },
|
|
373
|
-
|
|
733
|
+
xml5(
|
|
374
734
|
"field",
|
|
375
735
|
{ var: "FORM_TYPE", type: "hidden" },
|
|
376
|
-
|
|
736
|
+
xml5("value", {}, NS_PUBSUB_PUBLISH_OPTIONS)
|
|
377
737
|
),
|
|
378
|
-
|
|
738
|
+
xml5("field", { var: "pubsub#access_model" }, xml5("value", {}, accessModel))
|
|
379
739
|
)
|
|
380
740
|
)
|
|
381
741
|
);
|
|
@@ -383,7 +743,7 @@ function pepPublishEl(node, itemId, payload, accessModel = "open") {
|
|
|
383
743
|
function pubsubItemsEl(node, maxItems) {
|
|
384
744
|
const attrs = { node };
|
|
385
745
|
if (maxItems !== void 0) attrs.max_items = String(maxItems);
|
|
386
|
-
return
|
|
746
|
+
return xml5("pubsub", { xmlns: NS_PUBSUB }, xml5("items", attrs));
|
|
387
747
|
}
|
|
388
748
|
async function pepPublish(entity, to, node, itemId, payload, timeoutMs = defaultTimeoutMs()) {
|
|
389
749
|
await entity.iqCaller.set(pepPublishEl(node, itemId, payload), to, timeoutMs);
|
|
@@ -408,6 +768,9 @@ function isItemNotFound(err) {
|
|
|
408
768
|
}
|
|
409
769
|
|
|
410
770
|
export {
|
|
771
|
+
ScramAuthError,
|
|
772
|
+
scramClient,
|
|
773
|
+
startScramClient,
|
|
411
774
|
defaultTimeoutMs,
|
|
412
775
|
waitForStanza,
|
|
413
776
|
MucJoinError,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Embedded from lbframe/wacando@
|
|
1
|
+
// Embedded from lbframe/wacando@40dd0c30b3653095f08994f9534fd5110e1d0925 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-
|
|
33
|
-
import "./chunks/chunk-
|
|
32
|
+
} from "./chunks/chunk-F7J3K43U.mjs";
|
|
33
|
+
import "./chunks/chunk-FFLYSYV6.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@
|
|
1
|
+
// Embedded from lbframe/wacando@40dd0c30b3653095f08994f9534fd5110e1d0925 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-
|
|
6
|
+
} from "./chunks/chunk-FUNUGIGH.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-
|
|
40
|
+
} from "./chunks/chunk-F7J3K43U.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-
|
|
46
|
+
} from "./chunks/chunk-FFLYSYV6.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:
|
|
589
|
-
* backend parses
|
|
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
|
|
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@
|
|
1
|
+
// Embedded from lbframe/wacando@40dd0c30b3653095f08994f9534fd5110e1d0925 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-
|
|
14
|
-
import "./chunks/chunk-
|
|
16
|
+
} from "./chunks/chunk-FUNUGIGH.mjs";
|
|
17
|
+
import "./chunks/chunk-FFLYSYV6.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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wacando-claude",
|
|
3
3
|
"displayName": "Wacando",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.0",
|
|
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.
|
|
4
|
+
"version": "2.4.0",
|
|
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"],
|