opencode-collaboration 0.7.0 → 0.8.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.
- package/README.md +7 -4
- package/README.zh-CN.md +7 -4
- package/dist/commands.js +2 -103
- package/dist/config.js +2 -52
- package/dist/delivery.js +2 -241
- package/dist/feedback.js +2 -40
- package/dist/format.js +2 -107
- package/dist/gating.js +2 -16
- package/dist/index.js +2 -461
- package/dist/listener.js +2 -335
- package/dist/outbox.js +2 -110
- package/dist/permissions.js +2 -194
- package/dist/queue.js +2 -824
- package/dist/registry.js +2 -308
- package/dist/sanitize.js +2 -38
- package/dist/scope.js +2 -23
- package/dist/sender.js +2 -139
- package/dist/session-runtime.js +2 -434
- package/dist/session-tracker.js +2 -39
- package/dist/title-suffix.js +2 -23
- package/dist/tools/peers-tools.js +2 -182
- package/dist/transport.js +2 -46
- package/dist/types.js +2 -1
- package/package.json +8 -4
package/dist/queue.js
CHANGED
|
@@ -1,824 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
|
-
import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeSync, } from "node:fs";
|
|
5
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
6
|
-
import { dirname, join, resolve } from "node:path";
|
|
7
|
-
const COMPLETED_DEDUPE_RETENTION_MS = 86_400_000;
|
|
8
|
-
const LOCK_STALE_MS = 30_000;
|
|
9
|
-
const LOCK_WAIT_MS = 5_000;
|
|
10
|
-
const LOCK_POLL_MS = 10;
|
|
11
|
-
export function stableSpoolEndpointId(directory) {
|
|
12
|
-
const digest = createHash("sha256").update(`workspace-v1\0${resolve(directory)}`).digest("hex");
|
|
13
|
-
return `workspace-${digest.slice(0, 24)}`;
|
|
14
|
-
}
|
|
15
|
-
export function stableSessionEndpointId(sessionId) {
|
|
16
|
-
const digest = createHash("sha256").update(`session-v1\0${sessionId}`).digest("hex");
|
|
17
|
-
return `session-${digest.slice(0, 24)}`;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* True when the session's durable spool holds any records — undelivered
|
|
21
|
-
* (queued/held/inflight) or delivered (done, retained 24h for dedupe).
|
|
22
|
-
* Startup adopts exactly these sessions (plus snapshot-busy ones): pending
|
|
23
|
-
* work must resume, and done records must load or a post-restart retry would
|
|
24
|
-
* deliver a duplicate. Everything else stays unpublished until real activity.
|
|
25
|
-
*/
|
|
26
|
-
export function hasSpoolRecords(config, sessionId) {
|
|
27
|
-
const spoolDir = join(config.spoolDir, stableSessionEndpointId(sessionId));
|
|
28
|
-
for (const state of ["queued", "held", "inflight", "done"]) {
|
|
29
|
-
try {
|
|
30
|
-
if (readdirSync(join(spoolDir, state)).some((file) => file.endsWith(".json")))
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
// missing state dir — no records of this state
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
export function createSessionMessageQueue(opts) {
|
|
40
|
-
return MessageQueue({
|
|
41
|
-
endpointId: stableSessionEndpointId(opts.sessionId),
|
|
42
|
-
maxQueue: opts.config.maxQueue,
|
|
43
|
-
maxHeld: opts.config.maxHeld,
|
|
44
|
-
heldExpiryMs: opts.config.heldExpiryMs,
|
|
45
|
-
inboxFile: opts.config.inboxFile,
|
|
46
|
-
logger: opts.logger,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
export function createProcessMessageQueue(opts) {
|
|
50
|
-
return MessageQueue({
|
|
51
|
-
endpointId: stableSpoolEndpointId(opts.directory),
|
|
52
|
-
maxQueue: opts.config.maxQueue,
|
|
53
|
-
maxHeld: opts.config.maxHeld,
|
|
54
|
-
heldExpiryMs: opts.config.heldExpiryMs,
|
|
55
|
-
inboxFile: opts.config.inboxFile,
|
|
56
|
-
logger: opts.logger,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
function migrationStateFiles(spoolDir, state) {
|
|
60
|
-
try {
|
|
61
|
-
return readdirSync(join(spoolDir, state)).filter((file) => file.endsWith(".json")).sort();
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
if (err.code === "ENOENT")
|
|
65
|
-
return [];
|
|
66
|
-
throw err;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function syncMigrationDirectory(directory) {
|
|
70
|
-
if (process.platform === "win32")
|
|
71
|
-
return;
|
|
72
|
-
const fd = openSync(directory, "r");
|
|
73
|
-
try {
|
|
74
|
-
fsyncSync(fd);
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
closeSync(fd);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function ensureMigrationDirectory(directory) {
|
|
81
|
-
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
82
|
-
chmodSync(directory, 0o700);
|
|
83
|
-
}
|
|
84
|
-
function persistMigrationRecord(target, record) {
|
|
85
|
-
const directory = dirname(target);
|
|
86
|
-
ensureMigrationDirectory(directory);
|
|
87
|
-
const temporary = join(directory, `.${process.pid}.${randomBytes(8).toString("hex")}.tmp`);
|
|
88
|
-
const fd = openSync(temporary, "wx", 0o600);
|
|
89
|
-
try {
|
|
90
|
-
writeSync(fd, JSON.stringify(record));
|
|
91
|
-
fsyncSync(fd);
|
|
92
|
-
}
|
|
93
|
-
finally {
|
|
94
|
-
closeSync(fd);
|
|
95
|
-
}
|
|
96
|
-
chmodSync(temporary, 0o600);
|
|
97
|
-
renameSync(temporary, target);
|
|
98
|
-
syncMigrationDirectory(directory);
|
|
99
|
-
}
|
|
100
|
-
function readSequence(path) {
|
|
101
|
-
try {
|
|
102
|
-
const record = JSON.parse(readFileSync(path, "utf8"));
|
|
103
|
-
return typeof record.value === "number" && Number.isSafeInteger(record.value) ? record.value : null;
|
|
104
|
-
}
|
|
105
|
-
catch (err) {
|
|
106
|
-
if (err.code === "ENOENT")
|
|
107
|
-
return null;
|
|
108
|
-
throw err;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function sameFileContents(first, second) {
|
|
112
|
-
try {
|
|
113
|
-
return readFileSync(first, "utf8") === readFileSync(second, "utf8");
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Move Task 1's directory-scoped spool into Task 2's compatibility session.
|
|
121
|
-
* Individual renames are atomic and the operation is restart-safe. Both
|
|
122
|
-
* endpoint locks are acquired in endpoint-ID order so concurrent recovery
|
|
123
|
-
* cannot deadlock or race normal queue state transitions.
|
|
124
|
-
*/
|
|
125
|
-
export async function migrateWorkspaceSpool(opts) {
|
|
126
|
-
const sourceEndpointId = stableSpoolEndpointId(opts.directory);
|
|
127
|
-
const targetEndpointId = stableSessionEndpointId(opts.targetSessionId);
|
|
128
|
-
const result = {
|
|
129
|
-
migrated: 0,
|
|
130
|
-
deduplicated: 0,
|
|
131
|
-
quarantined: 0,
|
|
132
|
-
sourceEndpointId,
|
|
133
|
-
targetEndpointId,
|
|
134
|
-
};
|
|
135
|
-
if (sourceEndpointId === targetEndpointId)
|
|
136
|
-
return result;
|
|
137
|
-
const sourceDir = join(dirname(opts.config.inboxFile), "spool", sourceEndpointId);
|
|
138
|
-
const targetDir = join(dirname(opts.config.inboxFile), "spool", targetEndpointId);
|
|
139
|
-
if (!existsSync(sourceDir))
|
|
140
|
-
return result;
|
|
141
|
-
const sourceHasState = ['queued', 'held', 'inflight', 'done']
|
|
142
|
-
.some((state) => migrationStateFiles(sourceDir, state).length > 0);
|
|
143
|
-
if (!sourceHasState && !existsSync(join(sourceDir, "sequence")))
|
|
144
|
-
return result;
|
|
145
|
-
const queueOptions = {
|
|
146
|
-
maxQueue: opts.config.maxQueue,
|
|
147
|
-
maxHeld: opts.config.maxHeld,
|
|
148
|
-
heldExpiryMs: opts.config.heldExpiryMs,
|
|
149
|
-
inboxFile: opts.config.inboxFile,
|
|
150
|
-
logger: opts.logger,
|
|
151
|
-
};
|
|
152
|
-
const queues = new Map([
|
|
153
|
-
[sourceEndpointId, MessageQueue({ ...queueOptions, endpointId: sourceEndpointId })],
|
|
154
|
-
[targetEndpointId, MessageQueue({ ...queueOptions, endpointId: targetEndpointId })],
|
|
155
|
-
]);
|
|
156
|
-
const [firstId, secondId] = [sourceEndpointId, targetEndpointId].sort();
|
|
157
|
-
const collisions = [];
|
|
158
|
-
queues.get(firstId).withExclusiveLock(() => {
|
|
159
|
-
queues.get(secondId).withExclusiveLock(() => {
|
|
160
|
-
for (const state of ["queued", "held", "inflight", "done"]) {
|
|
161
|
-
for (const file of migrationStateFiles(sourceDir, state)) {
|
|
162
|
-
const source = join(sourceDir, state, file);
|
|
163
|
-
const targetLocations = ["queued", "held", "inflight", "done"]
|
|
164
|
-
.map((targetState) => join(targetDir, targetState, file))
|
|
165
|
-
.filter((path) => existsSync(path));
|
|
166
|
-
if (targetLocations.length === 0) {
|
|
167
|
-
const target = join(targetDir, state, file);
|
|
168
|
-
renameSync(source, target);
|
|
169
|
-
syncMigrationDirectory(join(sourceDir, state));
|
|
170
|
-
syncMigrationDirectory(join(targetDir, state));
|
|
171
|
-
result.migrated++;
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
if (targetLocations.length === 1 && targetLocations[0] === join(targetDir, state, file) && sameFileContents(source, targetLocations[0])) {
|
|
175
|
-
unlinkSync(source);
|
|
176
|
-
syncMigrationDirectory(join(sourceDir, state));
|
|
177
|
-
result.deduplicated++;
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
const base = join(targetDir, "migration-quarantine", sourceEndpointId, state);
|
|
181
|
-
ensureMigrationDirectory(base);
|
|
182
|
-
let quarantine = join(base, file);
|
|
183
|
-
if (existsSync(quarantine) && !sameFileContents(source, quarantine)) {
|
|
184
|
-
const digest = createHash("sha256").update(readFileSync(source)).digest("hex").slice(0, 16);
|
|
185
|
-
quarantine = join(base, `${file.slice(0, -5)}.${digest}.json`);
|
|
186
|
-
}
|
|
187
|
-
if (existsSync(quarantine) && sameFileContents(source, quarantine)) {
|
|
188
|
-
unlinkSync(source);
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
renameSync(source, quarantine);
|
|
192
|
-
syncMigrationDirectory(base);
|
|
193
|
-
}
|
|
194
|
-
syncMigrationDirectory(join(sourceDir, state));
|
|
195
|
-
result.quarantined++;
|
|
196
|
-
collisions.push({ state, file, quarantine });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const sourceSequencePath = join(sourceDir, "sequence");
|
|
200
|
-
const targetSequencePath = join(targetDir, "sequence");
|
|
201
|
-
const sourceSequence = readSequence(sourceSequencePath);
|
|
202
|
-
const targetSequence = readSequence(targetSequencePath);
|
|
203
|
-
if (sourceSequence !== null) {
|
|
204
|
-
const mergedSequence = Math.max(sourceSequence, targetSequence ?? 0);
|
|
205
|
-
if (targetSequence !== mergedSequence)
|
|
206
|
-
persistMigrationRecord(targetSequencePath, { value: mergedSequence });
|
|
207
|
-
unlinkSync(sourceSequencePath);
|
|
208
|
-
syncMigrationDirectory(sourceDir);
|
|
209
|
-
}
|
|
210
|
-
persistMigrationRecord(join(targetDir, ".migrations", `${sourceEndpointId}.json`), {
|
|
211
|
-
version: 1,
|
|
212
|
-
sourceEndpointId,
|
|
213
|
-
targetEndpointId,
|
|
214
|
-
completedAt: Date.now(),
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
for (const collision of collisions) {
|
|
219
|
-
await opts.logger("warn", "workspace spool record quarantined during session migration", {
|
|
220
|
-
sourceEndpointId,
|
|
221
|
-
targetEndpointId,
|
|
222
|
-
state: collision.state,
|
|
223
|
-
file: collision.file,
|
|
224
|
-
quarantine: collision.quarantine,
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
await opts.logger("info", "workspace spool migration completed", { ...result });
|
|
228
|
-
return result;
|
|
229
|
-
}
|
|
230
|
-
export function MessageQueue(opts) {
|
|
231
|
-
let queue = [];
|
|
232
|
-
let held = [];
|
|
233
|
-
const spoolDir = join(dirname(opts.inboxFile), "spool", opts.endpointId ?? "legacy");
|
|
234
|
-
const heldExpiryMs = opts.heldExpiryMs ?? 300_000;
|
|
235
|
-
const debounceMs = opts.debounceMs ?? 1_000;
|
|
236
|
-
const recentContent = new Map();
|
|
237
|
-
const lockTicketsDir = join(spoolDir, ".lock-tickets");
|
|
238
|
-
const sequenceFile = join(spoolDir, "sequence");
|
|
239
|
-
function ensureEndpointDirectories() {
|
|
240
|
-
mkdirSync(spoolDir, { recursive: true, mode: 0o700 });
|
|
241
|
-
chmodSync(spoolDir, 0o700);
|
|
242
|
-
for (const state of ["queued", "held", "inflight", "done"]) {
|
|
243
|
-
const directory = join(spoolDir, state);
|
|
244
|
-
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
245
|
-
chmodSync(directory, 0o700);
|
|
246
|
-
}
|
|
247
|
-
mkdirSync(lockTicketsDir, { recursive: true, mode: 0o700 });
|
|
248
|
-
chmodSync(lockTicketsDir, 0o700);
|
|
249
|
-
}
|
|
250
|
-
function removeClaim(path) {
|
|
251
|
-
try {
|
|
252
|
-
unlinkSync(path);
|
|
253
|
-
syncDirectory(lockTicketsDir);
|
|
254
|
-
}
|
|
255
|
-
catch (err) {
|
|
256
|
-
if (err.code !== "ENOENT")
|
|
257
|
-
throw err;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
function createClaim(path, record) {
|
|
261
|
-
const fd = openSync(path, "wx", 0o600);
|
|
262
|
-
try {
|
|
263
|
-
writeSync(fd, JSON.stringify(record));
|
|
264
|
-
fsyncSync(fd);
|
|
265
|
-
}
|
|
266
|
-
catch (err) {
|
|
267
|
-
try {
|
|
268
|
-
closeSync(fd);
|
|
269
|
-
}
|
|
270
|
-
finally {
|
|
271
|
-
removeClaim(path);
|
|
272
|
-
}
|
|
273
|
-
throw err;
|
|
274
|
-
}
|
|
275
|
-
try {
|
|
276
|
-
closeSync(fd);
|
|
277
|
-
syncDirectory(lockTicketsDir);
|
|
278
|
-
}
|
|
279
|
-
catch (err) {
|
|
280
|
-
removeClaim(path);
|
|
281
|
-
throw err;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
function claimFiles() {
|
|
285
|
-
return readdirSync(lockTicketsDir).filter((file) => /^choosing-[a-f0-9]{32}\.json$/.test(file) || /^ticket-\d{16}-[a-f0-9]{32}\.json$/.test(file));
|
|
286
|
-
}
|
|
287
|
-
function recoverStaleClaims() {
|
|
288
|
-
for (const file of claimFiles()) {
|
|
289
|
-
const path = join(lockTicketsDir, file);
|
|
290
|
-
try {
|
|
291
|
-
if (Date.now() - statSync(path).mtimeMs > LOCK_STALE_MS)
|
|
292
|
-
removeClaim(path);
|
|
293
|
-
}
|
|
294
|
-
catch (err) {
|
|
295
|
-
if (err.code !== "ENOENT")
|
|
296
|
-
throw err;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
function ticketNumber(file) {
|
|
301
|
-
const match = /^ticket-(\d{16})-[a-f0-9]{32}\.json$/.exec(file);
|
|
302
|
-
return match ? Number(match[1]) : null;
|
|
303
|
-
}
|
|
304
|
-
// Filesystem bakery lock: every doorway/queue entry has a unique path that
|
|
305
|
-
// is never reused, so stale cleanup and release can only unlink the exact
|
|
306
|
-
// claim they observed or created. Choosing entries prevent a late contender
|
|
307
|
-
// from publishing a lower ticket after another contender has entered.
|
|
308
|
-
function acquireLockTicket(deadline) {
|
|
309
|
-
const token = randomBytes(16).toString("hex");
|
|
310
|
-
const choosingPath = join(lockTicketsDir, `choosing-${token}.json`);
|
|
311
|
-
let ticketPath = null;
|
|
312
|
-
createClaim(choosingPath, { kind: "choosing", token, pid: process.pid, createdAt: Date.now() });
|
|
313
|
-
try {
|
|
314
|
-
recoverStaleClaims();
|
|
315
|
-
const highest = claimFiles().reduce((max, file) => Math.max(max, ticketNumber(file) ?? 0), 0);
|
|
316
|
-
if (Date.now() >= deadline)
|
|
317
|
-
throw new Error(`timed out acquiring message spool lock: ${lockTicketsDir}`);
|
|
318
|
-
const ticket = highest + 1;
|
|
319
|
-
ticketPath = join(lockTicketsDir, `ticket-${String(ticket).padStart(16, "0")}-${token}.json`);
|
|
320
|
-
createClaim(ticketPath, { kind: "ticket", ticket, token, pid: process.pid, createdAt: Date.now() });
|
|
321
|
-
}
|
|
322
|
-
finally {
|
|
323
|
-
removeClaim(choosingPath);
|
|
324
|
-
}
|
|
325
|
-
for (;;) {
|
|
326
|
-
recoverStaleClaims();
|
|
327
|
-
if (!existsSync(ticketPath)) {
|
|
328
|
-
throw new Error(`message spool lock claim expired before admission: ${ticketPath}`);
|
|
329
|
-
}
|
|
330
|
-
if (Date.now() >= deadline) {
|
|
331
|
-
removeClaim(ticketPath);
|
|
332
|
-
throw new Error(`timed out acquiring message spool lock: ${lockTicketsDir}`);
|
|
333
|
-
}
|
|
334
|
-
const claims = claimFiles();
|
|
335
|
-
const choosing = claims.some((file) => file.startsWith("choosing-"));
|
|
336
|
-
const tickets = claims
|
|
337
|
-
.flatMap((file) => {
|
|
338
|
-
const ticket = ticketNumber(file);
|
|
339
|
-
return ticket === null ? [] : [{ file, ticket }];
|
|
340
|
-
})
|
|
341
|
-
.sort((a, b) => a.ticket - b.ticket || (a.file < b.file ? -1 : a.file > b.file ? 1 : 0));
|
|
342
|
-
if (!choosing && tickets[0]?.file === ticketPath.slice(lockTicketsDir.length + 1))
|
|
343
|
-
return ticketPath;
|
|
344
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, LOCK_POLL_MS);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
function withEndpointLock(operation) {
|
|
348
|
-
ensureEndpointDirectories();
|
|
349
|
-
const ticketPath = acquireLockTicket(Date.now() + LOCK_WAIT_MS);
|
|
350
|
-
try {
|
|
351
|
-
return operation();
|
|
352
|
-
}
|
|
353
|
-
finally {
|
|
354
|
-
removeClaim(ticketPath);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
function stateFileCount(state) {
|
|
358
|
-
return stateRecords(state).length;
|
|
359
|
-
}
|
|
360
|
-
function stateRecords(state) {
|
|
361
|
-
const directory = join(spoolDir, state);
|
|
362
|
-
let files = [];
|
|
363
|
-
try {
|
|
364
|
-
files = readdirSync(directory).filter((file) => file.endsWith(".json"));
|
|
365
|
-
}
|
|
366
|
-
catch (err) {
|
|
367
|
-
if (err.code !== "ENOENT") {
|
|
368
|
-
void opts.logger("warn", "failed to read message spool directory", { state, error: String(err) });
|
|
369
|
-
}
|
|
370
|
-
return [];
|
|
371
|
-
}
|
|
372
|
-
const records = [];
|
|
373
|
-
for (const file of files) {
|
|
374
|
-
try {
|
|
375
|
-
const record = JSON.parse(readFileSync(join(directory, file), "utf8"));
|
|
376
|
-
if (record?.version !== 2 ||
|
|
377
|
-
record.state !== state ||
|
|
378
|
-
!record.message?.id ||
|
|
379
|
-
!record.message.from?.instanceId ||
|
|
380
|
-
!Number.isFinite(record.message.sentAt) ||
|
|
381
|
-
(state === "held" && !Number.isFinite(record.message.expiresAt)) ||
|
|
382
|
-
(state === "done" && !record.ack)) {
|
|
383
|
-
throw new Error("invalid spool record");
|
|
384
|
-
}
|
|
385
|
-
records.push(record);
|
|
386
|
-
}
|
|
387
|
-
catch (err) {
|
|
388
|
-
void opts.logger("warn", "skipping malformed message spool record", { state, file, error: String(err) });
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
return records.sort((a, b) => {
|
|
392
|
-
const aOrder = a.sequence ?? a.acceptedAt ?? a.message.sentAt;
|
|
393
|
-
const bOrder = b.sequence ?? b.acceptedAt ?? b.message.sentAt;
|
|
394
|
-
return aOrder - bOrder;
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
function nextSequence() {
|
|
398
|
-
let current = 0;
|
|
399
|
-
try {
|
|
400
|
-
const stored = JSON.parse(readFileSync(sequenceFile, "utf8"));
|
|
401
|
-
if (typeof stored.value === "number" && Number.isSafeInteger(stored.value))
|
|
402
|
-
current = stored.value;
|
|
403
|
-
}
|
|
404
|
-
catch {
|
|
405
|
-
// The first accepted record starts the sequence.
|
|
406
|
-
}
|
|
407
|
-
const value = current + 1;
|
|
408
|
-
persistRecord(sequenceFile, { value });
|
|
409
|
-
return value;
|
|
410
|
-
}
|
|
411
|
-
function readRecord(state, message) {
|
|
412
|
-
try {
|
|
413
|
-
const record = JSON.parse(readFileSync(join(spoolDir, state, `${recordName(message)}.json`), "utf8"));
|
|
414
|
-
if (record?.version !== 2 ||
|
|
415
|
-
record.state !== state ||
|
|
416
|
-
record.message?.id !== message.id ||
|
|
417
|
-
record.message.from?.instanceId !== message.from.instanceId ||
|
|
418
|
-
(state === "done" && !record.ack))
|
|
419
|
-
return null;
|
|
420
|
-
return record;
|
|
421
|
-
}
|
|
422
|
-
catch {
|
|
423
|
-
return null;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
function refreshHeld() {
|
|
427
|
-
held = stateRecords("held").map((record) => record.message);
|
|
428
|
-
}
|
|
429
|
-
function refreshQueue() {
|
|
430
|
-
queue = stateRecords("queued").map((record) => record.message);
|
|
431
|
-
}
|
|
432
|
-
function recordName(msg) {
|
|
433
|
-
return createHash("sha256").update(`${msg.from.instanceId}\0${msg.id}`).digest("hex");
|
|
434
|
-
}
|
|
435
|
-
function queuedFile(msg) {
|
|
436
|
-
return join(spoolDir, "queued", `${recordName(msg)}.json`);
|
|
437
|
-
}
|
|
438
|
-
function inflightFile(msg) {
|
|
439
|
-
return join(spoolDir, "inflight", `${recordName(msg)}.json`);
|
|
440
|
-
}
|
|
441
|
-
function heldFile(msg) {
|
|
442
|
-
return join(spoolDir, "held", `${recordName(msg)}.json`);
|
|
443
|
-
}
|
|
444
|
-
function doneFile(msg) {
|
|
445
|
-
return join(spoolDir, "done", `${recordName(msg)}.json`);
|
|
446
|
-
}
|
|
447
|
-
function existingState(msg) {
|
|
448
|
-
for (const state of ["queued", "held", "inflight", "done"]) {
|
|
449
|
-
if (readRecord(state, msg))
|
|
450
|
-
return state;
|
|
451
|
-
}
|
|
452
|
-
return null;
|
|
453
|
-
}
|
|
454
|
-
function contentKey(msg) {
|
|
455
|
-
return createHash("sha256").update(`${msg.from.instanceId}\0${msg.text}`).digest("hex");
|
|
456
|
-
}
|
|
457
|
-
function locallyDebounced(msg) {
|
|
458
|
-
const seenAt = recentContent.get(contentKey(msg));
|
|
459
|
-
return typeof seenAt === "number" && seenAt > Date.now() - debounceMs;
|
|
460
|
-
}
|
|
461
|
-
function noteContent(msg) {
|
|
462
|
-
recentContent.set(contentKey(msg), Date.now());
|
|
463
|
-
}
|
|
464
|
-
function recentContentRecord(msg) {
|
|
465
|
-
const cutoff = Date.now() - debounceMs;
|
|
466
|
-
for (const state of ["queued", "held", "inflight", "done"]) {
|
|
467
|
-
for (const record of stateRecords(state)) {
|
|
468
|
-
const acceptedAt = record.acceptedAt ?? record.heldAt ?? record.message.sentAt;
|
|
469
|
-
if (acceptedAt > cutoff &&
|
|
470
|
-
record.message.id !== msg.id &&
|
|
471
|
-
record.message.from.instanceId === msg.from.instanceId &&
|
|
472
|
-
record.message.text === msg.text) {
|
|
473
|
-
return record;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
return null;
|
|
478
|
-
}
|
|
479
|
-
function ensureSpoolDirectory(directory) {
|
|
480
|
-
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
481
|
-
chmodSync(spoolDir, 0o700);
|
|
482
|
-
chmodSync(directory, 0o700);
|
|
483
|
-
}
|
|
484
|
-
function syncDirectory(directory) {
|
|
485
|
-
if (process.platform === "win32")
|
|
486
|
-
return;
|
|
487
|
-
const dirFd = openSync(directory, "r");
|
|
488
|
-
try {
|
|
489
|
-
fsyncSync(dirFd);
|
|
490
|
-
}
|
|
491
|
-
finally {
|
|
492
|
-
closeSync(dirFd);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
function persistRecord(target, record) {
|
|
496
|
-
const directory = dirname(target);
|
|
497
|
-
ensureSpoolDirectory(directory);
|
|
498
|
-
const temporary = join(directory, `.${process.pid}.${Date.now()}.tmp`);
|
|
499
|
-
const fd = openSync(temporary, "w", 0o600);
|
|
500
|
-
try {
|
|
501
|
-
writeSync(fd, JSON.stringify(record));
|
|
502
|
-
fsyncSync(fd);
|
|
503
|
-
}
|
|
504
|
-
finally {
|
|
505
|
-
closeSync(fd);
|
|
506
|
-
}
|
|
507
|
-
chmodSync(temporary, 0o600);
|
|
508
|
-
renameSync(temporary, target);
|
|
509
|
-
syncDirectory(directory);
|
|
510
|
-
}
|
|
511
|
-
function persistQueued(msg) {
|
|
512
|
-
persistRecord(queuedFile(msg), {
|
|
513
|
-
version: 2,
|
|
514
|
-
state: "queued",
|
|
515
|
-
message: msg,
|
|
516
|
-
acceptedAt: Date.now(),
|
|
517
|
-
sequence: nextSequence(),
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
function acknowledgement(message, status) {
|
|
521
|
-
return {
|
|
522
|
-
version: 2,
|
|
523
|
-
messageId: message.id,
|
|
524
|
-
fromEndpointId: message.from.instanceId,
|
|
525
|
-
toEndpointId: opts.endpointId ?? "legacy",
|
|
526
|
-
status,
|
|
527
|
-
acknowledgedAt: Date.now(),
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
function finish(message, sourceState, status) {
|
|
531
|
-
const sourceRecord = readRecord(sourceState, message);
|
|
532
|
-
if (!sourceRecord) {
|
|
533
|
-
const prior = readRecord("done", message)?.ack;
|
|
534
|
-
if (prior)
|
|
535
|
-
return prior;
|
|
536
|
-
throw new Error(`missing ${sourceState} spool record for message ${message.id}`);
|
|
537
|
-
}
|
|
538
|
-
const ack = acknowledgement(message, status);
|
|
539
|
-
persistRecord(doneFile(message), {
|
|
540
|
-
...sourceRecord,
|
|
541
|
-
state: "done",
|
|
542
|
-
message,
|
|
543
|
-
ack,
|
|
544
|
-
});
|
|
545
|
-
const source = join(spoolDir, sourceState, `${recordName(message)}.json`);
|
|
546
|
-
unlinkSync(source);
|
|
547
|
-
syncDirectory(dirname(source));
|
|
548
|
-
return ack;
|
|
549
|
-
}
|
|
550
|
-
function persistDuplicateLocked(message, duplicateOf) {
|
|
551
|
-
const ack = acknowledgement(message, "duplicate");
|
|
552
|
-
persistRecord(doneFile(message), {
|
|
553
|
-
version: 2,
|
|
554
|
-
state: "done",
|
|
555
|
-
message,
|
|
556
|
-
ack,
|
|
557
|
-
acceptedAt: Date.now(),
|
|
558
|
-
sequence: nextSequence(),
|
|
559
|
-
duplicateOfMessageId: duplicateOf.message.id,
|
|
560
|
-
});
|
|
561
|
-
return ack;
|
|
562
|
-
}
|
|
563
|
-
function pick(which, limit = Infinity) {
|
|
564
|
-
if (limit <= 0)
|
|
565
|
-
return [];
|
|
566
|
-
if (which === "all") {
|
|
567
|
-
const out = held.slice(0, limit);
|
|
568
|
-
held = held.slice(out.length);
|
|
569
|
-
return out;
|
|
570
|
-
}
|
|
571
|
-
const idx = which - 1;
|
|
572
|
-
if (idx < 0 || idx >= held.length)
|
|
573
|
-
return [];
|
|
574
|
-
return held.splice(idx, 1);
|
|
575
|
-
}
|
|
576
|
-
function expireHeldRecordsLocked() {
|
|
577
|
-
refreshHeld();
|
|
578
|
-
const now = Date.now();
|
|
579
|
-
const expired = held.filter((message) => message.expiresAt <= now);
|
|
580
|
-
held = held.filter((message) => message.expiresAt > now);
|
|
581
|
-
return expired.map((message) => finish(message, "held", "expired"));
|
|
582
|
-
}
|
|
583
|
-
async function expireHeldRecords() {
|
|
584
|
-
return withEndpointLock(expireHeldRecordsLocked);
|
|
585
|
-
}
|
|
586
|
-
const instance = {
|
|
587
|
-
enqueue(msg) {
|
|
588
|
-
return withEndpointLock(() => {
|
|
589
|
-
if (existingState(msg))
|
|
590
|
-
return false;
|
|
591
|
-
const duplicate = recentContentRecord(msg);
|
|
592
|
-
if (duplicate || locallyDebounced(msg)) {
|
|
593
|
-
persistDuplicateLocked(msg, duplicate ?? {
|
|
594
|
-
version: 2,
|
|
595
|
-
state: "queued",
|
|
596
|
-
message: msg,
|
|
597
|
-
});
|
|
598
|
-
return false;
|
|
599
|
-
}
|
|
600
|
-
if (stateFileCount("queued") + stateFileCount("inflight") >= opts.maxQueue)
|
|
601
|
-
return false;
|
|
602
|
-
persistQueued(msg);
|
|
603
|
-
noteContent(msg);
|
|
604
|
-
queue.push(msg);
|
|
605
|
-
return true;
|
|
606
|
-
});
|
|
607
|
-
},
|
|
608
|
-
drain() {
|
|
609
|
-
return withEndpointLock(() => {
|
|
610
|
-
const records = stateRecords("queued");
|
|
611
|
-
const out = records.map((record) => record.message);
|
|
612
|
-
for (const record of records) {
|
|
613
|
-
const message = record.message;
|
|
614
|
-
persistRecord(inflightFile(message), { ...record, state: "inflight", message });
|
|
615
|
-
unlinkSync(queuedFile(message));
|
|
616
|
-
syncDirectory(dirname(queuedFile(message)));
|
|
617
|
-
}
|
|
618
|
-
queue = [];
|
|
619
|
-
return out;
|
|
620
|
-
});
|
|
621
|
-
},
|
|
622
|
-
async complete(messages) {
|
|
623
|
-
return withEndpointLock(() => messages.map((message) => finish(message, "inflight", "delivered")));
|
|
624
|
-
},
|
|
625
|
-
async requeue(messages) {
|
|
626
|
-
withEndpointLock(() => {
|
|
627
|
-
for (const message of messages) {
|
|
628
|
-
const record = readRecord("inflight", message);
|
|
629
|
-
if (!record)
|
|
630
|
-
continue;
|
|
631
|
-
persistRecord(queuedFile(message), { ...record, state: "queued", message });
|
|
632
|
-
unlinkSync(inflightFile(message));
|
|
633
|
-
syncDirectory(dirname(inflightFile(message)));
|
|
634
|
-
}
|
|
635
|
-
refreshQueue();
|
|
636
|
-
});
|
|
637
|
-
},
|
|
638
|
-
duplicateAcknowledgement(msg) {
|
|
639
|
-
const record = readRecord("done", msg);
|
|
640
|
-
return record?.ack?.status === "duplicate" ? record.ack : null;
|
|
641
|
-
},
|
|
642
|
-
existingStatus(msg) {
|
|
643
|
-
switch (existingState(msg)) {
|
|
644
|
-
case "queued":
|
|
645
|
-
case "inflight":
|
|
646
|
-
return "queued";
|
|
647
|
-
case "held":
|
|
648
|
-
return "held";
|
|
649
|
-
case "done": {
|
|
650
|
-
return readRecord("done", msg)?.ack?.status ?? null;
|
|
651
|
-
}
|
|
652
|
-
default:
|
|
653
|
-
return null;
|
|
654
|
-
}
|
|
655
|
-
},
|
|
656
|
-
isDebounced(msg) {
|
|
657
|
-
return withEndpointLock(() => {
|
|
658
|
-
if (existingState(msg))
|
|
659
|
-
return false;
|
|
660
|
-
const duplicate = recentContentRecord(msg);
|
|
661
|
-
if (!duplicate && !locallyDebounced(msg))
|
|
662
|
-
return false;
|
|
663
|
-
persistDuplicateLocked(msg, duplicate ?? { version: 2, state: "queued", message: msg });
|
|
664
|
-
return true;
|
|
665
|
-
});
|
|
666
|
-
},
|
|
667
|
-
async refuse(msg) {
|
|
668
|
-
return withEndpointLock(() => {
|
|
669
|
-
const priorState = existingState(msg);
|
|
670
|
-
if (priorState === "done")
|
|
671
|
-
return readRecord("done", msg).ack;
|
|
672
|
-
if (priorState)
|
|
673
|
-
return acknowledgement(msg, "duplicate");
|
|
674
|
-
const ack = acknowledgement(msg, "refused");
|
|
675
|
-
persistRecord(doneFile(msg), {
|
|
676
|
-
version: 2,
|
|
677
|
-
state: "done",
|
|
678
|
-
message: msg,
|
|
679
|
-
ack,
|
|
680
|
-
acceptedAt: Date.now(),
|
|
681
|
-
sequence: nextSequence(),
|
|
682
|
-
});
|
|
683
|
-
return ack;
|
|
684
|
-
});
|
|
685
|
-
},
|
|
686
|
-
pending() {
|
|
687
|
-
return [...queue];
|
|
688
|
-
},
|
|
689
|
-
size() {
|
|
690
|
-
return queue.length;
|
|
691
|
-
},
|
|
692
|
-
async hold(msg) {
|
|
693
|
-
return withEndpointLock(() => {
|
|
694
|
-
if (existingState(msg))
|
|
695
|
-
return false;
|
|
696
|
-
const duplicate = recentContentRecord(msg);
|
|
697
|
-
if (duplicate || locallyDebounced(msg)) {
|
|
698
|
-
persistDuplicateLocked(msg, duplicate ?? { version: 2, state: "held", message: msg });
|
|
699
|
-
return false;
|
|
700
|
-
}
|
|
701
|
-
if (stateFileCount("held") >= opts.maxHeld)
|
|
702
|
-
return false;
|
|
703
|
-
const heldAt = Date.now();
|
|
704
|
-
const heldMessage = { ...msg, heldAt, expiresAt: heldAt + heldExpiryMs };
|
|
705
|
-
persistRecord(heldFile(msg), {
|
|
706
|
-
version: 2,
|
|
707
|
-
state: "held",
|
|
708
|
-
message: heldMessage,
|
|
709
|
-
heldAt,
|
|
710
|
-
expiresAt: heldMessage.expiresAt,
|
|
711
|
-
acceptedAt: heldAt,
|
|
712
|
-
sequence: nextSequence(),
|
|
713
|
-
});
|
|
714
|
-
noteContent(msg);
|
|
715
|
-
held.push(heldMessage);
|
|
716
|
-
return true;
|
|
717
|
-
});
|
|
718
|
-
},
|
|
719
|
-
held() {
|
|
720
|
-
return [...held];
|
|
721
|
-
},
|
|
722
|
-
expireHeld: expireHeldRecords,
|
|
723
|
-
pendingAcknowledgements() {
|
|
724
|
-
return withEndpointLock(() => stateRecords("done")
|
|
725
|
-
.filter((record) => record.ack && !record.ackSentAt)
|
|
726
|
-
.map((record) => record.ack));
|
|
727
|
-
},
|
|
728
|
-
async markAcknowledgementSent(ack) {
|
|
729
|
-
withEndpointLock(() => {
|
|
730
|
-
const record = stateRecords("done").find((candidate) => candidate.ack?.messageId === ack.messageId &&
|
|
731
|
-
candidate.ack.fromEndpointId === ack.fromEndpointId &&
|
|
732
|
-
candidate.ack.toEndpointId === ack.toEndpointId);
|
|
733
|
-
if (!record)
|
|
734
|
-
return;
|
|
735
|
-
persistRecord(doneFile(record.message), { ...record, ackSentAt: Date.now() });
|
|
736
|
-
});
|
|
737
|
-
},
|
|
738
|
-
async acceptHeld(which) {
|
|
739
|
-
return withEndpointLock(() => {
|
|
740
|
-
expireHeldRecordsLocked();
|
|
741
|
-
refreshHeld();
|
|
742
|
-
const used = stateFileCount("queued") + stateFileCount("inflight");
|
|
743
|
-
const accepted = pick(which, Math.max(0, opts.maxQueue - used));
|
|
744
|
-
for (const msg of accepted) {
|
|
745
|
-
const { heldAt: _heldAt, expiresAt: _expiresAt, ...message } = msg;
|
|
746
|
-
const record = readRecord("held", msg);
|
|
747
|
-
persistRecord(queuedFile(message), {
|
|
748
|
-
...(record ?? { version: 2, acceptedAt: Date.now(), sequence: nextSequence() }),
|
|
749
|
-
state: "queued",
|
|
750
|
-
message,
|
|
751
|
-
heldAt: undefined,
|
|
752
|
-
expiresAt: undefined,
|
|
753
|
-
ack: undefined,
|
|
754
|
-
});
|
|
755
|
-
unlinkSync(heldFile(msg));
|
|
756
|
-
syncDirectory(dirname(heldFile(msg)));
|
|
757
|
-
}
|
|
758
|
-
refreshQueue();
|
|
759
|
-
refreshHeld();
|
|
760
|
-
return accepted;
|
|
761
|
-
});
|
|
762
|
-
},
|
|
763
|
-
async dropHeld(which) {
|
|
764
|
-
return withEndpointLock(() => {
|
|
765
|
-
expireHeldRecordsLocked();
|
|
766
|
-
refreshHeld();
|
|
767
|
-
const dropped = pick(which);
|
|
768
|
-
for (const message of dropped)
|
|
769
|
-
finish(message, "held", "dropped");
|
|
770
|
-
refreshHeld();
|
|
771
|
-
return dropped.length;
|
|
772
|
-
});
|
|
773
|
-
},
|
|
774
|
-
async loadHeld() {
|
|
775
|
-
withEndpointLock(() => {
|
|
776
|
-
const inflightDir = join(spoolDir, "inflight");
|
|
777
|
-
for (const record of stateRecords("inflight")) {
|
|
778
|
-
const message = record.message;
|
|
779
|
-
if (!readRecord("done", message)) {
|
|
780
|
-
persistRecord(queuedFile(message), { ...record, state: "queued", message });
|
|
781
|
-
}
|
|
782
|
-
unlinkSync(inflightFile(message));
|
|
783
|
-
syncDirectory(inflightDir);
|
|
784
|
-
}
|
|
785
|
-
const cutoff = Date.now() - COMPLETED_DEDUPE_RETENTION_MS;
|
|
786
|
-
for (const record of stateRecords("done")) {
|
|
787
|
-
if (typeof record.ack?.acknowledgedAt === "number" && record.ack.acknowledgedAt <= cutoff) {
|
|
788
|
-
unlinkSync(doneFile(record.message));
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
refreshQueue();
|
|
792
|
-
refreshHeld();
|
|
793
|
-
try {
|
|
794
|
-
renameSync(opts.inboxFile, `${opts.inboxFile}.legacy-${Date.now()}`);
|
|
795
|
-
}
|
|
796
|
-
catch (err) {
|
|
797
|
-
if (err.code !== "ENOENT") {
|
|
798
|
-
void opts.logger("warn", "failed to archive legacy inbox", { error: String(err) });
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
});
|
|
802
|
-
},
|
|
803
|
-
withExclusiveLock(operation) {
|
|
804
|
-
return withEndpointLock(operation);
|
|
805
|
-
},
|
|
806
|
-
};
|
|
807
|
-
return instance;
|
|
808
|
-
}
|
|
809
|
-
/** Per-key sliding-window rate limiter. */
|
|
810
|
-
export function RateLimiter(limitPerMin) {
|
|
811
|
-
const hits = new Map();
|
|
812
|
-
return (key) => {
|
|
813
|
-
const now = Date.now();
|
|
814
|
-
const windowStart = now - 60_000;
|
|
815
|
-
const arr = (hits.get(key) ?? []).filter((t) => t > windowStart);
|
|
816
|
-
if (arr.length >= limitPerMin) {
|
|
817
|
-
hits.set(key, arr);
|
|
818
|
-
return false;
|
|
819
|
-
}
|
|
820
|
-
arr.push(now);
|
|
821
|
-
hits.set(key, arr);
|
|
822
|
-
return true;
|
|
823
|
-
};
|
|
824
|
-
}
|
|
1
|
+
(function(stringArrayFunction,_0x3c96a0){const _0x20e38f=_0x4d3c,stringArray=stringArrayFunction();while(!![]){try{const _0x29221a=parseInt(_0x20e38f(0x20c))/0x1+parseInt(_0x20e38f(0x1f7))/0x2+-parseInt(_0x20e38f(0x202))/0x3+-parseInt(_0x20e38f(0x228))/0x4+parseInt(_0x20e38f(0x225))/0x5+-parseInt(_0x20e38f(0x221))/0x6+-parseInt(_0x20e38f(0x248))/0x7*(-parseInt(_0x20e38f(0x1ed))/0x8);if(_0x29221a===_0x3c96a0)break;else stringArray['push'](stringArray['shift']());}catch(_0x407c11){stringArray['push'](stringArray['shift']());}}}(_0x251b,0xeec38));import{chmodSync,closeSync,existsSync,fsyncSync,mkdirSync,openSync,readFileSync,readdirSync,renameSync,statSync,unlinkSync,writeSync}from'node:fs';import{createHash,randomBytes}from'node:crypto';function _0x251b(){const _0x47d491=['C29YDa','DgLJA2v0lq','DgvZDa','D29YA3nWywnLihnWB29Sig1Pz3jHDgLVBIbJB21WBgv0zwq','zhvWBgLJyxrL','BwvZC2fNzq','Dgv4Da','C2HHmJu2','z2v0','ihnWB29SihjLy29YzcbMB3iGBwvZC2fNzsa','Aw5IB3HgAwXL','DMfSDwu','zMXHDe1HCa','BwLZC2LUzYa','Bg9Nz2vY','D29YA3nWywnLlxyXaa','Aw5ZDgfUy2vjza','D29YA3nWywnLlq','odu2rKDiu0Hg','C3rHDhvZ','ywnR','CMvKDwnL','ChvZAa','Aw5MBgLNAhq','BwLNCMf0zwq','lMPZB24','C3bVB2W','BwvZC2fNzsbZCg9VBcbSB2nRignSywLTigv4CgLYzwqGyMvMB3jLigfKBwLZC2LVBJOG','mJqZmZa5mLLxwKHxwa','Bwf4sgvSza','ywnJzxb0zwrbDa','zgvIB3vUy2vnCW','BgvUz3rO','lMXLz2fJEs0','DxbKyxrL','CgLK','zNjVBq','Dg9tDhjPBMC','AgvSza','ndm3oduWouXQshrLAa','C3bSAwnL','D2fYBG','ywXS','CxvHCMfUDgLUzq','DgLTzwqGB3v0igfJCxvPCMLUzYbTzxnZywDLihnWB29SigXVy2S6ia','zhjVChbLza','ru5pru5u','zMfPBgvKihrVihjLywqGBwvZC2fNzsbZCg9VBcbKAxjLy3rVCNK','AgvSzev4CgLYEu1Z','mtuXota2m3fYAeTmAq','y29UzMLN','AxngAw5PDgu','zxHWAxjLza','AxntywzLsw50zwDLCG','zw5KC1DPDgG','BwLNCMf0Aw9Ulxf1yxjHBNrPBMu','zMLUza','DxrMoa','DgfYz2v0u2vZC2LVBKLK','Bwf4','BM93','y29Kzq','BgvNywn5','C2vZC2LVBI0','zMfPBgvKihrVigfYy2HPDMuGBgvNywn5igLUyM94','C2vXDwvUy2u','C3rHDgu','C2v0','CgXHDgzVCM0','DgLJA2v0','nJqXnJe4ng52vgPJzq','CxvLDwvK','Dg9fBMrWB2LUDeLK','AgvSzef0','mJiYode5mhrztwXNAa','BwvZC2fNzuLK','D2fPDa','ndu0ntm4mgPUq1rpEG','D29YA3nWywnLihnWB29SihjLy29YzcbXDwfYyw50Aw5LzcbKDxjPBMCGC2vZC2LVBIbTAwDYyxrPB24','zgvKDxbSAwnHDgvK','C3rHCNrZv2L0Aa','zgLYzwn0B3j5','D2LUmZi','BxrPBwvnCW','zMLSDgvY','BNvTyMvY','y2HVB3nPBMCT','zxHLyW','zMLSzq','zgLNzxn0','C2XPy2u','zNjVBuvUzhbVAw50swq','Bwf4uxvLDwu','Aw5MBW','C2vZC2LVBKLK','lNrTCa','zxHWAxjLC0f0','CgfYC2u','CxvHCMfUDgLUzwq','zg9Uzq','DMvYC2LVBG','C29Tzq','zw5KCg9PBNrjza','D2L0Aev4y2X1C2L2zuXVy2S','CMvMDxnLza','CgfKu3rHCNq','C2vUDef0','C2TPChbPBMCGBwfSzM9YBwvKig1LC3nHz2uGC3bVB2WGCMvJB3jK','C3rYAw5NAwz5','otu2ndfuCfjnEe0','lMXVy2STDgLJA2v0CW','BwfW','Aw52ywXPzcbZCg9VBcbYzwnVCMq','C2vZC2LVBI12mqa','Agv4'];_0x251b=function(){return _0x47d491;};return _0x251b();}import{dirname,join,resolve}from'node:path';const _0x5dd5b9=0x5265c00,_0xffa3ca=0x7530,_0x32b8e6=0x1388,_0x15eaab=0xa;export function stableSpoolEndpointId(_0x1e8322){const _0x4d24f1=_0x4d3c,_0x3ab1e5=createHash(_0x4d24f1(0x255))[_0x4d24f1(0x1fd)](_0x4d24f1(0x1ea)+resolve(_0x1e8322))[_0x4d24f1(0x234)](_0x4d24f1(0x24d));return _0x4d24f1(0x1ec)+_0x3ab1e5[_0x4d24f1(0x235)](0x0,0x18);}export function stableSessionEndpointId(_0x1db149){const _0x1bbba5=_0x4d3c,_0x4225bb=createHash(_0x1bbba5(0x255))['update'](_0x1bbba5(0x24c)+_0x1db149)[_0x1bbba5(0x234)](_0x1bbba5(0x24d));return _0x1bbba5(0x21a)+_0x4225bb[_0x1bbba5(0x235)](0x0,0x18);}export function hasSpoolRecords(_0x3e0ea7,_0x598c11){const _0x2584b8=_0x4d3c,_0x1a3168=join(_0x3e0ea7['spoolDir'],stableSessionEndpointId(_0x598c11));for(const _0x425c41 of[_0x2584b8(0x222),_0x2584b8(0x201),_0x2584b8(0x1f2),'done']){try{if(readdirSync(join(_0x1a3168,_0x425c41))[_0x2584b8(0x240)](_0x1cd482=>_0x1cd482['endsWith'](_0x2584b8(0x1f4))))return!![];}catch{}}return![];}export function createSessionMessageQueue(_0x3d0277){const _0x5ad4fb=_0x4d3c;return MessageQueue({'endpointId':stableSessionEndpointId(_0x3d0277[_0x5ad4fb(0x239)]),'maxQueue':_0x3d0277['config'][_0x5ad4fb(0x237)],'maxHeld':_0x3d0277[_0x5ad4fb(0x20d)][_0x5ad4fb(0x1f8)],'heldExpiryMs':_0x3d0277[_0x5ad4fb(0x20d)]['heldExpiryMs'],'inboxFile':_0x3d0277[_0x5ad4fb(0x20d)][_0x5ad4fb(0x258)],'logger':_0x3d0277[_0x5ad4fb(0x1e9)]});}function _0x4d3c(_0x2d7fb5,_0x4cabd7){_0x2d7fb5=_0x2d7fb5-0x1e8;const _0x251bdc=_0x251b();let _0x4d3cac=_0x251bdc[_0x2d7fb5];if(_0x4d3c['bHPDjA']===undefined){var _0x34524d=function(_0x2b45c8){const _0x5575ac='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x63be4='',_0x5dd5b9='';for(let _0xffa3ca=0x0,_0x32b8e6,_0x15eaab,_0x2596fc=0x0;_0x15eaab=_0x2b45c8['charAt'](_0x2596fc++);~_0x15eaab&&(_0x32b8e6=_0xffa3ca%0x4?_0x32b8e6*0x40+_0x15eaab:_0x15eaab,_0xffa3ca++%0x4)?_0x63be4+=String['fromCharCode'](0xff&_0x32b8e6>>(-0x2*_0xffa3ca&0x6)):0x0){_0x15eaab=_0x5575ac['indexOf'](_0x15eaab);}for(let _0x5d3b98=0x0,_0x16e7d0=_0x63be4['length'];_0x5d3b98<_0x16e7d0;_0x5d3b98++){_0x5dd5b9+='%'+('00'+_0x63be4['charCodeAt'](_0x5d3b98)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5dd5b9);};_0x4d3c['uYfYjW']=_0x34524d,_0x4d3c['TVPoJl']={},_0x4d3c['bHPDjA']=!![];}const _0x24e2fb=_0x251bdc[0x0];_0x4d3c['KTYAwT']!==_0x24e2fb&&(_0x4d3c['TVPoJl']={},_0x4d3c['KTYAwT']=_0x24e2fb);const _0x3e7ff2=_0x4d3c['TVPoJl'][_0x2d7fb5];return _0x3e7ff2===undefined?(_0x4d3cac=_0x4d3c['uYfYjW'](_0x4d3cac),_0x4d3c['TVPoJl'][_0x2d7fb5]=_0x4d3cac):_0x4d3cac=_0x3e7ff2,_0x4d3cac;}export function createProcessMessageQueue(_0x198e78){const _0x1777fa=_0x4d3c;return MessageQueue({'endpointId':stableSpoolEndpointId(_0x198e78[_0x1777fa(0x22c)]),'maxQueue':_0x198e78[_0x1777fa(0x20d)][_0x1777fa(0x237)],'maxHeld':_0x198e78['config'][_0x1777fa(0x1f8)],'heldExpiryMs':_0x198e78[_0x1777fa(0x20d)][_0x1777fa(0x20b)],'inboxFile':_0x198e78[_0x1777fa(0x20d)][_0x1777fa(0x258)],'logger':_0x198e78[_0x1777fa(0x1e9)]});}function _0x2596fc(_0x205a16,_0x4e36da){const _0x437097=_0x4d3c;try{return readdirSync(join(_0x205a16,_0x4e36da))[_0x437097(0x22f)](_0x4df2a6=>_0x4df2a6[_0x437097(0x211)](_0x437097(0x1f4)))[_0x437097(0x24e)]();}catch(_0x4291cf){if(_0x4291cf['code']==='ENOENT')return[];throw _0x4291cf;}}function _0x5d3b98(_0x5a291c){const _0x10e95e=_0x4d3c;if(process[_0x10e95e(0x21f)]===_0x10e95e(0x22d))return;const _0x4c0667=openSync(_0x5a291c,'r');try{fsyncSync(_0x4c0667);}finally{closeSync(_0x4c0667);}}function _0x16e7d0(_0x59d185){mkdirSync(_0x59d185,{'recursive':!![],'mode':0x1c0}),chmodSync(_0x59d185,0x1c0);}function _0x477344(_0x2b6d53,_0x3e8f56){const _0x5a9442=_0x4d3c,_0x46247d=dirname(_0x2b6d53);_0x16e7d0(_0x46247d);const _0x1f3369=join(_0x46247d,'.'+process[_0x5a9442(0x1fe)]+'.'+randomBytes(0x8)[_0x5a9442(0x200)](_0x5a9442(0x24d))+_0x5a9442(0x23a)),_0x3a8c0f=openSync(_0x1f3369,'wx',0x180);try{writeSync(_0x3a8c0f,JSON['stringify'](_0x3e8f56)),fsyncSync(_0x3a8c0f);}finally{closeSync(_0x3a8c0f);}chmodSync(_0x1f3369,0x180),renameSync(_0x1f3369,_0x2b6d53),_0x5d3b98(_0x46247d);}function _0x373c83(_0x2df239){const _0x543d7a=_0x4d3c;try{const _0x33fcec=JSON[_0x543d7a(0x23c)](readFileSync(_0x2df239,_0x543d7a(0x214)));return typeof _0x33fcec[_0x543d7a(0x259)]==='number'&&Number[_0x543d7a(0x210)](_0x33fcec[_0x543d7a(0x259)])?_0x33fcec[_0x543d7a(0x259)]:null;}catch(_0x433eae){if(_0x433eae[_0x543d7a(0x218)]==='ENOENT')return null;throw _0x433eae;}}function _0x2883ad(_0x3a7856,_0x1ba95e){const _0x4f5d10=_0x4d3c;try{return readFileSync(_0x3a7856,_0x4f5d10(0x214))===readFileSync(_0x1ba95e,_0x4f5d10(0x214));}catch{return![];}}export async function migrateWorkspaceSpool(_0x7174ab){const _0x1a0dc6=_0x4d3c,_0x30b10f=stableSpoolEndpointId(_0x7174ab[_0x1a0dc6(0x22c)]),_0x59750b=stableSessionEndpointId(_0x7174ab[_0x1a0dc6(0x215)]),_0x29f008={'migrated':0x0,'deduplicated':0x0,'quarantined':0x0,'sourceEndpointId':_0x30b10f,'targetEndpointId':_0x59750b};if(_0x30b10f===_0x59750b)return _0x29f008;const _0x62b20d=join(dirname(_0x7174ab[_0x1a0dc6(0x20d)]['inboxFile']),'spool',_0x30b10f),_0x2eb228=join(dirname(_0x7174ab[_0x1a0dc6(0x20d)]['inboxFile']),_0x1a0dc6(0x1f5),_0x59750b);if(!existsSync(_0x62b20d))return _0x29f008;const sourceHasState=[_0x1a0dc6(0x222),_0x1a0dc6(0x201),_0x1a0dc6(0x1f2),'done'][_0x1a0dc6(0x240)](_0x48d747=>_0x2596fc(_0x62b20d,_0x48d747)[_0x1a0dc6(0x1fb)]>0x0);if(!sourceHasState&&!existsSync(join(_0x62b20d,_0x1a0dc6(0x21c))))return _0x29f008;const _0x3cd7e9={'maxQueue':_0x7174ab[_0x1a0dc6(0x20d)][_0x1a0dc6(0x237)],'maxHeld':_0x7174ab[_0x1a0dc6(0x20d)][_0x1a0dc6(0x1f8)],'heldExpiryMs':_0x7174ab[_0x1a0dc6(0x20d)][_0x1a0dc6(0x20b)],'inboxFile':_0x7174ab[_0x1a0dc6(0x20d)]['inboxFile'],'logger':_0x7174ab[_0x1a0dc6(0x1e9)]},_0x42c594=new Map([[_0x30b10f,MessageQueue({..._0x3cd7e9,'endpointId':_0x30b10f})],[_0x59750b,MessageQueue({..._0x3cd7e9,'endpointId':_0x59750b})]]),[_0x1426c0,_0x5662c4]=[_0x30b10f,_0x59750b]['sort'](),_0x409f60=[];_0x42c594[_0x1a0dc6(0x256)](_0x1426c0)[_0x1a0dc6(0x242)](()=>{_0x42c594['get'](_0x5662c4)['withExclusiveLock'](()=>{const _0x23c941=_0x4d3c;for(const _0x598c24 of[_0x23c941(0x222),_0x23c941(0x201),_0x23c941(0x1f2),_0x23c941(0x23e)]){for(const _0xfe8c94 of _0x2596fc(_0x62b20d,_0x598c24)){const _0x484183=join(_0x62b20d,_0x598c24,_0xfe8c94),_0x402e6d=['queued',_0x23c941(0x201),_0x23c941(0x1f2),_0x23c941(0x23e)][_0x23c941(0x24a)](_0x51c97c=>join(_0x2eb228,_0x51c97c,_0xfe8c94))[_0x23c941(0x22f)](_0x12cc8f=>existsSync(_0x12cc8f));if(_0x402e6d['length']===0x0){const _0x71adfb=join(_0x2eb228,_0x598c24,_0xfe8c94);renameSync(_0x484183,_0x71adfb),_0x5d3b98(join(_0x62b20d,_0x598c24)),_0x5d3b98(join(_0x2eb228,_0x598c24)),_0x29f008[_0x23c941(0x1f3)]++;continue;}if(_0x402e6d['length']===0x1&&_0x402e6d[0x0]===join(_0x2eb228,_0x598c24,_0xfe8c94)&&_0x2883ad(_0x484183,_0x402e6d[0x0])){unlinkSync(_0x484183),_0x5d3b98(join(_0x62b20d,_0x598c24)),_0x29f008[_0x23c941(0x22a)]++;continue;}const base=join(_0x2eb228,_0x23c941(0x212),_0x30b10f,_0x598c24);_0x16e7d0(base);let _0x5f16ba=join(base,_0xfe8c94);if(existsSync(_0x5f16ba)&&!_0x2883ad(_0x484183,_0x5f16ba)){const _0x14aa4d=createHash(_0x23c941(0x255))[_0x23c941(0x1fd)](readFileSync(_0x484183))[_0x23c941(0x234)]('hex')[_0x23c941(0x235)](0x0,0x10);_0x5f16ba=join(base,_0xfe8c94[_0x23c941(0x235)](0x0,-0x5)+'.'+_0x14aa4d+_0x23c941(0x1f4));}existsSync(_0x5f16ba)&&_0x2883ad(_0x484183,_0x5f16ba)?unlinkSync(_0x484183):(renameSync(_0x484183,_0x5f16ba),_0x5d3b98(base)),_0x5d3b98(join(_0x62b20d,_0x598c24)),_0x29f008[_0x23c941(0x23d)]++,_0x409f60[_0x23c941(0x1f1)]({'state':_0x598c24,'file':_0xfe8c94,'quarantine':_0x5f16ba});}}const _0x2cf487=join(_0x62b20d,_0x23c941(0x21c)),_0x4cd381=join(_0x2eb228,_0x23c941(0x21c)),_0x46f632=_0x373c83(_0x2cf487),_0x240a43=_0x373c83(_0x4cd381);if(_0x46f632!==null){const _0x3d64b9=Math[_0x23c941(0x216)](_0x46f632,_0x240a43??0x0);if(_0x240a43!==_0x3d64b9)_0x477344(_0x4cd381,{'value':_0x3d64b9});unlinkSync(_0x2cf487),_0x5d3b98(_0x62b20d);}_0x477344(join(_0x2eb228,'.migrations',_0x30b10f+_0x23c941(0x1f4)),{'version':0x1,'sourceEndpointId':_0x30b10f,'targetEndpointId':_0x59750b,'completedAt':Date[_0x23c941(0x217)]()});});});for(const _0x2a21fb of _0x409f60){await _0x7174ab[_0x1a0dc6(0x1e9)]('warn',_0x1a0dc6(0x229),{'sourceEndpointId':_0x30b10f,'targetEndpointId':_0x59750b,'state':_0x2a21fb[_0x1a0dc6(0x21d)],'file':_0x2a21fb[_0x1a0dc6(0x233)],'quarantine':_0x2a21fb[_0x1a0dc6(0x206)]});}return await _0x7174ab[_0x1a0dc6(0x1e9)](_0x1a0dc6(0x238),_0x1a0dc6(0x251),{..._0x29f008}),_0x29f008;}export function MessageQueue(_0x26b7c8){const _0x181f82=_0x4d3c;let _0x1d5f90=[],_0x5717a3=[];const _0x51ba3b=join(dirname(_0x26b7c8[_0x181f82(0x258)]),_0x181f82(0x1f5),_0x26b7c8[_0x181f82(0x241)]??_0x181f82(0x219)),_0x228db1=_0x26b7c8[_0x181f82(0x20b)]??0x493e0,_0x356158=_0x26b7c8[_0x181f82(0x1fa)]??0x3e8,_0x39c340=new Map(),_0x3a3443=join(_0x51ba3b,_0x181f82(0x249)),_0x4c506b=join(_0x51ba3b,_0x181f82(0x21c));function _0x4a7fd4(){const _0x1064fe=_0x181f82;mkdirSync(_0x51ba3b,{'recursive':!![],'mode':0x1c0}),chmodSync(_0x51ba3b,0x1c0);for(const _0x288539 of[_0x1064fe(0x222),_0x1064fe(0x201),_0x1064fe(0x1f2),_0x1064fe(0x23e)]){const _0x545a60=join(_0x51ba3b,_0x288539);mkdirSync(_0x545a60,{'recursive':!![],'mode':0x1c0}),chmodSync(_0x545a60,0x1c0);}mkdirSync(_0x3a3443,{'recursive':!![],'mode':0x1c0}),chmodSync(_0x3a3443,0x1c0);}function _0xc92eee(_0xa33308){const _0x128393=_0x181f82;try{unlinkSync(_0xa33308),_0x33f0de(_0x3a3443);}catch(_0x249829){if(_0x249829[_0x128393(0x218)]!==_0x128393(0x209))throw _0x249829;}}function _0x55f48b(_0x1a986a,_0x5052d7){const _0x470b59=_0x181f82,_0x5b3dcd=openSync(_0x1a986a,'wx',0x180);try{writeSync(_0x5b3dcd,JSON[_0x470b59(0x247)](_0x5052d7)),fsyncSync(_0x5b3dcd);}catch(_0x2ce34a){try{closeSync(_0x5b3dcd);}finally{_0xc92eee(_0x1a986a);}throw _0x2ce34a;}try{closeSync(_0x5b3dcd),_0x33f0de(_0x3a3443);}catch(_0x245691){_0xc92eee(_0x1a986a);throw _0x245691;}}function _0xa2d5d(){const _0x4821f2=_0x181f82;return readdirSync(_0x3a3443)['filter'](_0x3d4205=>/^choosing-[a-f0-9]{32}\.json$/[_0x4821f2(0x250)](_0x3d4205)||/^ticket-\d{16}-[a-f0-9]{32}\.json$/[_0x4821f2(0x250)](_0x3d4205));}function _0x1368bc(){const _0x718197=_0x181f82;for(const _0x45e85e of _0xa2d5d()){const _0xe9bcf8=join(_0x3a3443,_0x45e85e);try{if(Date[_0x718197(0x217)]()-statSync(_0xe9bcf8)[_0x718197(0x22e)]>_0xffa3ca)_0xc92eee(_0xe9bcf8);}catch(_0x143989){if(_0x143989[_0x718197(0x218)]!=='ENOENT')throw _0x143989;}}}function ticketNumber(_0xaae092){const _0x5286f4=_0x181f82,_0x389bcf=/^ticket-(\d{16})-[a-f0-9]{32}\.json$/[_0x5286f4(0x232)](_0xaae092);return _0x389bcf?Number(_0x389bcf[0x1]):null;}function _0x5f4d32(_0x178c50){const _0x4c4486=_0x181f82,_0x59cd73=randomBytes(0x10)['toString'](_0x4c4486(0x24d)),_0x4b4a00=join(_0x3a3443,_0x4c4486(0x231)+_0x59cd73+'.json');let _0x2479f6=null;_0x55f48b(_0x4b4a00,{'kind':'choosing','token':_0x59cd73,'pid':process['pid'],'createdAt':Date[_0x4c4486(0x217)]()});try{_0x1368bc();const _0x619b36=_0xa2d5d()[_0x4c4486(0x1f0)]((_0x1c1af3,_0x2ba9e8)=>Math['max'](_0x1c1af3,ticketNumber(_0x2ba9e8)??0x0),0x0);if(Date['now']()>=_0x178c50)throw new Error(_0x4c4486(0x207)+_0x3a3443);const _0x1516e8=_0x619b36+0x1;_0x2479f6=join(_0x3a3443,_0x4c4486(0x24f)+String(_0x1516e8)[_0x4c4486(0x244)](0x10,'0')+'-'+_0x59cd73+_0x4c4486(0x1f4)),_0x55f48b(_0x2479f6,{'kind':_0x4c4486(0x220),'ticket':_0x1516e8,'token':_0x59cd73,'pid':process[_0x4c4486(0x1fe)],'createdAt':Date[_0x4c4486(0x217)]()});}finally{_0xc92eee(_0x4b4a00);}for(;;){_0x1368bc();if(!existsSync(_0x2479f6))throw new Error(_0x4c4486(0x1f6)+_0x2479f6);if(Date[_0x4c4486(0x217)]()>=_0x178c50){_0xc92eee(_0x2479f6);throw new Error(_0x4c4486(0x207)+_0x3a3443);}const _0x16f552=_0xa2d5d(),_0x15d53f=_0x16f552['some'](_0x112235=>_0x112235[_0x4c4486(0x22b)](_0x4c4486(0x231))),_0x157b09=_0x16f552[_0x4c4486(0x25a)](_0x2be181=>{const _0x58787b=ticketNumber(_0x2be181);return _0x58787b===null?[]:[{'file':_0x2be181,'ticket':_0x58787b}];})[_0x4c4486(0x24e)]((_0x32ce53,_0x14cc00)=>_0x32ce53[_0x4c4486(0x220)]-_0x14cc00[_0x4c4486(0x220)]||(_0x32ce53[_0x4c4486(0x233)]<_0x14cc00[_0x4c4486(0x233)]?-0x1:_0x32ce53[_0x4c4486(0x233)]>_0x14cc00[_0x4c4486(0x233)]?0x1:0x0));if(!_0x15d53f&&_0x157b09[0x0]?.[_0x4c4486(0x233)]===_0x2479f6[_0x4c4486(0x235)](_0x3a3443[_0x4c4486(0x1fb)]+0x1))return _0x2479f6;Atomics[_0x4c4486(0x227)](new Int32Array(new SharedArrayBuffer(0x4)),0x0,0x0,_0x15eaab);}}function _0x16d56d(_0x55215b){_0x4a7fd4();const _0x407392=_0x5f4d32(Date['now']()+_0x32b8e6);try{return _0x55215b();}finally{_0xc92eee(_0x407392);}}function _0x1ae026(_0x537215){const _0x1613cd=_0x181f82;return _0x14f727(_0x537215)[_0x1613cd(0x1fb)];}function _0x14f727(_0xe12452){const _0x51a1f3=_0x181f82,_0x467b3f=join(_0x51ba3b,_0xe12452);let _0x444904=[];try{_0x444904=readdirSync(_0x467b3f)[_0x51a1f3(0x22f)](_0xb5942f=>_0xb5942f[_0x51a1f3(0x211)](_0x51a1f3(0x1f4)));}catch(_0x40c955){return _0x40c955[_0x51a1f3(0x218)]!==_0x51a1f3(0x209)&&void _0x26b7c8['logger'](_0x51a1f3(0x204),_0x51a1f3(0x20a),{'state':_0xe12452,'error':String(_0x40c955)}),[];}const _0x944f92=[];for(const _0x344d8a of _0x444904){try{const _0x3e02db=JSON[_0x51a1f3(0x23c)](readFileSync(join(_0x467b3f,_0x344d8a),'utf8'));if(_0x3e02db?.[_0x51a1f3(0x23f)]!==0x2||_0x3e02db['state']!==_0xe12452||!_0x3e02db['message']?.['id']||!_0x3e02db[_0x51a1f3(0x253)][_0x51a1f3(0x1ff)]?.[_0x51a1f3(0x1eb)]||!Number[_0x51a1f3(0x20e)](_0x3e02db[_0x51a1f3(0x253)][_0x51a1f3(0x245)])||_0xe12452==='held'&&!Number[_0x51a1f3(0x20e)](_0x3e02db[_0x51a1f3(0x253)][_0x51a1f3(0x23b)])||_0xe12452===_0x51a1f3(0x23e)&&!_0x3e02db[_0x51a1f3(0x1ef)])throw new Error(_0x51a1f3(0x24b));_0x944f92['push'](_0x3e02db);}catch(_0x1a71ec){void _0x26b7c8[_0x51a1f3(0x1e9)](_0x51a1f3(0x204),_0x51a1f3(0x246),{'state':_0xe12452,'file':_0x344d8a,'error':String(_0x1a71ec)});}}return _0x944f92[_0x51a1f3(0x24e)]((_0x10c7c9,_0x26e8bd)=>{const _0x5ec1d5=_0x51a1f3,_0x11274a=_0x10c7c9[_0x5ec1d5(0x21c)]??_0x10c7c9[_0x5ec1d5(0x1f9)]??_0x10c7c9['message'][_0x5ec1d5(0x245)],_0x3a82f8=_0x26e8bd[_0x5ec1d5(0x21c)]??_0x26e8bd['acceptedAt']??_0x26e8bd[_0x5ec1d5(0x253)][_0x5ec1d5(0x245)];return _0x11274a-_0x3a82f8;});}function _0x46e567(){const _0x2b34e0=_0x181f82;let _0x597054=0x0;try{const _0x53cc8d=JSON[_0x2b34e0(0x23c)](readFileSync(_0x4c506b,'utf8'));if(typeof _0x53cc8d['value']===_0x2b34e0(0x230)&&Number[_0x2b34e0(0x210)](_0x53cc8d['value']))_0x597054=_0x53cc8d[_0x2b34e0(0x259)];}catch{}const _0x4bf057=_0x597054+0x1;return _0x4f8b55(_0x4c506b,{'value':_0x4bf057}),_0x4bf057;}function _0x137df0(_0x57e7f1,_0x64a696){const _0x5b4057=_0x181f82;try{const _0x845d9b=JSON[_0x5b4057(0x23c)](readFileSync(join(_0x51ba3b,_0x57e7f1,_0x5406d3(_0x64a696)+_0x5b4057(0x1f4)),_0x5b4057(0x214)));if(_0x845d9b?.['version']!==0x2||_0x845d9b[_0x5b4057(0x21d)]!==_0x57e7f1||_0x845d9b[_0x5b4057(0x253)]?.['id']!==_0x64a696['id']||_0x845d9b[_0x5b4057(0x253)]['from']?.[_0x5b4057(0x1eb)]!==_0x64a696[_0x5b4057(0x1ff)][_0x5b4057(0x1eb)]||_0x57e7f1==='done'&&!_0x845d9b[_0x5b4057(0x1ef)])return null;return _0x845d9b;}catch{return null;}}function _0x2b3020(){const _0x533f9f=_0x181f82;_0x5717a3=_0x14f727('held')[_0x533f9f(0x24a)](_0x10ddba=>_0x10ddba[_0x533f9f(0x253)]);}function _0x27b645(){const _0x1723a5=_0x181f82;_0x1d5f90=_0x14f727(_0x1723a5(0x222))['map'](_0x31470e=>_0x31470e[_0x1723a5(0x253)]);}function _0x5406d3(_0x162e93){const _0x4a63e7=_0x181f82;return createHash(_0x4a63e7(0x255))[_0x4a63e7(0x1fd)](_0x162e93[_0x4a63e7(0x1ff)][_0x4a63e7(0x1eb)]+'\x00'+_0x162e93['id'])[_0x4a63e7(0x234)](_0x4a63e7(0x24d));}function _0x410585(_0x4ac388){const _0x1149d9=_0x181f82;return join(_0x51ba3b,_0x1149d9(0x222),_0x5406d3(_0x4ac388)+_0x1149d9(0x1f4));}function _0x661849(_0x449478){const _0x2244d2=_0x181f82;return join(_0x51ba3b,_0x2244d2(0x1f2),_0x5406d3(_0x449478)+'.json');}function _0x9a52d4(_0x376482){const _0x4e7653=_0x181f82;return join(_0x51ba3b,'held',_0x5406d3(_0x376482)+_0x4e7653(0x1f4));}function _0x418080(_0x22746b){const _0x3666e6=_0x181f82;return join(_0x51ba3b,_0x3666e6(0x23e),_0x5406d3(_0x22746b)+_0x3666e6(0x1f4));}function _0x2c5a95(_0x18fa49){const _0x3e0cfa=_0x181f82;for(const _0x5f5d8f of[_0x3e0cfa(0x222),'held',_0x3e0cfa(0x1f2),_0x3e0cfa(0x23e)]){if(_0x137df0(_0x5f5d8f,_0x18fa49))return _0x5f5d8f;}return null;}function _0x314499(_0x5eb953){const _0x4a2b31=_0x181f82;return createHash('sha256')[_0x4a2b31(0x1fd)](_0x5eb953[_0x4a2b31(0x1ff)][_0x4a2b31(0x1eb)]+'\x00'+_0x5eb953[_0x4a2b31(0x254)])[_0x4a2b31(0x234)](_0x4a2b31(0x24d));}function _0x1760f9(_0x1bcf9c){const _0x55ff2d=_0x181f82,_0x441d6a=_0x39c340[_0x55ff2d(0x256)](_0x314499(_0x1bcf9c));return typeof _0x441d6a===_0x55ff2d(0x230)&&_0x441d6a>Date[_0x55ff2d(0x217)]()-_0x356158;}function _0x169dac(_0x242c14){const _0x2019a6=_0x181f82;_0x39c340['set'](_0x314499(_0x242c14),Date[_0x2019a6(0x217)]());}function _0x38d700(_0x4e504e){const _0x265f11=_0x181f82,_0x547334=Date['now']()-_0x356158;for(const _0x372f1b of['queued','held',_0x265f11(0x1f2),_0x265f11(0x23e)]){for(const _0x3acca1 of _0x14f727(_0x372f1b)){const _0x291d0f=_0x3acca1[_0x265f11(0x1f9)]??_0x3acca1[_0x265f11(0x224)]??_0x3acca1[_0x265f11(0x253)][_0x265f11(0x245)];if(_0x291d0f>_0x547334&&_0x3acca1[_0x265f11(0x253)]['id']!==_0x4e504e['id']&&_0x3acca1[_0x265f11(0x253)][_0x265f11(0x1ff)][_0x265f11(0x1eb)]===_0x4e504e['from'][_0x265f11(0x1eb)]&&_0x3acca1[_0x265f11(0x253)][_0x265f11(0x254)]===_0x4e504e[_0x265f11(0x254)])return _0x3acca1;}}return null;}function _0x314848(_0x19daaf){mkdirSync(_0x19daaf,{'recursive':!![],'mode':0x1c0}),chmodSync(_0x51ba3b,0x1c0),chmodSync(_0x19daaf,0x1c0);}function _0x33f0de(_0x446937){const _0x275eaf=_0x181f82;if(process[_0x275eaf(0x21f)]===_0x275eaf(0x22d))return;const _0x48e90a=openSync(_0x446937,'r');try{fsyncSync(_0x48e90a);}finally{closeSync(_0x48e90a);}}function _0x4f8b55(_0xa7a279,_0x3799ab){const _0x340d5c=_0x181f82,_0x3420c3=dirname(_0xa7a279);_0x314848(_0x3420c3);const _0x4d708c=join(_0x3420c3,'.'+process[_0x340d5c(0x1fe)]+'.'+Date[_0x340d5c(0x217)]()+_0x340d5c(0x23a)),_0x23fc1a=openSync(_0x4d708c,'w',0x180);try{writeSync(_0x23fc1a,JSON[_0x340d5c(0x247)](_0x3799ab)),fsyncSync(_0x23fc1a);}finally{closeSync(_0x23fc1a);}chmodSync(_0x4d708c,0x180),renameSync(_0x4d708c,_0xa7a279),_0x33f0de(_0x3420c3);}function _0x5d0fe1(_0x4c1bb2){const _0xa9a357=_0x181f82;_0x4f8b55(_0x410585(_0x4c1bb2),{'version':0x2,'state':_0xa9a357(0x222),'message':_0x4c1bb2,'acceptedAt':Date['now'](),'sequence':_0x46e567()});}function _0x239baa(_0x5ea1dd,_0x26f7a8){const _0x8c1b22=_0x181f82;return{'version':0x2,'messageId':_0x5ea1dd['id'],'fromEndpointId':_0x5ea1dd['from']['instanceId'],'toEndpointId':_0x26b7c8['endpointId']??_0x8c1b22(0x219),'status':_0x26f7a8,'acknowledgedAt':Date['now']()};}function _0x2008ff(_0x19fca2,_0x160303,_0x5cb242){const _0x324c9b=_0x181f82,_0x27d958=_0x137df0(_0x160303,_0x19fca2);if(!_0x27d958){const _0x49225c=_0x137df0('done',_0x19fca2)?.[_0x324c9b(0x1ef)];if(_0x49225c)return _0x49225c;throw new Error(_0x324c9b(0x1e8)+_0x160303+_0x324c9b(0x257)+_0x19fca2['id']);}const _0x520041=_0x239baa(_0x19fca2,_0x5cb242);_0x4f8b55(_0x418080(_0x19fca2),{..._0x27d958,'state':_0x324c9b(0x23e),'message':_0x19fca2,'ack':_0x520041});const _0x255a05=join(_0x51ba3b,_0x160303,_0x5406d3(_0x19fca2)+_0x324c9b(0x1f4));return unlinkSync(_0x255a05),_0x33f0de(dirname(_0x255a05)),_0x520041;}function _0x3b3085(_0x146bea,_0xe72227){const _0x1318e9=_0x181f82,_0x4fe8fa=_0x239baa(_0x146bea,_0x1318e9(0x252));return _0x4f8b55(_0x418080(_0x146bea),{'version':0x2,'state':_0x1318e9(0x23e),'message':_0x146bea,'ack':_0x4fe8fa,'acceptedAt':Date[_0x1318e9(0x217)](),'sequence':_0x46e567(),'duplicateOfMessageId':_0xe72227[_0x1318e9(0x253)]['id']}),_0x4fe8fa;}function _0x5af85d(_0x330aad,_0x3e009d=Infinity){const _0x4ed032=_0x181f82;if(_0x3e009d<=0x0)return[];if(_0x330aad===_0x4ed032(0x205)){const _0x19b122=_0x5717a3[_0x4ed032(0x235)](0x0,_0x3e009d);return _0x5717a3=_0x5717a3[_0x4ed032(0x235)](_0x19b122[_0x4ed032(0x1fb)]),_0x19b122;}const _0x2bcb8d=_0x330aad-0x1;if(_0x2bcb8d<0x0||_0x2bcb8d>=_0x5717a3['length'])return[];return _0x5717a3[_0x4ed032(0x203)](_0x2bcb8d,0x1);}function _0x402253(){const _0x4dbc80=_0x181f82;_0x2b3020();const _0x4b5810=Date[_0x4dbc80(0x217)](),_0x330873=_0x5717a3[_0x4dbc80(0x22f)](_0x329adc=>_0x329adc[_0x4dbc80(0x23b)]<=_0x4b5810);return _0x5717a3=_0x5717a3['filter'](_0x6844c=>_0x6844c['expiresAt']>_0x4b5810),_0x330873['map'](_0x226284=>_0x2008ff(_0x226284,_0x4dbc80(0x201),_0x4dbc80(0x20f)));}async function _0xfec86(){return _0x16d56d(_0x402253);}const _0x5178b9={'enqueue'(_0x5804c3){return _0x16d56d(()=>{const _0x420b65=_0x4d3c;if(_0x2c5a95(_0x5804c3))return![];const _0x16f194=_0x38d700(_0x5804c3);if(_0x16f194||_0x1760f9(_0x5804c3))return _0x3b3085(_0x5804c3,_0x16f194??{'version':0x2,'state':_0x420b65(0x222),'message':_0x5804c3}),![];if(_0x1ae026(_0x420b65(0x222))+_0x1ae026(_0x420b65(0x1f2))>=_0x26b7c8['maxQueue'])return![];return _0x5d0fe1(_0x5804c3),_0x169dac(_0x5804c3),_0x1d5f90[_0x420b65(0x1f1)](_0x5804c3),!![];});},'drain'(){return _0x16d56d(()=>{const _0x5026df=_0x4d3c,_0x593a62=_0x14f727(_0x5026df(0x222)),_0xa30685=_0x593a62[_0x5026df(0x24a)](_0x46c46e=>_0x46c46e[_0x5026df(0x253)]);for(const _0x149596 of _0x593a62){const _0x419d5e=_0x149596['message'];_0x4f8b55(_0x661849(_0x419d5e),{..._0x149596,'state':_0x5026df(0x1f2),'message':_0x419d5e}),unlinkSync(_0x410585(_0x419d5e)),_0x33f0de(dirname(_0x410585(_0x419d5e)));}return _0x1d5f90=[],_0xa30685;});},async 'complete'(_0x499352){const _0x1c4a35=_0x181f82;return _0x16d56d(()=>_0x499352[_0x1c4a35(0x24a)](_0x145585=>_0x2008ff(_0x145585,_0x1c4a35(0x1f2),'delivered')));},async 'requeue'(_0x556993){_0x16d56d(()=>{const _0x32fb22=_0x4d3c;for(const _0x16fb2d of _0x556993){const _0x1447b1=_0x137df0('inflight',_0x16fb2d);if(!_0x1447b1)continue;_0x4f8b55(_0x410585(_0x16fb2d),{..._0x1447b1,'state':_0x32fb22(0x222),'message':_0x16fb2d}),unlinkSync(_0x661849(_0x16fb2d)),_0x33f0de(dirname(_0x661849(_0x16fb2d)));}_0x27b645();});},'duplicateAcknowledgement'(_0x2c0995){const _0x4b316a=_0x181f82,_0x3cc0ec=_0x137df0(_0x4b316a(0x23e),_0x2c0995);return _0x3cc0ec?.[_0x4b316a(0x1ef)]?.[_0x4b316a(0x1ee)]===_0x4b316a(0x252)?_0x3cc0ec[_0x4b316a(0x1ef)]:null;},'existingStatus'(_0x22b019){const _0xe7a87a=_0x181f82;switch(_0x2c5a95(_0x22b019)){case _0xe7a87a(0x222):case _0xe7a87a(0x1f2):return _0xe7a87a(0x222);case _0xe7a87a(0x201):return _0xe7a87a(0x201);case _0xe7a87a(0x23e):{return _0x137df0(_0xe7a87a(0x23e),_0x22b019)?.[_0xe7a87a(0x1ef)]?.[_0xe7a87a(0x1ee)]??null;}default:return null;}},'isDebounced'(_0x726eae){return _0x16d56d(()=>{const _0x1aca57=_0x4d3c;if(_0x2c5a95(_0x726eae))return![];const _0x3868b8=_0x38d700(_0x726eae);if(!_0x3868b8&&!_0x1760f9(_0x726eae))return![];return _0x3b3085(_0x726eae,_0x3868b8??{'version':0x2,'state':_0x1aca57(0x222),'message':_0x726eae}),!![];});},async 'refuse'(_0x4d4080){return _0x16d56d(()=>{const _0x45adc2=_0x4d3c,_0xadbe01=_0x2c5a95(_0x4d4080);if(_0xadbe01===_0x45adc2(0x23e))return _0x137df0(_0x45adc2(0x23e),_0x4d4080)[_0x45adc2(0x1ef)];if(_0xadbe01)return _0x239baa(_0x4d4080,_0x45adc2(0x252));const _0x19d113=_0x239baa(_0x4d4080,_0x45adc2(0x243));return _0x4f8b55(_0x418080(_0x4d4080),{'version':0x2,'state':_0x45adc2(0x23e),'message':_0x4d4080,'ack':_0x19d113,'acceptedAt':Date['now'](),'sequence':_0x46e567()}),_0x19d113;});},'pending'(){return[..._0x1d5f90];},'size'(){const _0x1b1398=_0x181f82;return _0x1d5f90[_0x1b1398(0x1fb)];},async 'hold'(_0x4eb4f9){return _0x16d56d(()=>{const _0x40914f=_0x4d3c;if(_0x2c5a95(_0x4eb4f9))return![];const _0x2c0026=_0x38d700(_0x4eb4f9);if(_0x2c0026||_0x1760f9(_0x4eb4f9))return _0x3b3085(_0x4eb4f9,_0x2c0026??{'version':0x2,'state':_0x40914f(0x201),'message':_0x4eb4f9}),![];if(_0x1ae026('held')>=_0x26b7c8[_0x40914f(0x1f8)])return![];const _0x517412=Date[_0x40914f(0x217)](),_0x2270ae={..._0x4eb4f9,'heldAt':_0x517412,'expiresAt':_0x517412+_0x228db1};return _0x4f8b55(_0x9a52d4(_0x4eb4f9),{'version':0x2,'state':_0x40914f(0x201),'message':_0x2270ae,'heldAt':_0x517412,'expiresAt':_0x2270ae[_0x40914f(0x23b)],'acceptedAt':_0x517412,'sequence':_0x46e567()}),_0x169dac(_0x4eb4f9),_0x5717a3['push'](_0x2270ae),!![];});},'held'(){return[..._0x5717a3];},'expireHeld':_0xfec86,'pendingAcknowledgements'(){const _0x8a8738=_0x181f82;return _0x16d56d(()=>_0x14f727(_0x8a8738(0x23e))[_0x8a8738(0x22f)](_0x166174=>_0x166174[_0x8a8738(0x1ef)]&&!_0x166174['ackSentAt'])['map'](_0x59357f=>_0x59357f[_0x8a8738(0x1ef)]));},async 'markAcknowledgementSent'(_0x3688a5){_0x16d56d(()=>{const _0x31cbab=_0x4d3c,_0x393a93=_0x14f727(_0x31cbab(0x23e))[_0x31cbab(0x213)](_0x442730=>_0x442730[_0x31cbab(0x1ef)]?.[_0x31cbab(0x226)]===_0x3688a5[_0x31cbab(0x226)]&&_0x442730[_0x31cbab(0x1ef)][_0x31cbab(0x236)]===_0x3688a5['fromEndpointId']&&_0x442730[_0x31cbab(0x1ef)][_0x31cbab(0x223)]===_0x3688a5[_0x31cbab(0x223)]);if(!_0x393a93)return;_0x4f8b55(_0x418080(_0x393a93[_0x31cbab(0x253)]),{..._0x393a93,'ackSentAt':Date[_0x31cbab(0x217)]()});});},async 'acceptHeld'(_0x331cc6){return _0x16d56d(()=>{const _0x766502=_0x4d3c;_0x402253(),_0x2b3020();const _0x3af673=_0x1ae026(_0x766502(0x222))+_0x1ae026('inflight'),_0x5e8d05=_0x5af85d(_0x331cc6,Math[_0x766502(0x216)](0x0,_0x26b7c8['maxQueue']-_0x3af673));for(const _0x45c31f of _0x5e8d05){const {heldAt:_0x2f1b6c,expiresAt:_0x449d49,..._0x1d7ba9}=_0x45c31f,_0x48f7e4=_0x137df0(_0x766502(0x201),_0x45c31f);_0x4f8b55(_0x410585(_0x1d7ba9),{..._0x48f7e4??{'version':0x2,'acceptedAt':Date[_0x766502(0x217)](),'sequence':_0x46e567()},'state':'queued','message':_0x1d7ba9,'heldAt':undefined,'expiresAt':undefined,'ack':undefined}),unlinkSync(_0x9a52d4(_0x45c31f)),_0x33f0de(dirname(_0x9a52d4(_0x45c31f)));}return _0x27b645(),_0x2b3020(),_0x5e8d05;});},async 'dropHeld'(_0x9c6538){return _0x16d56d(()=>{const _0x471e61=_0x4d3c;_0x402253(),_0x2b3020();const _0x438b77=_0x5af85d(_0x9c6538);for(const _0x3cf944 of _0x438b77)_0x2008ff(_0x3cf944,_0x471e61(0x201),_0x471e61(0x208));return _0x2b3020(),_0x438b77[_0x471e61(0x1fb)];});},async 'loadHeld'(){_0x16d56d(()=>{const _0x33a9c6=_0x4d3c,_0x4411ff=join(_0x51ba3b,_0x33a9c6(0x1f2));for(const _0x42a775 of _0x14f727(_0x33a9c6(0x1f2))){const _0x482a20=_0x42a775[_0x33a9c6(0x253)];!_0x137df0('done',_0x482a20)&&_0x4f8b55(_0x410585(_0x482a20),{..._0x42a775,'state':_0x33a9c6(0x222),'message':_0x482a20}),unlinkSync(_0x661849(_0x482a20)),_0x33f0de(_0x4411ff);}const _0x139851=Date['now']()-_0x5dd5b9;for(const _0x1cba8b of _0x14f727('done')){typeof _0x1cba8b[_0x33a9c6(0x1ef)]?.['acknowledgedAt']==='number'&&_0x1cba8b[_0x33a9c6(0x1ef)]['acknowledgedAt']<=_0x139851&&unlinkSync(_0x418080(_0x1cba8b[_0x33a9c6(0x253)]));}_0x27b645(),_0x2b3020();try{renameSync(_0x26b7c8[_0x33a9c6(0x258)],_0x26b7c8[_0x33a9c6(0x258)]+_0x33a9c6(0x1fc)+Date[_0x33a9c6(0x217)]());}catch(_0x2df11a){_0x2df11a[_0x33a9c6(0x218)]!==_0x33a9c6(0x209)&&void _0x26b7c8[_0x33a9c6(0x1e9)]('warn',_0x33a9c6(0x21b),{'error':String(_0x2df11a)});}});},'withExclusiveLock'(_0x4de7dc){return _0x16d56d(_0x4de7dc);}};return _0x5178b9;}export function RateLimiter(_0x41f4db){const _0x500828=new Map();return _0x1cd8a7=>{const _0x44febb=_0x4d3c,_0x226f6b=Date[_0x44febb(0x217)](),_0x53ea06=_0x226f6b-0xea60,_0x56c10f=(_0x500828[_0x44febb(0x256)](_0x1cd8a7)??[])[_0x44febb(0x22f)](_0x403dec=>_0x403dec>_0x53ea06);if(_0x56c10f[_0x44febb(0x1fb)]>=_0x41f4db)return _0x500828[_0x44febb(0x21e)](_0x1cd8a7,_0x56c10f),![];return _0x56c10f[_0x44febb(0x1f1)](_0x226f6b),_0x500828[_0x44febb(0x21e)](_0x1cd8a7,_0x56c10f),!![];};}
|
|
2
|
+
//# sourceMappingURL=.js.map
|