clawbuds 0.0.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.
@@ -0,0 +1,519 @@
1
+ // src/config.ts
2
+ import { mkdirSync, readFileSync, writeFileSync, renameSync, chmodSync } from "fs";
3
+ import { join } from "path";
4
+ import { homedir } from "os";
5
+ function getConfigDir() {
6
+ return process.env.CLAWBUDS_CONFIG_DIR || join(homedir(), ".clawbuds");
7
+ }
8
+ function ensureConfigDir() {
9
+ const dir = getConfigDir();
10
+ mkdirSync(dir, { recursive: true });
11
+ return dir;
12
+ }
13
+ function configPath() {
14
+ return join(getConfigDir(), "config.json");
15
+ }
16
+ function privateKeyPath() {
17
+ return join(getConfigDir(), "private.key");
18
+ }
19
+ function statePath() {
20
+ return join(getConfigDir(), "state.json");
21
+ }
22
+ function inboxCachePath() {
23
+ return join(getConfigDir(), "inbox.jsonl");
24
+ }
25
+ function loadConfig() {
26
+ try {
27
+ const data = readFileSync(configPath(), "utf-8");
28
+ return JSON.parse(data);
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+ function saveConfig(config) {
34
+ ensureConfigDir();
35
+ writeFileSync(configPath(), JSON.stringify(config, null, 2) + "\n");
36
+ }
37
+ function loadPrivateKey() {
38
+ try {
39
+ return readFileSync(privateKeyPath(), "utf-8").trim();
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+ function savePrivateKey(key) {
45
+ ensureConfigDir();
46
+ const path = privateKeyPath();
47
+ writeFileSync(path, key + "\n", { mode: 384 });
48
+ chmodSync(path, 384);
49
+ }
50
+ function loadState() {
51
+ try {
52
+ const data = readFileSync(statePath(), "utf-8");
53
+ return JSON.parse(data);
54
+ } catch {
55
+ return { lastSeq: 0 };
56
+ }
57
+ }
58
+ function saveState(state) {
59
+ ensureConfigDir();
60
+ const target = statePath();
61
+ const tmp = target + ".tmp";
62
+ writeFileSync(tmp, JSON.stringify(state, null, 2) + "\n");
63
+ renameSync(tmp, target);
64
+ }
65
+ function isRegistered() {
66
+ return loadConfig() !== null && loadPrivateKey() !== null;
67
+ }
68
+ function getServerUrl() {
69
+ return process.env.CLAWBUDS_SERVER || loadConfig()?.serverUrl || "https://clawbuds.com";
70
+ }
71
+
72
+ // ../shared/dist/crypto/ed25519.js
73
+ import { ed25519 } from "@noble/curves/ed25519";
74
+
75
+ // ../node_modules/@noble/hashes/esm/utils.js
76
+ function isBytes(a) {
77
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
78
+ }
79
+ function abytes(b, ...lengths) {
80
+ if (!isBytes(b))
81
+ throw new Error("Uint8Array expected");
82
+ if (lengths.length > 0 && !lengths.includes(b.length))
83
+ throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
84
+ }
85
+ function aexists(instance, checkFinished = true) {
86
+ if (instance.destroyed)
87
+ throw new Error("Hash instance has been destroyed");
88
+ if (checkFinished && instance.finished)
89
+ throw new Error("Hash#digest() has already been called");
90
+ }
91
+ function aoutput(out, instance) {
92
+ abytes(out);
93
+ const min = instance.outputLen;
94
+ if (out.length < min) {
95
+ throw new Error("digestInto() expects output buffer of length at least " + min);
96
+ }
97
+ }
98
+ function clean(...arrays) {
99
+ for (let i = 0; i < arrays.length; i++) {
100
+ arrays[i].fill(0);
101
+ }
102
+ }
103
+ function createView(arr) {
104
+ return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
105
+ }
106
+ function rotr(word, shift) {
107
+ return word << 32 - shift | word >>> shift;
108
+ }
109
+ var hasHexBuiltin = /* @__PURE__ */ (() => (
110
+ // @ts-ignore
111
+ typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
112
+ ))();
113
+ var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
114
+ function bytesToHex(bytes) {
115
+ abytes(bytes);
116
+ if (hasHexBuiltin)
117
+ return bytes.toHex();
118
+ let hex = "";
119
+ for (let i = 0; i < bytes.length; i++) {
120
+ hex += hexes[bytes[i]];
121
+ }
122
+ return hex;
123
+ }
124
+ function utf8ToBytes(str) {
125
+ if (typeof str !== "string")
126
+ throw new Error("string expected");
127
+ return new Uint8Array(new TextEncoder().encode(str));
128
+ }
129
+ function toBytes(data) {
130
+ if (typeof data === "string")
131
+ data = utf8ToBytes(data);
132
+ abytes(data);
133
+ return data;
134
+ }
135
+ var Hash = class {
136
+ };
137
+ function createHasher(hashCons) {
138
+ const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
139
+ const tmp = hashCons();
140
+ hashC.outputLen = tmp.outputLen;
141
+ hashC.blockLen = tmp.blockLen;
142
+ hashC.create = () => hashCons();
143
+ return hashC;
144
+ }
145
+
146
+ // ../node_modules/@noble/hashes/esm/_md.js
147
+ function setBigUint64(view, byteOffset, value, isLE) {
148
+ if (typeof view.setBigUint64 === "function")
149
+ return view.setBigUint64(byteOffset, value, isLE);
150
+ const _32n = BigInt(32);
151
+ const _u32_max = BigInt(4294967295);
152
+ const wh = Number(value >> _32n & _u32_max);
153
+ const wl = Number(value & _u32_max);
154
+ const h = isLE ? 4 : 0;
155
+ const l = isLE ? 0 : 4;
156
+ view.setUint32(byteOffset + h, wh, isLE);
157
+ view.setUint32(byteOffset + l, wl, isLE);
158
+ }
159
+ function Chi(a, b, c) {
160
+ return a & b ^ ~a & c;
161
+ }
162
+ function Maj(a, b, c) {
163
+ return a & b ^ a & c ^ b & c;
164
+ }
165
+ var HashMD = class extends Hash {
166
+ constructor(blockLen, outputLen, padOffset, isLE) {
167
+ super();
168
+ this.finished = false;
169
+ this.length = 0;
170
+ this.pos = 0;
171
+ this.destroyed = false;
172
+ this.blockLen = blockLen;
173
+ this.outputLen = outputLen;
174
+ this.padOffset = padOffset;
175
+ this.isLE = isLE;
176
+ this.buffer = new Uint8Array(blockLen);
177
+ this.view = createView(this.buffer);
178
+ }
179
+ update(data) {
180
+ aexists(this);
181
+ data = toBytes(data);
182
+ abytes(data);
183
+ const { view, buffer, blockLen } = this;
184
+ const len = data.length;
185
+ for (let pos = 0; pos < len; ) {
186
+ const take = Math.min(blockLen - this.pos, len - pos);
187
+ if (take === blockLen) {
188
+ const dataView = createView(data);
189
+ for (; blockLen <= len - pos; pos += blockLen)
190
+ this.process(dataView, pos);
191
+ continue;
192
+ }
193
+ buffer.set(data.subarray(pos, pos + take), this.pos);
194
+ this.pos += take;
195
+ pos += take;
196
+ if (this.pos === blockLen) {
197
+ this.process(view, 0);
198
+ this.pos = 0;
199
+ }
200
+ }
201
+ this.length += data.length;
202
+ this.roundClean();
203
+ return this;
204
+ }
205
+ digestInto(out) {
206
+ aexists(this);
207
+ aoutput(out, this);
208
+ this.finished = true;
209
+ const { buffer, view, blockLen, isLE } = this;
210
+ let { pos } = this;
211
+ buffer[pos++] = 128;
212
+ clean(this.buffer.subarray(pos));
213
+ if (this.padOffset > blockLen - pos) {
214
+ this.process(view, 0);
215
+ pos = 0;
216
+ }
217
+ for (let i = pos; i < blockLen; i++)
218
+ buffer[i] = 0;
219
+ setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
220
+ this.process(view, 0);
221
+ const oview = createView(out);
222
+ const len = this.outputLen;
223
+ if (len % 4)
224
+ throw new Error("_sha2: outputLen should be aligned to 32bit");
225
+ const outLen = len / 4;
226
+ const state = this.get();
227
+ if (outLen > state.length)
228
+ throw new Error("_sha2: outputLen bigger than state");
229
+ for (let i = 0; i < outLen; i++)
230
+ oview.setUint32(4 * i, state[i], isLE);
231
+ }
232
+ digest() {
233
+ const { buffer, outputLen } = this;
234
+ this.digestInto(buffer);
235
+ const res = buffer.slice(0, outputLen);
236
+ this.destroy();
237
+ return res;
238
+ }
239
+ _cloneInto(to) {
240
+ to || (to = new this.constructor());
241
+ to.set(...this.get());
242
+ const { blockLen, buffer, length, finished, destroyed, pos } = this;
243
+ to.destroyed = destroyed;
244
+ to.finished = finished;
245
+ to.length = length;
246
+ to.pos = pos;
247
+ if (length % blockLen)
248
+ to.buffer.set(buffer);
249
+ return to;
250
+ }
251
+ clone() {
252
+ return this._cloneInto();
253
+ }
254
+ };
255
+ var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
256
+ 1779033703,
257
+ 3144134277,
258
+ 1013904242,
259
+ 2773480762,
260
+ 1359893119,
261
+ 2600822924,
262
+ 528734635,
263
+ 1541459225
264
+ ]);
265
+
266
+ // ../node_modules/@noble/hashes/esm/sha2.js
267
+ var SHA256_K = /* @__PURE__ */ Uint32Array.from([
268
+ 1116352408,
269
+ 1899447441,
270
+ 3049323471,
271
+ 3921009573,
272
+ 961987163,
273
+ 1508970993,
274
+ 2453635748,
275
+ 2870763221,
276
+ 3624381080,
277
+ 310598401,
278
+ 607225278,
279
+ 1426881987,
280
+ 1925078388,
281
+ 2162078206,
282
+ 2614888103,
283
+ 3248222580,
284
+ 3835390401,
285
+ 4022224774,
286
+ 264347078,
287
+ 604807628,
288
+ 770255983,
289
+ 1249150122,
290
+ 1555081692,
291
+ 1996064986,
292
+ 2554220882,
293
+ 2821834349,
294
+ 2952996808,
295
+ 3210313671,
296
+ 3336571891,
297
+ 3584528711,
298
+ 113926993,
299
+ 338241895,
300
+ 666307205,
301
+ 773529912,
302
+ 1294757372,
303
+ 1396182291,
304
+ 1695183700,
305
+ 1986661051,
306
+ 2177026350,
307
+ 2456956037,
308
+ 2730485921,
309
+ 2820302411,
310
+ 3259730800,
311
+ 3345764771,
312
+ 3516065817,
313
+ 3600352804,
314
+ 4094571909,
315
+ 275423344,
316
+ 430227734,
317
+ 506948616,
318
+ 659060556,
319
+ 883997877,
320
+ 958139571,
321
+ 1322822218,
322
+ 1537002063,
323
+ 1747873779,
324
+ 1955562222,
325
+ 2024104815,
326
+ 2227730452,
327
+ 2361852424,
328
+ 2428436474,
329
+ 2756734187,
330
+ 3204031479,
331
+ 3329325298
332
+ ]);
333
+ var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
334
+ var SHA256 = class extends HashMD {
335
+ constructor(outputLen = 32) {
336
+ super(64, outputLen, 8, false);
337
+ this.A = SHA256_IV[0] | 0;
338
+ this.B = SHA256_IV[1] | 0;
339
+ this.C = SHA256_IV[2] | 0;
340
+ this.D = SHA256_IV[3] | 0;
341
+ this.E = SHA256_IV[4] | 0;
342
+ this.F = SHA256_IV[5] | 0;
343
+ this.G = SHA256_IV[6] | 0;
344
+ this.H = SHA256_IV[7] | 0;
345
+ }
346
+ get() {
347
+ const { A, B, C, D, E, F, G, H } = this;
348
+ return [A, B, C, D, E, F, G, H];
349
+ }
350
+ // prettier-ignore
351
+ set(A, B, C, D, E, F, G, H) {
352
+ this.A = A | 0;
353
+ this.B = B | 0;
354
+ this.C = C | 0;
355
+ this.D = D | 0;
356
+ this.E = E | 0;
357
+ this.F = F | 0;
358
+ this.G = G | 0;
359
+ this.H = H | 0;
360
+ }
361
+ process(view, offset) {
362
+ for (let i = 0; i < 16; i++, offset += 4)
363
+ SHA256_W[i] = view.getUint32(offset, false);
364
+ for (let i = 16; i < 64; i++) {
365
+ const W15 = SHA256_W[i - 15];
366
+ const W2 = SHA256_W[i - 2];
367
+ const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
368
+ const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
369
+ SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
370
+ }
371
+ let { A, B, C, D, E, F, G, H } = this;
372
+ for (let i = 0; i < 64; i++) {
373
+ const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
374
+ const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
375
+ const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
376
+ const T2 = sigma0 + Maj(A, B, C) | 0;
377
+ H = G;
378
+ G = F;
379
+ F = E;
380
+ E = D + T1 | 0;
381
+ D = C;
382
+ C = B;
383
+ B = A;
384
+ A = T1 + T2 | 0;
385
+ }
386
+ A = A + this.A | 0;
387
+ B = B + this.B | 0;
388
+ C = C + this.C | 0;
389
+ D = D + this.D | 0;
390
+ E = E + this.E | 0;
391
+ F = F + this.F | 0;
392
+ G = G + this.G | 0;
393
+ H = H + this.H | 0;
394
+ this.set(A, B, C, D, E, F, G, H);
395
+ }
396
+ roundClean() {
397
+ clean(SHA256_W);
398
+ }
399
+ destroy() {
400
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
401
+ clean(this.buffer);
402
+ }
403
+ };
404
+ var sha256 = /* @__PURE__ */ createHasher(() => new SHA256());
405
+
406
+ // ../node_modules/@noble/hashes/esm/sha256.js
407
+ var sha2562 = sha256;
408
+
409
+ // ../shared/dist/crypto/ed25519.js
410
+ function generateKeyPair() {
411
+ const privateKeyBytes = ed25519.utils.randomPrivateKey();
412
+ const publicKeyBytes = ed25519.getPublicKey(privateKeyBytes);
413
+ return {
414
+ publicKey: bytesToHex(publicKeyBytes),
415
+ privateKey: bytesToHex(privateKeyBytes)
416
+ };
417
+ }
418
+ function sign(message, privateKey) {
419
+ const msgBytes = new TextEncoder().encode(message);
420
+ const signature = ed25519.sign(msgBytes, privateKey);
421
+ return bytesToHex(signature);
422
+ }
423
+ function sha256hex(data) {
424
+ const bytes = new TextEncoder().encode(data);
425
+ return bytesToHex(sha2562(bytes));
426
+ }
427
+ function generateClawId(publicKey) {
428
+ const hash = sha256hex(publicKey);
429
+ return `claw_${hash.slice(0, 16)}`;
430
+ }
431
+ function buildSignMessage(method, path, timestamp, body) {
432
+ const bodyHash = sha256hex(body || "");
433
+ return `${method}|${path}|${timestamp}|${bodyHash}`;
434
+ }
435
+
436
+ // ../shared/dist/crypto/x25519.js
437
+ import { x25519 } from "@noble/curves/ed25519";
438
+ import { createHash, createCipheriv, createDecipheriv, randomBytes as randomBytes2 } from "crypto";
439
+ import { hkdf } from "crypto";
440
+ function ed25519PrivateToX25519(ed25519PrivateKey) {
441
+ const privBytes = Buffer.from(ed25519PrivateKey, "hex");
442
+ const hash = createHash("sha512").update(privBytes).digest();
443
+ hash[0] &= 248;
444
+ hash[31] &= 127;
445
+ hash[31] |= 64;
446
+ const x25519Private = hash.subarray(0, 32);
447
+ return Buffer.from(x25519Private).toString("hex");
448
+ }
449
+ function x25519GetPublicKey(x25519PrivateKey) {
450
+ const privBytes = Buffer.from(x25519PrivateKey, "hex");
451
+ const pubBytes = x25519.getPublicKey(privBytes);
452
+ return Buffer.from(pubBytes).toString("hex");
453
+ }
454
+
455
+ // ../shared/dist/types/blocks.js
456
+ import { z } from "zod";
457
+ var TextBlockSchema = z.object({
458
+ type: z.literal("text"),
459
+ text: z.string().min(1).max(1e4)
460
+ });
461
+ var LinkBlockSchema = z.object({
462
+ type: z.literal("link"),
463
+ url: z.string().url(),
464
+ preview: z.object({
465
+ title: z.string(),
466
+ description: z.string(),
467
+ image: z.string().url().optional(),
468
+ siteName: z.string().optional()
469
+ }).optional()
470
+ });
471
+ var ImageBlockSchema = z.object({
472
+ type: z.literal("image"),
473
+ url: z.string().url(),
474
+ alt: z.string().max(500).optional(),
475
+ width: z.number().int().positive().optional(),
476
+ height: z.number().int().positive().optional()
477
+ });
478
+ var CodeBlockSchema = z.object({
479
+ type: z.literal("code"),
480
+ code: z.string().min(1).max(5e4),
481
+ language: z.string().max(50).optional()
482
+ });
483
+ var PollBlockInputSchema = z.object({
484
+ type: z.literal("poll"),
485
+ question: z.string().min(1).max(500),
486
+ options: z.array(z.string().min(1).max(200)).min(2).max(10)
487
+ });
488
+ var BlockSchema = z.discriminatedUnion("type", [
489
+ TextBlockSchema,
490
+ LinkBlockSchema,
491
+ ImageBlockSchema,
492
+ CodeBlockSchema,
493
+ PollBlockInputSchema
494
+ ]);
495
+ var BlocksArraySchema = z.array(BlockSchema).min(1).max(20);
496
+
497
+ export {
498
+ generateKeyPair,
499
+ sign,
500
+ generateClawId,
501
+ buildSignMessage,
502
+ ed25519PrivateToX25519,
503
+ x25519GetPublicKey,
504
+ ensureConfigDir,
505
+ inboxCachePath,
506
+ loadConfig,
507
+ saveConfig,
508
+ loadPrivateKey,
509
+ savePrivateKey,
510
+ loadState,
511
+ saveState,
512
+ isRegistered,
513
+ getServerUrl
514
+ };
515
+ /*! Bundled license information:
516
+
517
+ @noble/hashes/esm/utils.js:
518
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
519
+ */